From abc66e87955f65556b1748ddcd851e56964e0814 Mon Sep 17 00:00:00 2001 From: Shaquu Date: Fri, 21 Nov 2025 23:55:09 +0100 Subject: [PATCH 01/14] Updated hap-nodejs to 2.0.2 and added support for Node 24 (removing for 18) --- .github/workflows/tests.yml | 2 +- CHANGELOG.md | 22 +- package-lock.json | 1245 ++++++++++++++++++++--------------- package.json | 28 +- 4 files changed, 758 insertions(+), 539 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 3360dfb1..b0b3d55b 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -7,7 +7,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - node_version: [ 18, 20, 22 ] + node_version: [ 20, 22, 24 ] os: [ ubuntu-latest, windows-latest, macOS-latest ] steps: - uses: actions/checkout@v4 diff --git a/CHANGELOG.md b/CHANGELOG.md index cfdec49b..02807147 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,11 +9,22 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [1.8.0] - 2025-11-21 + +### Changed + +- Updated hap-nodejs [0.12.3 to 2.0.2](https://github.com/homebridge/HAP-NodeJS/blob/latest/CHANGELOG.md) (features + and bug fixes) +- Dependencies upgrade +- Node `18` no longer supported, use Node + 24 [#578](https://github.com/NRCHKB/node-red-contrib-homekit-bridged/issues/578)! Or at least 20. + ## [1.7.3] - 2025-01-16 ### Changed -- Updated hap-nodejs [0.12.3-beta.18 to 0.12.3](https://github.com/homebridge/HAP-NodeJS/blob/latest/CHANGELOG.md) (features +- Updated hap-nodejs [0.12.3-beta.18 to 0.12.3](https://github.com/homebridge/HAP-NodeJS/blob/latest/CHANGELOG.md) ( + features and bug fixes) - Dependencies upgrade @@ -31,7 +42,8 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ### Fixed -- Fix bad listeners detachment for characteristics [#563](https://github.com/NRCHKB/node-red-contrib-homekit-bridged/issues/563) +- Fix bad listeners detachment for + characteristics [#563](https://github.com/NRCHKB/node-red-contrib-homekit-bridged/issues/563) ## [1.7.0] - 2024-09-19 @@ -43,11 +55,13 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ### Added - Adaptive Lighting support [#335](https://github.com/NRCHKB/node-red-contrib-homekit-bridged/issues/335) -- By default, registered Eve.app Characteristics for power management - for existing setup, requires old custom characteristics file to be removed +- By default, registered Eve.app Characteristics for power management - for existing setup, requires old custom + characteristics file to be removed ### Changed -- Updated hap-nodejs [0.11.1 to 0.12.3-beta.18](https://github.com/homebridge/HAP-NodeJS/blob/latest/CHANGELOG.md) (features +- Updated hap-nodejs [0.11.1 to 0.12.3-beta.18](https://github.com/homebridge/HAP-NodeJS/blob/latest/CHANGELOG.md) ( + features and bug fixes) - Dependencies upgrade - Node `10`, `12` and `16` no longer supported, use Node 20! Or at least 18 diff --git a/package-lock.json b/package-lock.json index 4a1cfdca..03768841 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,29 +1,29 @@ { "name": "node-red-contrib-homekit-bridged", - "version": "1.7.3", + "version": "1.8.0-dev.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "node-red-contrib-homekit-bridged", - "version": "1.7.3", + "version": "1.8.0-dev.0", "license": "Apache-2.0", "dependencies": { + "@homebridge/hap-nodejs": "2.0.2", "@nrchkb/logger": "~3.1.1", - "hap-nodejs": "0.12.3", "node-persist": "^3.1.3", - "semver": "~7.6.3", + "semver": "~7.7.3", "uuid": "~11.0.5" }, "devDependencies": { - "@homebridge/ciao": "~1.3.1", - "@node-red/registry": "^4.0.8", + "@homebridge/ciao": "~1.3.4", + "@node-red/registry": "^4.1.1", "@types/mocha": "^10.0.10", - "@types/node": "^18", + "@types/node": "^20", "@types/node-persist": "^3.1.8", "@types/node-red": "^1.3.5", - "@types/node-red-node-test-helper": "^0.3.4", - "@types/semver": "^7.5.8", + "@types/node-red-node-test-helper": "^0.3.5", + "@types/semver": "^7.7.1", "@types/uuid": "^10.0.0", "@typescript-eslint/eslint-plugin": "^7.16.0", "@typescript-eslint/parser": "^7.16.0", @@ -31,18 +31,18 @@ "del-cli": "^5.1.0", "eslint": "^8", "eslint-config-prettier": "^9.1.0", - "eslint-plugin-prettier": "^5.1.3", + "eslint-plugin-prettier": "^5.5.4", "eslint-plugin-simple-import-sort": "^12.1.1", - "husky": "^9.0.11", + "husky": "^9.1.7", "mocha": "^10.6.0", - "node-red": "^4.0.8", - "node-red-node-test-helper": "^0.3.4", - "prettier": "^3.4.2", + "node-red": "^4.1.1", + "node-red-node-test-helper": "^0.3.5", + "prettier": "^3.6.2", "ts-node": "^10.9.2", "typescript": "^5.7.3" }, "engines": { - "node": ">=18" + "node": "^20 || ^22 || ^24" } }, "node_modules/@aashutoshrathi/word-wrap": { @@ -173,14 +173,11 @@ } }, "node_modules/@babel/runtime": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.0.tgz", - "integrity": "sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw==", + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.4.tgz", + "integrity": "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==", "dev": true, "license": "MIT", - "dependencies": { - "regenerator-runtime": "^0.14.0" - }, "engines": { "node": ">=6.9.0" } @@ -257,21 +254,21 @@ } }, "node_modules/@emnapi/core": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.2.0.tgz", - "integrity": "sha512-E7Vgw78I93we4ZWdYCb4DGAwRROGkMIXk7/y87UmANR+J6qsWusmC3gLt0H+O0KOt5e6O38U8oJamgbudrES/w==", + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.7.1.tgz", + "integrity": "sha512-o1uhUASyo921r2XtHYOHy7gdkGLge8ghBEQHMWmyJFoXlpU58kIrhhN3w26lpQb6dspetweapMn2CSNwQ8I4wg==", "dev": true, "license": "MIT", "optional": true, "dependencies": { - "@emnapi/wasi-threads": "1.0.1", + "@emnapi/wasi-threads": "1.1.0", "tslib": "^2.4.0" } }, "node_modules/@emnapi/runtime": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.2.0.tgz", - "integrity": "sha512-bV21/9LQmcQeCPEg3BDFtvwL6cwiTMksYNWQQ4KOxCZikEGalWtenoZ0wCiukJINlGCIi2KXx01g4FoH/LxpzQ==", + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.7.1.tgz", + "integrity": "sha512-PVtJr5CmLwYAU9PZDMITZoR5iAOShYREoR45EyyLrbntV50mdePTgUn4AmOw90Ifcj+x2kRjdzr1HP3RrNiHGA==", "dev": true, "license": "MIT", "optional": true, @@ -280,9 +277,9 @@ } }, "node_modules/@emnapi/wasi-threads": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.0.1.tgz", - "integrity": "sha512-iIBu7mwkq4UQGeMEM8bLwNK962nXdhodeScX4slfQnRhEMMzvYivHhutCIk8uojvmASXXPC2WNEjwxFWk72Oqw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.1.0.tgz", + "integrity": "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==", "dev": true, "license": "MIT", "optional": true, @@ -374,33 +371,51 @@ } }, "node_modules/@homebridge/ciao": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@homebridge/ciao/-/ciao-1.3.1.tgz", - "integrity": "sha512-87tQCBNNnTymlbg8pKlQjRsk7a5uuqhWBpCbUriVYUebz3voJkLbbTmp0TQg7Sa6Jnpk/Uo6LA8zAOy2sbK9bw==", + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/@homebridge/ciao/-/ciao-1.3.4.tgz", + "integrity": "sha512-qK6ZgGx0wwOubq/MY6eTbhApQHBUQCvCOsTYpQE01uLvfA2/Prm6egySHlZouKaina1RPuDwfLhCmsRCxwHj3Q==", "license": "MIT", "dependencies": { - "debug": "^4.3.6", + "debug": "^4.4.1", "fast-deep-equal": "^3.1.3", "source-map-support": "^0.5.21", - "tslib": "^2.6.3" + "tslib": "^2.8.1" }, "bin": { "ciao-bcs": "lib/bonjour-conformance-testing.js" + } + }, + "node_modules/@homebridge/hap-nodejs": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@homebridge/hap-nodejs/-/hap-nodejs-2.0.2.tgz", + "integrity": "sha512-HqlMqVQ8bzh7uFqL0vNI6a5PJHAmCyPzHuPbBxf6XcPVKn02ELwCMDQ8ud5oS1fPO5z20lvV7rIfAqTbSlZ7Uw==", + "license": "Apache-2.0", + "dependencies": { + "@homebridge/ciao": "^1.3.4", + "@homebridge/dbus-native": "^0.7.2", + "bonjour-hap": "^3.9.1", + "debug": "^4.4.3", + "fast-srp-hap": "^2.0.4", + "futoin-hkdf": "^1.5.3", + "node-persist": "^0.0.12", + "source-map-support": "^0.5.21", + "tslib": "^2.8.1", + "tweetnacl": "^1.0.3" }, "engines": { - "node": "^18 || ^20 || ^22" + "node": "^20 || ^22 || ^24" } }, - "node_modules/@homebridge/dbus-native": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/@homebridge/dbus-native/-/dbus-native-0.6.0.tgz", - "integrity": "sha512-xObqQeYHTXmt6wsfj10+krTo4xbzR9BgUfX2aQ+edDC9nc4ojfzLScfXCh3zluAm6UCowKw+AFfXn6WLWUOPkg==", + "node_modules/@homebridge/hap-nodejs/node_modules/@homebridge/dbus-native": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/@homebridge/dbus-native/-/dbus-native-0.7.2.tgz", + "integrity": "sha512-BNVe6YNxiy5x/E5/ZXDIWMD6Njv9cjW59PM/1CMpYe0jLAJ8pJN+Tq/JhVs3gXwmTavz2S86/sspmHquChet8A==", + "license": "MIT", "dependencies": { - "@homebridge/long": "^5.2.1", - "@homebridge/put": "^0.0.8", "event-stream": "^4.0.1", "hexy": "^0.3.5", - "minimist": "^1.2.6", + "long": "^5.3.2", + "minimist": "^1.2.8", "safe-buffer": "^5.1.2", "xml2js": "^0.6.2" }, @@ -408,17 +423,14 @@ "dbus2js": "bin/dbus2js.js" } }, - "node_modules/@homebridge/long": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/@homebridge/long/-/long-5.2.1.tgz", - "integrity": "sha512-i5Df8R63XNPCn+Nj1OgAoRdw9e+jHUQb3CNUbvJneI2iu3j4+OtzQj+5PA1Ce+747NR1SPqZSvyvD483dOT3AA==" - }, - "node_modules/@homebridge/put": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/@homebridge/put/-/put-0.0.8.tgz", - "integrity": "sha512-mwxLHHqKebOmOSU0tsPEWQSBHGApPhuaqtNpCe7U+AMdsduweANiu64E9SXXUtdpyTjsOpgSMLhD1+kbLHD2gA==", - "engines": { - "node": ">=0.3.0" + "node_modules/@homebridge/hap-nodejs/node_modules/node-persist": { + "version": "0.0.12", + "resolved": "https://registry.npmjs.org/node-persist/-/node-persist-0.0.12.tgz", + "integrity": "sha512-Fbia3FYnURzaql53wLu0t19dmAwQg/tXT6O7YPmdwNwysNKEyFmgoT2BQlPD3XXQnYeiQVNvR5lfvufGwKuxhg==", + "license": "MIT", + "dependencies": { + "mkdirp": "~0.5.1", + "q": "~1.1.1" } }, "node_modules/@humanwhocodes/config-array": { @@ -625,36 +637,49 @@ "license": "MIT" }, "node_modules/@napi-rs/wasm-runtime": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.4.tgz", - "integrity": "sha512-9zESzOO5aDByvhIAsOy9TbpZ0Ur2AJbUI7UT73kcUTS2mxAMHOBaa1st/jAymNoCtvrit99kkzT1FZuXVcgfIQ==", + "version": "0.2.12", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz", + "integrity": "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==", "dev": true, "license": "MIT", "optional": true, "dependencies": { - "@emnapi/core": "^1.1.0", - "@emnapi/runtime": "^1.1.0", - "@tybys/wasm-util": "^0.9.0" + "@emnapi/core": "^1.4.3", + "@emnapi/runtime": "^1.4.3", + "@tybys/wasm-util": "^0.10.0" + } + }, + "node_modules/@noble/hashes": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz", + "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" } }, "node_modules/@node-red/editor-api": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/@node-red/editor-api/-/editor-api-4.0.8.tgz", - "integrity": "sha512-ngsyd/Ro5oyefE+jCJa43fU9WLIGWFkTvifTheU9fj+epSgCGHQLLMOoEvs4FKOaPJ8L4dAqHgD/kik9c73rdg==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@node-red/editor-api/-/editor-api-4.1.1.tgz", + "integrity": "sha512-vev2s3NntphqinzP2e3WmPnQY8+cHfSrQyESis9Fy+prp+E8uSgT4yfLjHMFyT116xPMB5WIg6qSDciq5OV1tA==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@node-red/editor-client": "4.0.8", - "@node-red/util": "4.0.8", - "bcryptjs": "2.4.3", + "@node-red/editor-client": "4.1.1", + "@node-red/util": "4.1.1", + "bcryptjs": "3.0.2", "body-parser": "1.20.3", "clone": "2.1.2", "cors": "2.8.5", "express": "4.21.2", - "express-session": "1.18.1", + "express-session": "1.18.2", "memorystore": "1.6.7", "mime": "3.0.0", - "multer": "1.4.5-lts.1", + "multer": "2.0.2", "mustache": "4.2.0", "oauth2orize": "1.12.0", "passport": "0.7.0", @@ -663,24 +688,24 @@ "ws": "7.5.10" }, "optionalDependencies": { - "@node-rs/bcrypt": "1.10.4" + "@node-rs/bcrypt": "1.10.7" } }, "node_modules/@node-red/editor-client": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/@node-red/editor-client/-/editor-client-4.0.8.tgz", - "integrity": "sha512-LQI24xhXio4iftiiAvZ191Zjo9N1MsD0563aHGwsqGaLKxCTfOa+G1t5LslQoYGf0qMcYusf6Nftc2+5Q4nf/g==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@node-red/editor-client/-/editor-client-4.1.1.tgz", + "integrity": "sha512-JIJirftuB0NrvsFvPZXW3R16c8mLRy2UQh0AyxGU8ZQyz/dmF8auINbbGpQ4qxssBOGFWf9j4ZXP7B8EdLIOBQ==", "dev": true, "license": "Apache-2.0" }, "node_modules/@node-red/nodes": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/@node-red/nodes/-/nodes-4.0.8.tgz", - "integrity": "sha512-DAj0DyImWZ6lJo7D0LS/tFntkCEiUMAMMKBkyZjOudGLhxppaa99uzcDgQnSkM9vLSU1Uczxc9zHDY3RhxIpdA==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@node-red/nodes/-/nodes-4.1.1.tgz", + "integrity": "sha512-zTTwxpnPebHA5PjDBZEcsGv0BoqMJEjhf27aQIhlGed40/PaNiR0tmc5f5P6HKflmS3Iv6kiwGsY12Mjvyx/3Q==", "dev": true, "license": "Apache-2.0", "dependencies": { - "acorn": "8.12.1", + "acorn": "8.15.0", "acorn-walk": "8.3.4", "ajv": "8.17.1", "body-parser": "1.20.3", @@ -691,8 +716,8 @@ "cors": "2.8.5", "cronosjs": "1.7.1", "denque": "2.1.0", - "form-data": "4.0.0", - "fs-extra": "11.2.0", + "form-data": "4.0.4", + "fs-extra": "11.3.0", "got": "12.6.1", "hash-sum": "2.0.0", "hpagent": "1.2.0", @@ -701,13 +726,13 @@ "is-utf8": "0.2.1", "js-yaml": "4.1.0", "media-typer": "1.1.0", - "mqtt": "5.7.0", - "multer": "1.4.5-lts.1", + "mqtt": "5.11.0", + "multer": "2.0.2", "mustache": "4.2.0", "node-watch": "0.7.4", - "on-headers": "1.0.2", + "on-headers": "1.1.0", "raw-body": "3.0.0", - "tough-cookie": "^5.0.0", + "tough-cookie": "5.1.2", "uuid": "9.0.1", "ws": "7.5.10", "xml2js": "0.6.2" @@ -768,57 +793,173 @@ } }, "node_modules/@node-red/registry": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/@node-red/registry/-/registry-4.0.8.tgz", - "integrity": "sha512-yZLeMi4crXehsU5VZ9l/TpU9gzVijFlxykDiUB//errA415sdtMMk02yKq+yZVlRyBPAhQRkL97t4/Y3wcWJog==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@node-red/registry/-/registry-4.1.1.tgz", + "integrity": "sha512-+5SvdL+6tXzfYW63TpsfgybNP7G4farM+2div5FYYPdMJULE1D9Z8BHD/fprieU5mTTTO100CeyGXHbkzRH+Qg==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@node-red/util": "4.0.8", + "@node-red/util": "4.1.1", "clone": "2.1.2", - "fs-extra": "11.2.0", - "semver": "7.6.3", + "fs-extra": "11.3.0", + "semver": "7.7.1", "tar": "7.4.3", - "uglify-js": "3.17.4" + "uglify-js": "3.19.3" + } + }, + "node_modules/@node-red/registry/node_modules/semver": { + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" } }, "node_modules/@node-red/runtime": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/@node-red/runtime/-/runtime-4.0.8.tgz", - "integrity": "sha512-TYYyDytZr4nYJgkAKwDduCUjOMrIorUnn28aSorHgWCVJEdlllJAbBQgrdDJm6GGqsDNx2iFwmVbgKC3PJbTKg==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@node-red/runtime/-/runtime-4.1.1.tgz", + "integrity": "sha512-NWV+u2GrLnaPjomJilwVhl5u6WLwJN7tvHEVm5r9/8quW0H8BuYfih5AwCzCl8aly1imhe1+kfiCExSfGVaQUA==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@node-red/registry": "4.0.8", - "@node-red/util": "4.0.8", + "@node-red/registry": "4.1.1", + "@node-red/util": "4.1.1", "async-mutex": "0.5.0", "clone": "2.1.2", + "cronosjs": "1.7.1", "express": "4.21.2", - "fs-extra": "11.2.0", + "fs-extra": "11.3.0", + "got": "12.6.1", "json-stringify-safe": "5.0.1", - "rfdc": "^1.3.1" + "rfdc": "^1.3.1", + "semver": "7.7.1" + } + }, + "node_modules/@node-red/runtime/node_modules/semver": { + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" } }, "node_modules/@node-red/util": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/@node-red/util/-/util-4.0.8.tgz", - "integrity": "sha512-Kl2e4i+Oryq5waTMYvY3ntrQtMfy4+hRTMmeXwpkdCa27DTnWfz0grJHIfy0k9F97K7S47gKFOpR6EjRCm0mWw==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@node-red/util/-/util-4.1.1.tgz", + "integrity": "sha512-gnkRXmz49rj2OXjJC/RAPbFUQvDATC3Oy6yGuhN/McPy8mmL7q4YTIflUwWKyrsd6TU3cK17JmmXtPTQBtS8jQ==", "dev": true, "license": "Apache-2.0", "dependencies": { - "fs-extra": "11.2.0", - "i18next": "21.10.0", + "chalk": "^4.1.2", + "fs-extra": "11.3.0", + "i18next": "24.2.3", "json-stringify-safe": "5.0.1", - "jsonata": "2.0.5", + "jsonata": "2.0.6", "lodash.clonedeep": "^4.5.0", "moment": "2.30.1", - "moment-timezone": "0.5.46" + "moment-timezone": "0.5.48" + } + }, + "node_modules/@node-red/util/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@node-red/util/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@node-red/util/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@node-red/util/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@node-red/util/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@node-red/util/node_modules/jsonata": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/jsonata/-/jsonata-2.0.6.tgz", + "integrity": "sha512-WhQB5tXQ32qjkx2GYHFw2XbL90u+LLzjofAYwi+86g6SyZeXHz9F1Q0amy3dWRYczshOC3Haok9J4pOCgHtwyQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@node-red/util/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, "node_modules/@node-rs/bcrypt": { - "version": "1.10.4", - "resolved": "https://registry.npmjs.org/@node-rs/bcrypt/-/bcrypt-1.10.4.tgz", - "integrity": "sha512-Kzs8HKt2eBeT5VnkeKgiz/QKTjOO3URcvSNEQZahNwZnL6dBeeJQTxxYisc/6969+5n6c3+gNwKvqJsZzmGe7g==", + "version": "1.10.7", + "resolved": "https://registry.npmjs.org/@node-rs/bcrypt/-/bcrypt-1.10.7.tgz", + "integrity": "sha512-1wk0gHsUQC/ap0j6SJa2K34qNhomxXRcEe3T8cI5s+g6fgHBgLTN7U9LzWTG/HE6G4+2tWWLeCabk1wiYGEQSA==", "dev": true, "license": "MIT", "optional": true, @@ -830,26 +971,26 @@ "url": "https://github.com/sponsors/Brooooooklyn" }, "optionalDependencies": { - "@node-rs/bcrypt-android-arm-eabi": "1.10.4", - "@node-rs/bcrypt-android-arm64": "1.10.4", - "@node-rs/bcrypt-darwin-arm64": "1.10.4", - "@node-rs/bcrypt-darwin-x64": "1.10.4", - "@node-rs/bcrypt-freebsd-x64": "1.10.4", - "@node-rs/bcrypt-linux-arm-gnueabihf": "1.10.4", - "@node-rs/bcrypt-linux-arm64-gnu": "1.10.4", - "@node-rs/bcrypt-linux-arm64-musl": "1.10.4", - "@node-rs/bcrypt-linux-x64-gnu": "1.10.4", - "@node-rs/bcrypt-linux-x64-musl": "1.10.4", - "@node-rs/bcrypt-wasm32-wasi": "1.10.4", - "@node-rs/bcrypt-win32-arm64-msvc": "1.10.4", - "@node-rs/bcrypt-win32-ia32-msvc": "1.10.4", - "@node-rs/bcrypt-win32-x64-msvc": "1.10.4" + "@node-rs/bcrypt-android-arm-eabi": "1.10.7", + "@node-rs/bcrypt-android-arm64": "1.10.7", + "@node-rs/bcrypt-darwin-arm64": "1.10.7", + "@node-rs/bcrypt-darwin-x64": "1.10.7", + "@node-rs/bcrypt-freebsd-x64": "1.10.7", + "@node-rs/bcrypt-linux-arm-gnueabihf": "1.10.7", + "@node-rs/bcrypt-linux-arm64-gnu": "1.10.7", + "@node-rs/bcrypt-linux-arm64-musl": "1.10.7", + "@node-rs/bcrypt-linux-x64-gnu": "1.10.7", + "@node-rs/bcrypt-linux-x64-musl": "1.10.7", + "@node-rs/bcrypt-wasm32-wasi": "1.10.7", + "@node-rs/bcrypt-win32-arm64-msvc": "1.10.7", + "@node-rs/bcrypt-win32-ia32-msvc": "1.10.7", + "@node-rs/bcrypt-win32-x64-msvc": "1.10.7" } }, "node_modules/@node-rs/bcrypt-android-arm-eabi": { - "version": "1.10.4", - "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-android-arm-eabi/-/bcrypt-android-arm-eabi-1.10.4.tgz", - "integrity": "sha512-55ajutuTdfK1hKseyliflnxzNtxszQQ/EoLtgJlgCe7rI24vGP9EEEZDznB/u9OaJ14/AYzZtIhkEOYdbIdw0A==", + "version": "1.10.7", + "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-android-arm-eabi/-/bcrypt-android-arm-eabi-1.10.7.tgz", + "integrity": "sha512-8dO6/PcbeMZXS3VXGEtct9pDYdShp2WBOWlDvSbcRwVqyB580aCBh0BEFmKYtXLzLvUK8Wf+CG3U6sCdILW1lA==", "cpu": [ "arm" ], @@ -864,9 +1005,9 @@ } }, "node_modules/@node-rs/bcrypt-android-arm64": { - "version": "1.10.4", - "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-android-arm64/-/bcrypt-android-arm64-1.10.4.tgz", - "integrity": "sha512-dCgQT7nH65tORmJw2hQ6zQgFmmC+/JBYZUWtf7pPZI76AVAn5tc7cIUrxYoV4OT1+uD63b9Av+mS1fT2EPzWEg==", + "version": "1.10.7", + "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-android-arm64/-/bcrypt-android-arm64-1.10.7.tgz", + "integrity": "sha512-UASFBS/CucEMHiCtL/2YYsAY01ZqVR1N7vSb94EOvG5iwW7BQO06kXXCTgj+Xbek9azxixrCUmo3WJnkJZ0hTQ==", "cpu": [ "arm64" ], @@ -881,9 +1022,9 @@ } }, "node_modules/@node-rs/bcrypt-darwin-arm64": { - "version": "1.10.4", - "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-darwin-arm64/-/bcrypt-darwin-arm64-1.10.4.tgz", - "integrity": "sha512-gmHdWikHL3YVZgqXAHT+X/PG+kqIyNlPeFAWKdby83RkDI8FUiPV4qqGilgNnBmVWKkobRae9/I1HDbc4Sbhyg==", + "version": "1.10.7", + "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-darwin-arm64/-/bcrypt-darwin-arm64-1.10.7.tgz", + "integrity": "sha512-DgzFdAt455KTuiJ/zYIyJcKFobjNDR/hnf9OS7pK5NRS13Nq4gLcSIIyzsgHwZHxsJWbLpHmFc1H23Y7IQoQBw==", "cpu": [ "arm64" ], @@ -898,9 +1039,9 @@ } }, "node_modules/@node-rs/bcrypt-darwin-x64": { - "version": "1.10.4", - "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-darwin-x64/-/bcrypt-darwin-x64-1.10.4.tgz", - "integrity": "sha512-WDzL1WKRtoyTkH6IMPx95Mkd6XaeN0VWJbSDMqQY6AFBOk03yJEj7YYXshCcF+Ur6KBBVSwRf6sdFJ15NI1Z3g==", + "version": "1.10.7", + "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-darwin-x64/-/bcrypt-darwin-x64-1.10.7.tgz", + "integrity": "sha512-SPWVfQ6sxSokoUWAKWD0EJauvPHqOGQTd7CxmYatcsUgJ/bruvEHxZ4bIwX1iDceC3FkOtmeHO0cPwR480n/xA==", "cpu": [ "x64" ], @@ -915,9 +1056,9 @@ } }, "node_modules/@node-rs/bcrypt-freebsd-x64": { - "version": "1.10.4", - "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-freebsd-x64/-/bcrypt-freebsd-x64-1.10.4.tgz", - "integrity": "sha512-seSPJi+4MIUd1faL/n/wmDdDwaynd/FTkvTnb7qzCk8LBT+/dxi7MTz+uaD8KYDREcB9Wmhv+lwr0S9/jBTcjg==", + "version": "1.10.7", + "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-freebsd-x64/-/bcrypt-freebsd-x64-1.10.7.tgz", + "integrity": "sha512-gpa+Ixs6GwEx6U6ehBpsQetzUpuAGuAFbOiuLB2oo4N58yU4AZz1VIcWyWAHrSWRs92O0SHtmo2YPrMrwfBbSw==", "cpu": [ "x64" ], @@ -932,9 +1073,9 @@ } }, "node_modules/@node-rs/bcrypt-linux-arm-gnueabihf": { - "version": "1.10.4", - "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-linux-arm-gnueabihf/-/bcrypt-linux-arm-gnueabihf-1.10.4.tgz", - "integrity": "sha512-YcMLUtN9cGNTWKnaXslxGO1M0S5b4QN9KYhuyG6Kju27RfqvU5UbmpKElCsEUO2EIjxGwzvPu59T+Fyh6sVbwg==", + "version": "1.10.7", + "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-linux-arm-gnueabihf/-/bcrypt-linux-arm-gnueabihf-1.10.7.tgz", + "integrity": "sha512-kYgJnTnpxrzl9sxYqzflobvMp90qoAlaX1oDL7nhNTj8OYJVDIk0jQgblj0bIkjmoPbBed53OJY/iu4uTS+wig==", "cpu": [ "arm" ], @@ -949,9 +1090,9 @@ } }, "node_modules/@node-rs/bcrypt-linux-arm64-gnu": { - "version": "1.10.4", - "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-linux-arm64-gnu/-/bcrypt-linux-arm64-gnu-1.10.4.tgz", - "integrity": "sha512-uYGUK/mO8SiftqmVSAePWxgK82vg+X/gtrVRJi95yq2iwp1+fYJX3ndxCyYPmeplBbd3NJ/F5lPT3FC/IHTTGw==", + "version": "1.10.7", + "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-linux-arm64-gnu/-/bcrypt-linux-arm64-gnu-1.10.7.tgz", + "integrity": "sha512-7cEkK2RA+gBCj2tCVEI1rDSJV40oLbSq7bQ+PNMHNI6jCoXGmj9Uzo7mg7ZRbNZ7piIyNH5zlJqutjo8hh/tmA==", "cpu": [ "arm64" ], @@ -966,9 +1107,9 @@ } }, "node_modules/@node-rs/bcrypt-linux-arm64-musl": { - "version": "1.10.4", - "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-linux-arm64-musl/-/bcrypt-linux-arm64-musl-1.10.4.tgz", - "integrity": "sha512-rLvSMW/gVUBd2k2gAqQfuOReHWd9+jvz58E3i1TbkRE3a5ChvjOFc9qKPEmXuXuD9Mdj7gUwcYwpq8MdB5MtNw==", + "version": "1.10.7", + "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-linux-arm64-musl/-/bcrypt-linux-arm64-musl-1.10.7.tgz", + "integrity": "sha512-X7DRVjshhwxUqzdUKDlF55cwzh+wqWJ2E/tILvZPboO3xaNO07Um568Vf+8cmKcz+tiZCGP7CBmKbBqjvKN/Pw==", "cpu": [ "arm64" ], @@ -983,9 +1124,9 @@ } }, "node_modules/@node-rs/bcrypt-linux-x64-gnu": { - "version": "1.10.4", - "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-linux-x64-gnu/-/bcrypt-linux-x64-gnu-1.10.4.tgz", - "integrity": "sha512-I++6bh+BIp70X/D/crlSgCq8K0s9nGvzmvAGFkqSG4h3LBtjJx4RKbygnoWvcBV9ErK1rvcjfMyjwZt1ukueFA==", + "version": "1.10.7", + "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-linux-x64-gnu/-/bcrypt-linux-x64-gnu-1.10.7.tgz", + "integrity": "sha512-LXRZsvG65NggPD12hn6YxVgH0W3VR5fsE/o1/o2D5X0nxKcNQGeLWnRzs5cP8KpoFOuk1ilctXQJn8/wq+Gn/Q==", "cpu": [ "x64" ], @@ -1000,9 +1141,9 @@ } }, "node_modules/@node-rs/bcrypt-linux-x64-musl": { - "version": "1.10.4", - "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-linux-x64-musl/-/bcrypt-linux-x64-musl-1.10.4.tgz", - "integrity": "sha512-f9RPl/5n2NS0mMJXB4IYbodKnq5HzOK5x1b9eKbcjsY0rw3mJC3K0XRFc8iaw1a5chA+xV1TPXz5mkykmr2CQQ==", + "version": "1.10.7", + "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-linux-x64-musl/-/bcrypt-linux-x64-musl-1.10.7.tgz", + "integrity": "sha512-tCjHmct79OfcO3g5q21ME7CNzLzpw1MAsUXCLHLGWH+V6pp/xTvMbIcLwzkDj6TI3mxK6kehTn40SEjBkZ3Rog==", "cpu": [ "x64" ], @@ -1017,9 +1158,9 @@ } }, "node_modules/@node-rs/bcrypt-wasm32-wasi": { - "version": "1.10.4", - "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-wasm32-wasi/-/bcrypt-wasm32-wasi-1.10.4.tgz", - "integrity": "sha512-VaDOf+wic0yoHFimMkC5VMa/33BNqg6ieD+C/ibb7Av3NnVW4/W9YpDpqAWMR2w3fA40uTLWZ7FZSrcFck27oA==", + "version": "1.10.7", + "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-wasm32-wasi/-/bcrypt-wasm32-wasi-1.10.7.tgz", + "integrity": "sha512-4qXSihIKeVXYglfXZEq/QPtYtBUvR8d3S85k15Lilv3z5B6NSGQ9mYiNleZ7QHVLN2gEc5gmi7jM353DMH9GkA==", "cpu": [ "wasm32" ], @@ -1027,16 +1168,16 @@ "license": "MIT", "optional": true, "dependencies": { - "@napi-rs/wasm-runtime": "^0.2.3" + "@napi-rs/wasm-runtime": "^0.2.5" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@node-rs/bcrypt-win32-arm64-msvc": { - "version": "1.10.4", - "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-win32-arm64-msvc/-/bcrypt-win32-arm64-msvc-1.10.4.tgz", - "integrity": "sha512-M7sGnbKPvhYJ5b76ywXiEwR4mIs/JSDHjRrhm9fshKAvltQrwc3Mou22TJggvDN3gKOF1W85uPiM2OgGX/jxMg==", + "version": "1.10.7", + "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-win32-arm64-msvc/-/bcrypt-win32-arm64-msvc-1.10.7.tgz", + "integrity": "sha512-FdfUQrqmDfvC5jFhntMBkk8EI+fCJTx/I1v7Rj+Ezlr9rez1j1FmuUnywbBj2Cg15/0BDhwYdbyZ5GCMFli2aQ==", "cpu": [ "arm64" ], @@ -1051,9 +1192,9 @@ } }, "node_modules/@node-rs/bcrypt-win32-ia32-msvc": { - "version": "1.10.4", - "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-win32-ia32-msvc/-/bcrypt-win32-ia32-msvc-1.10.4.tgz", - "integrity": "sha512-zn/n4DYnuOfC2JgmVDa0JHP+5DUqAOTl2jmV3yrMrmN+StDT4Om5wtvWxvEmgv3CkeZAuAU3Y/fwjSXIpZ0Fhg==", + "version": "1.10.7", + "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-win32-ia32-msvc/-/bcrypt-win32-ia32-msvc-1.10.7.tgz", + "integrity": "sha512-lZLf4Cx+bShIhU071p5BZft4OvP4PGhyp542EEsb3zk34U5GLsGIyCjOafcF/2DGewZL6u8/aqoxbSuROkgFXg==", "cpu": [ "ia32" ], @@ -1068,9 +1209,9 @@ } }, "node_modules/@node-rs/bcrypt-win32-x64-msvc": { - "version": "1.10.4", - "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-win32-x64-msvc/-/bcrypt-win32-x64-msvc-1.10.4.tgz", - "integrity": "sha512-ynQokTTGbuLu/cckaD8dNcE+Zsfam1zElE+teNol8AxcL7Jv+ghJItSnRthPRV/vLxuycDF2DIICgpXG/p9jrQ==", + "version": "1.10.7", + "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-win32-x64-msvc/-/bcrypt-win32-x64-msvc-1.10.7.tgz", + "integrity": "sha512-hdw7tGmN1DxVAMTzICLdaHpXjy+4rxaxnBMgI8seG1JL5e3VcRGsd1/1vVDogVp2cbsmgq+6d6yAY+D9lW/DCg==", "cpu": [ "x64" ], @@ -1128,6 +1269,16 @@ "debug": "^4.3.5" } }, + "node_modules/@paralleldrive/cuid2": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/@paralleldrive/cuid2/-/cuid2-2.3.1.tgz", + "integrity": "sha512-XO7cAxhnTZl0Yggq6jOgjiOHhbgcO4NqFqwSmQpjK3b6TEE6Uj/jfSk6wzYyemh3+I0sHirKSetjQwn5cZktFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@noble/hashes": "^1.1.5" + } + }, "node_modules/@pkgjs/parseargs": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", @@ -1140,15 +1291,16 @@ } }, "node_modules/@pkgr/core": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.0.tgz", - "integrity": "sha512-Zwq5OCzuwJC2jwqmpEQt7Ds1DTi6BWSwoGkbb1n9pO3hzb35BoJELx7c0T23iDkBGkh2e7tvOtjF3tr3OaQHDQ==", + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.9.tgz", + "integrity": "sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==", "dev": true, + "license": "MIT", "engines": { "node": "^12.20.0 || ^14.18.0 || >=16.0.0" }, "funding": { - "url": "https://opencollective.com/unts" + "url": "https://opencollective.com/pkgr" } }, "node_modules/@sindresorhus/is": { @@ -1237,9 +1389,9 @@ "dev": true }, "node_modules/@tybys/wasm-util": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.9.0.tgz", - "integrity": "sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw==", + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz", + "integrity": "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==", "dev": true, "license": "MIT", "optional": true, @@ -1353,12 +1505,13 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "18.19.34", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.34.tgz", - "integrity": "sha512-eXF4pfBNV5DAMKGbI02NnDtWrQ40hAN558/2vvS4gMpMIxaf6JmD7YjnZbq0Q9TDSSkKBamime8ewRoomHdt4g==", + "version": "20.19.25", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.25.tgz", + "integrity": "sha512-ZsJzA5thDQMSQO788d7IocwwQbI8B5OPzmqNvpf3NY/+MHDAS759Wo0gd2WQeXYt5AAAQjzcrTVC6SKCuYgoCQ==", "dev": true, + "license": "MIT", "dependencies": { - "undici-types": "~5.26.4" + "undici-types": "~6.21.0" } }, "node_modules/@types/node-persist": { @@ -1444,10 +1597,11 @@ } }, "node_modules/@types/node-red-node-test-helper": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/@types/node-red-node-test-helper/-/node-red-node-test-helper-0.3.4.tgz", - "integrity": "sha512-g6XWeB9twf+Y3ADRZpmks95rFexElomsM8a8WyWsTaNZKFaPSTGpENsOCBnR8tOG2okiNtoZCaW6tJM4ZL3X3Q==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@types/node-red-node-test-helper/-/node-red-node-test-helper-0.3.5.tgz", + "integrity": "sha512-ppCrp+3ncOCvciPXwQWhXy5voENjDyK1Xvw98Q9a4tJsSdqiitdy7HsUgtbCSn/mrKStRzZ61l+fHDAknR0BgA==", "dev": true, + "license": "MIT", "dependencies": { "@types/node-red": "*", "@types/node-red__runtime": "*", @@ -1483,29 +1637,22 @@ "dev": true }, "node_modules/@types/readable-stream": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/@types/readable-stream/-/readable-stream-4.0.18.tgz", - "integrity": "sha512-21jK/1j+Wg+7jVw1xnSwy/2Q1VgVjWuFssbYGTREPUBeZ+rqVFl2udq0IkxzPC0ZhOzVceUbyIACFZKLqKEBlA==", + "version": "4.0.22", + "resolved": "https://registry.npmjs.org/@types/readable-stream/-/readable-stream-4.0.22.tgz", + "integrity": "sha512-/FFhJpfCLAPwAcN3mFycNUa77ddnr8jTgF5VmSNetaemWB2cIlfCA9t0YTM3JAT0wOcv8D4tjPo7pkDhK3EJIg==", "dev": true, "license": "MIT", "dependencies": { - "@types/node": "*", - "safe-buffer": "~5.1.1" + "@types/node": "*" } }, - "node_modules/@types/readable-stream/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "node_modules/@types/semver": { + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-FmgJfu+MOcQ370SD0ev7EI8TlCAfKYU+B4m5T3yXc1CiRN94g/SZPtsCkk506aUDtlMnFZvasDwHHUcZUEaYuA==", "dev": true, "license": "MIT" }, - "node_modules/@types/semver": { - "version": "7.5.8", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", - "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", - "dev": true - }, "node_modules/@types/send": { "version": "0.17.1", "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.1.tgz", @@ -1574,9 +1721,9 @@ "dev": true }, "node_modules/@types/ws": { - "version": "8.5.13", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.13.tgz", - "integrity": "sha512-osM/gWBTPKgHV8XkTunnegTRIsvF6owmf5w+JtAfOw472dptdm0dlGv4xCt6GwQRcC2XVOvvRE/0bAoQcL2QkA==", + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz", + "integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==", "dev": true, "license": "MIT", "dependencies": { @@ -1736,9 +1883,9 @@ } }, "node_modules/@typescript-eslint/typescript-estree/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, "license": "MIT", "dependencies": { @@ -1841,9 +1988,9 @@ } }, "node_modules/acorn": { - "version": "8.12.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", - "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, "license": "MIT", "bin": { @@ -2028,7 +2175,8 @@ "version": "2.0.6", "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/async-mutex": { "version": "0.5.0", @@ -2044,7 +2192,8 @@ "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/available-typed-arrays": { "version": "1.0.7", @@ -2062,14 +2211,14 @@ } }, "node_modules/axios": { - "version": "1.7.7", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz", - "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==", + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.12.2.tgz", + "integrity": "sha512-vMJzPewAlRyOgxV2dU0Cuz2O8zzzx9VYtbJOaBgXFeLc4IV/Eg50n4LowmehOOR61S8ZMpc2K5Sa7g6A4jfkUw==", "dev": true, "license": "MIT", "dependencies": { "follow-redirects": "^1.15.6", - "form-data": "^4.0.0", + "form-data": "^4.0.4", "proxy-from-env": "^1.1.0" } }, @@ -2149,11 +2298,14 @@ "dev": true }, "node_modules/bcryptjs": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz", - "integrity": "sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-3.0.2.tgz", + "integrity": "sha512-k38b3XOZKv60C4E2hVsXTolJWfkGRMbILBIe2IBITXciy5bOsTKot5kDrf3ZfufQtQOUN5mXceUEpU1rTl9Uog==", "dev": true, - "license": "MIT" + "license": "BSD-3-Clause", + "bin": { + "bcrypt": "bin/bcrypt" + } }, "node_modules/binary-extensions": { "version": "2.2.0", @@ -2165,9 +2317,9 @@ } }, "node_modules/bl": { - "version": "6.0.18", - "resolved": "https://registry.npmjs.org/bl/-/bl-6.0.18.tgz", - "integrity": "sha512-2k76XmWCuvu9HTvu3tFOl5HDdCH0wLZ/jHYva/LBVJmc9oX8yUtNQjxrFmbTdXsCSmIxwVTANZPNDfMQrvHFUw==", + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/bl/-/bl-6.1.4.tgz", + "integrity": "sha512-ZV/9asSuknOExbM/zPPA8z00lc1ihPKWaStHkkQrxHNeYx+yY+TmF+v80dpv2G0mv3HVXBu7ryoAsxbFFhf4eg==", "dev": true, "license": "MIT", "dependencies": { @@ -2230,9 +2382,9 @@ "dev": true }, "node_modules/bonjour-hap": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/bonjour-hap/-/bonjour-hap-3.8.0.tgz", - "integrity": "sha512-l/Ptvrt/pjN2pCgiVyyA0EkE0uVoXXYZ4DW4xhL4kDVBaw0w54/3Jhdhzn5EyT1Z8YhNXiNhSX0uW6xz2zSxqQ==", + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/bonjour-hap/-/bonjour-hap-3.9.1.tgz", + "integrity": "sha512-ubpbZSBwRyAx2+j5RLKFO+QuRvB02s+7rinC0rQzICx9hEc0zryjRz56Rr9lxoW7UkE/mnZ4rP4mnTCF4/iUkg==", "license": "MIT", "dependencies": { "array-flatten": "^3.0.0", @@ -2249,10 +2401,11 @@ "license": "ISC" }, "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -2374,6 +2527,19 @@ "url": "https://github.com/sponsors/ljharb" } }, + "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==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -2604,6 +2770,7 @@ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", "dev": true, + "license": "MIT", "dependencies": { "delayed-stream": "~1.0.0" }, @@ -2623,6 +2790,7 @@ "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.1.tgz", "integrity": "sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==", "dev": true, + "license": "MIT", "funding": { "url": "https://github.com/sponsors/sindresorhus" } @@ -2719,12 +2887,6 @@ "version": "2.1.4", "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.4.tgz", "integrity": "sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==", - "dev": true - }, - "node_modules/core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", "dev": true, "license": "MIT" }, @@ -2791,9 +2953,9 @@ } }, "node_modules/css-what": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", - "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.2.2.tgz", + "integrity": "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==", "dev": true, "license": "BSD-2-Clause", "engines": { @@ -2804,9 +2966,9 @@ } }, "node_modules/debug": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", - "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -3082,6 +3244,7 @@ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.4.0" } @@ -3120,6 +3283,7 @@ "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.4.tgz", "integrity": "sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==", "dev": true, + "license": "ISC", "dependencies": { "asap": "^2.0.0", "wrappy": "1" @@ -3230,6 +3394,20 @@ "url": "https://github.com/fb55/domutils?sponsor=1" } }, + "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==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/duplexer": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", @@ -3298,12 +3476,10 @@ } }, "node_modules/es-define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", - "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", - "dependencies": { - "get-intrinsic": "^1.2.4" - }, + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", "engines": { "node": ">= 0.4" } @@ -3336,6 +3512,34 @@ "url": "https://github.com/sponsors/ljharb" } }, + "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==", + "license": "MIT", + "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==", + "dev": true, + "license": "MIT", + "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/escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", @@ -3429,13 +3633,14 @@ } }, "node_modules/eslint-plugin-prettier": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.1.3.tgz", - "integrity": "sha512-C9GCVAs4Eq7ZC/XFQHITLiHJxQngdtraXaM+LoUFoFp/lHNl2Zn8f3WQbe9HvTBBQ9YnKFB0/2Ajdqwo5D1EAw==", + "version": "5.5.4", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.5.4.tgz", + "integrity": "sha512-swNtI95SToIz05YINMA6Ox5R057IMAmWZ26GqPxusAp1TZzj+IdY9tXNWWD3vkF/wEqydCONcwjTFpxybBqZsg==", "dev": true, + "license": "MIT", "dependencies": { "prettier-linter-helpers": "^1.0.0", - "synckit": "^0.8.6" + "synckit": "^0.11.7" }, "engines": { "node": "^14.18.0 || >=16.0.0" @@ -3446,7 +3651,7 @@ "peerDependencies": { "@types/eslint": ">=8.0.0", "eslint": ">=8.0.0", - "eslint-config-prettier": "*", + "eslint-config-prettier": ">= 7.0.0 <10.0.0 || >=10.1.0", "prettier": ">=3.0.0" }, "peerDependenciesMeta": { @@ -3756,9 +3961,9 @@ } }, "node_modules/express-session": { - "version": "1.18.1", - "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.18.1.tgz", - "integrity": "sha512-a5mtTqEaZvBCL9A9aqkrtfz+3SMDhOVUnjafjo+s7A9Txkq+SVX2DLvSp1Zrv4uCXa3lMSK3viWnh9Gg07PBUA==", + "version": "1.18.2", + "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.18.2.tgz", + "integrity": "sha512-SZjssGQC7TzTs9rpPDuUrR23GNZ9+2+IkA/+IJWmvQilTr5OSliEHGF+D9scbIpdC6yGtTI0/VhaHoVes2AN/A==", "dev": true, "license": "MIT", "dependencies": { @@ -3766,7 +3971,7 @@ "cookie-signature": "1.0.7", "debug": "2.6.9", "depd": "~2.0.0", - "on-headers": "~1.0.2", + "on-headers": "~1.1.0", "parseurl": "~1.3.3", "safe-buffer": "5.2.1", "uid-safe": "~2.1.5" @@ -3885,7 +4090,8 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/fast-srp-hap": { "version": "2.0.4", @@ -3910,9 +4116,9 @@ } }, "node_modules/fast-uri": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.5.tgz", - "integrity": "sha512-5JnBCWpFlMo0a3ciDy/JckMzzv1U9coZrIhedq+HXxxUfDTAiS0LA8OKVao4G9BxmCVck/jtA5r3KAtRWEyD8Q==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz", + "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==", "dev": true, "funding": [ { @@ -4055,9 +4261,9 @@ "dev": true }, "node_modules/follow-redirects": { - "version": "1.15.9", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", - "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", + "version": "1.15.11", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", + "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", "dev": true, "funding": [ { @@ -4102,13 +4308,16 @@ } }, "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.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz", + "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", "dev": true, + "license": "MIT", "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": { @@ -4126,15 +4335,19 @@ } }, "node_modules/formidable": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/formidable/-/formidable-3.5.1.tgz", - "integrity": "sha512-WJWKelbRHN41m5dumb0/k8TeAx7Id/y3a+Z7QfhxP/htI9Js5zYaEDtG8uMgG0vM0lOlqnmjE99/kfpOYi/0Og==", + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/formidable/-/formidable-3.5.4.tgz", + "integrity": "sha512-YikH+7CUTOtP44ZTnUhR7Ic2UASBPOqmaRkRKxRbywPTe5VxF7RRCck4af9wutiZ/QKM5nME9Bie2fFaPz5Gug==", "dev": true, + "license": "MIT", "dependencies": { + "@paralleldrive/cuid2": "^2.2.2", "dezalgo": "^1.0.4", - "hexoid": "^1.0.0", "once": "^1.4.0" }, + "engines": { + "node": ">=14.0.0" + }, "funding": { "url": "https://ko-fi.com/tunnckoCore/commissions" } @@ -4164,10 +4377,11 @@ "integrity": "sha512-twe20eF1OxVxp/ML/kq2p1uc6KvFK/+vs8WjEbeKmV2He22MKm7YF2ANIt+EOqhJ5L3K/SuuPhk0hWQDjOM23g==" }, "node_modules/fs-extra": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", - "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", + "version": "11.3.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.0.tgz", + "integrity": "sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew==", "dev": true, + "license": "MIT", "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", @@ -4218,15 +4432,21 @@ } }, "node_modules/get-intrinsic": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", - "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", "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", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0" + "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" @@ -4235,6 +4455,19 @@ "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==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/get-stream": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", @@ -4311,11 +4544,12 @@ } }, "node_modules/gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", - "dependencies": { - "get-intrinsic": "^1.1.3" + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -4359,36 +4593,6 @@ "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", "dev": true }, - "node_modules/hap-nodejs": { - "version": "0.12.3", - "resolved": "https://registry.npmjs.org/hap-nodejs/-/hap-nodejs-0.12.3.tgz", - "integrity": "sha512-E6uEwSmDejvzaSAHosjjbWp7/YNo0o+LZtcbH2KoediVOHGG1tYRDGEMyOiG7ZtZn6CwXwr6xqSZTnXTzQCImQ==", - "license": "Apache-2.0", - "dependencies": { - "@homebridge/ciao": "^1.3.1", - "@homebridge/dbus-native": "^0.6.0", - "bonjour-hap": "^3.8.0", - "debug": "^4.3.7", - "fast-srp-hap": "^2.0.4", - "futoin-hkdf": "^1.5.3", - "node-persist": "^0.0.12", - "source-map-support": "^0.5.21", - "tslib": "^2.8.0", - "tweetnacl": "^1.0.3" - }, - "engines": { - "node": "^18 || ^20 || ^22" - } - }, - "node_modules/hap-nodejs/node_modules/node-persist": { - "version": "0.0.12", - "resolved": "https://registry.npmjs.org/node-persist/-/node-persist-0.0.12.tgz", - "integrity": "sha512-Fbia3FYnURzaql53wLu0t19dmAwQg/tXT6O7YPmdwNwysNKEyFmgoT2BQlPD3XXQnYeiQVNvR5lfvufGwKuxhg==", - "dependencies": { - "mkdirp": "~0.5.1", - "q": "~1.1.1" - } - }, "node_modules/hard-rejection": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", @@ -4439,21 +4643,11 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/has-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", - "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -4484,9 +4678,10 @@ "license": "MIT" }, "node_modules/hasown": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.1.tgz", - "integrity": "sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", "dependencies": { "function-bind": "^1.1.2" }, @@ -4510,15 +4705,6 @@ "dev": true, "license": "MIT" }, - "node_modules/hexoid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/hexoid/-/hexoid-1.0.0.tgz", - "integrity": "sha512-QFLV0taWQOZtvIRIAdBChesmogZrtuXvVWsFHZTk2SU+anspqZ2vMnoLg7IE1+Uk16N19APic1BuF8bC8c2m5g==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/hexy": { "version": "0.3.5", "resolved": "https://registry.npmjs.org/hexy/-/hexy-0.3.5.tgz", @@ -4591,9 +4777,9 @@ } }, "node_modules/http-cache-semantics": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", - "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", + "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==", "dev": true, "license": "BSD-2-Clause" }, @@ -4642,12 +4828,13 @@ } }, "node_modules/husky": { - "version": "9.0.11", - "resolved": "https://registry.npmjs.org/husky/-/husky-9.0.11.tgz", - "integrity": "sha512-AB6lFlbwwyIqMdHYhwPe+kjOC3Oc5P3nThEoW/AaO2BX3vJDjWPFxYLxokUZOo6RNX20He3AaT8sESs9NJcmEw==", + "version": "9.1.7", + "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.7.tgz", + "integrity": "sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==", "dev": true, + "license": "MIT", "bin": { - "husky": "bin.mjs" + "husky": "bin.js" }, "engines": { "node": ">=18" @@ -4657,9 +4844,9 @@ } }, "node_modules/i18next": { - "version": "21.10.0", - "resolved": "https://registry.npmjs.org/i18next/-/i18next-21.10.0.tgz", - "integrity": "sha512-YeuIBmFsGjUfO3qBmMOc0rQaun4mIpGKET5WDwvu8lU7gvwpcariZLNtL0Fzj+zazcHUrlXHiptcFhBMFaxzfg==", + "version": "24.2.3", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-24.2.3.tgz", + "integrity": "sha512-lfbf80OzkocvX7nmZtu7nSTNbrTYR52sLWxPtlXX1zAhVw8WEnFk4puUkCR4B1dNQwbSpEHHHemcZu//7EcB7A==", "dev": true, "funding": [ { @@ -4677,7 +4864,15 @@ ], "license": "MIT", "dependencies": { - "@babel/runtime": "^7.17.2" + "@babel/runtime": "^7.26.10" + }, + "peerDependencies": { + "typescript": "^5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, "node_modules/iconv-lite": { @@ -4790,6 +4985,16 @@ "node": ">= 0.4" } }, + "node_modules/ip-address": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.1.0.tgz", + "integrity": "sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, "node_modules/ipaddr.js": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", @@ -5244,10 +5449,11 @@ } }, "node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", "dev": true, + "license": "MIT", "dependencies": { "universalify": "^2.0.0" }, @@ -5419,6 +5625,12 @@ "node": ">=8" } }, + "node_modules/long": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz", + "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==", + "license": "Apache-2.0" + }, "node_modules/lowercase-keys": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-3.0.0.tgz", @@ -5466,6 +5678,15 @@ "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.0.7.tgz", "integrity": "sha512-C0X0KQmGm3N2ftbTGBhSyuydQ+vV1LC3f3zPvT3RXHXNZrvfPZcoXp/N5DOa8vedX/rTMm2CjTtivFg2STJMRQ==" }, + "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==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/media-typer": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", @@ -5741,10 +5962,11 @@ } }, "node_modules/mocha/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, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } @@ -5828,9 +6050,9 @@ } }, "node_modules/moment-timezone": { - "version": "0.5.46", - "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.46.tgz", - "integrity": "sha512-ZXm9b36esbe7OmdABqIWJuBBiLLwAjrN7CE+7sYdCCx82Nabt1wHDj8TVseS59QIlfFPbOoiBPm6ca9BioG4hw==", + "version": "0.5.48", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.48.tgz", + "integrity": "sha512-f22b8LV1gbTO2ms2j2z13MuPogNoh5UzxL3nzNAYKGraILnbGc9NEE6dyiiiLv46DGRb8A4kg8UKWLjPthxBHw==", "dev": true, "license": "MIT", "dependencies": { @@ -5841,29 +6063,29 @@ } }, "node_modules/mqtt": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/mqtt/-/mqtt-5.7.0.tgz", - "integrity": "sha512-/o0CBYSjZzddmQDV2iglCafsA0xWKpqnS62tGbOLOliubBxszpXO1DAQPyfI7ZcPDG0b9ni7QITn+5FW1E2UTg==", + "version": "5.11.0", + "resolved": "https://registry.npmjs.org/mqtt/-/mqtt-5.11.0.tgz", + "integrity": "sha512-VDqfADTNvohwcY02NgxPb7OojIeDrNQ1q62r/DcM+bnIWY8LBi3nMTvdEaFEp6Bu4ejBIpHjJVthUEgnvGLemA==", "dev": true, "license": "MIT", "dependencies": { - "@types/readable-stream": "^4.0.5", - "@types/ws": "^8.5.9", + "@types/readable-stream": "^4.0.18", + "@types/ws": "^8.5.14", "commist": "^3.2.0", "concat-stream": "^2.0.0", - "debug": "^4.3.4", + "debug": "^4.4.0", "help-me": "^5.0.0", - "lru-cache": "^10.0.1", + "lru-cache": "^10.4.3", "minimist": "^1.2.8", - "mqtt": "^5.2.0", - "mqtt-packet": "^9.0.0", + "mqtt-packet": "^9.0.2", "number-allocator": "^1.0.14", - "readable-stream": "^4.4.2", + "readable-stream": "^4.7.0", "reinterval": "^1.1.0", - "rfdc": "^1.3.0", + "rfdc": "^1.4.1", + "socks": "^2.8.3", "split2": "^4.2.0", - "worker-timers": "^7.1.4", - "ws": "^8.14.2" + "worker-timers": "^7.1.8", + "ws": "^8.18.0" }, "bin": { "mqtt": "build/bin/mqtt.js", @@ -5875,9 +6097,9 @@ } }, "node_modules/mqtt-packet": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-9.0.1.tgz", - "integrity": "sha512-koZF1V/X2RZUI6uD9wN5OK1JxxcG1ofAR4H3LjCw1FkeKzruZQ26aAA6v2m1lZyWONZIR5wMMJFrZJDRNzbiQw==", + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-9.0.2.tgz", + "integrity": "sha512-MvIY0B8/qjq7bKxdN1eD+nrljoeaai+qjLJgfRn3TiMuz0pamsIWY2bFODPZMSNmabsLANXsLl4EMoWvlaTZWA==", "dev": true, "license": "MIT", "dependencies": { @@ -5894,9 +6116,9 @@ "license": "ISC" }, "node_modules/mqtt/node_modules/ws": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", - "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", + "version": "8.18.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", + "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", "dev": true, "license": "MIT", "engines": { @@ -5922,78 +6144,22 @@ "license": "MIT" }, "node_modules/multer": { - "version": "1.4.5-lts.1", - "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.5-lts.1.tgz", - "integrity": "sha512-ywPWvcDMeH+z9gQq5qYHCCy+ethsk4goepZ45GLD63fOu0YcNecQxi64nDs3qluZB+murG3/D4dJ7+dGctcCQQ==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/multer/-/multer-2.0.2.tgz", + "integrity": "sha512-u7f2xaZ/UG8oLXHvtF/oWTRvT44p9ecwBBqTwgJVq0+4BW1g8OW01TyMEGWBHbyMOYVHXslaut7qEQ1meATXgw==", "dev": true, "license": "MIT", "dependencies": { "append-field": "^1.0.0", - "busboy": "^1.0.0", - "concat-stream": "^1.5.2", - "mkdirp": "^0.5.4", + "busboy": "^1.6.0", + "concat-stream": "^2.0.0", + "mkdirp": "^0.5.6", "object-assign": "^4.1.1", - "type-is": "^1.6.4", - "xtend": "^4.0.0" + "type-is": "^1.6.18", + "xtend": "^4.0.2" }, "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/multer/node_modules/concat-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "dev": true, - "engines": [ - "node >= 0.8" - ], - "license": "MIT", - "dependencies": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" - } - }, - "node_modules/multer/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/multer/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dev": true, - "license": "MIT", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/multer/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true, - "license": "MIT" - }, - "node_modules/multer/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "license": "MIT", - "dependencies": { - "safe-buffer": "~5.1.0" + "node": ">= 10.16.0" } }, "node_modules/multicast-dns": { @@ -6116,24 +6282,24 @@ } }, "node_modules/node-red": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/node-red/-/node-red-4.0.8.tgz", - "integrity": "sha512-0A3qtJh27C9zWwzWe79QUIX0luDF9JxBPmqcIxaLNBgfQBtpQgEhSjz0zIR2NXWtLvBab8L2Ju7rQgnHn4iOXg==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/node-red/-/node-red-4.1.1.tgz", + "integrity": "sha512-yk8cornC+ELzbmQk8yw3KY1jS+djTMDupMOwZ85HeC+zcxJK0LNYUbJPCFI+Bm2NQny9pd863lNj9/tLwCDotg==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@node-red/editor-api": "4.0.8", - "@node-red/nodes": "4.0.8", - "@node-red/runtime": "4.0.8", - "@node-red/util": "4.0.8", + "@node-red/editor-api": "4.1.1", + "@node-red/nodes": "4.1.1", + "@node-red/runtime": "4.1.1", + "@node-red/util": "4.1.1", "basic-auth": "2.0.1", - "bcryptjs": "2.4.3", + "bcryptjs": "3.0.2", "cors": "2.8.5", "express": "4.21.2", - "fs-extra": "11.2.0", - "node-red-admin": "^4.0.1", + "fs-extra": "11.3.0", + "node-red-admin": "^4.1.2", "nopt": "5.0.0", - "semver": "7.6.3" + "semver": "7.7.1" }, "bin": { "node-red": "red.js", @@ -6143,19 +6309,19 @@ "node": ">=18.5" }, "optionalDependencies": { - "@node-rs/bcrypt": "1.10.4" + "@node-rs/bcrypt": "1.10.7" } }, "node_modules/node-red-admin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/node-red-admin/-/node-red-admin-4.0.1.tgz", - "integrity": "sha512-NLZgAM8JgFa/2/7Z4+nSSQrtkuBbfS9m+kxegadhHfuta5rErOx6zrrNhF+yAglMTPlVmdoqgso7VSt3nTRBGQ==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/node-red-admin/-/node-red-admin-4.1.2.tgz", + "integrity": "sha512-Yqe3dREfZZmc/BqT3Ntg0DEXivbP3HBNYCbjDkUaakkIIrapNR8TK1vj3RgkSW6FMtpfcVXBcLGI4cA0I1zbOw==", "dev": true, "license": "Apache-2.0", "dependencies": { "ansi-colors": "^4.1.3", - "axios": "^1.7.7", - "bcryptjs": "^2.4.3", + "axios": "1.12.2", + "bcryptjs": "3.0.2", "cli-table": "^0.3.11", "enquirer": "^2.3.6", "minimist": "^1.2.8", @@ -6169,28 +6335,42 @@ "node": ">=18" }, "optionalDependencies": { - "@node-rs/bcrypt": "1.10.4" + "@node-rs/bcrypt": "1.10.7" } }, "node_modules/node-red-node-test-helper": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/node-red-node-test-helper/-/node-red-node-test-helper-0.3.4.tgz", - "integrity": "sha512-OFXGEkKZpLkgoijAgpUIjzn5RF8QnbwPX9RjfI2LWXq1ACfeXkXcW0i1ioiphrokdE3MiWQJtH5omLNnSNdyaQ==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/node-red-node-test-helper/-/node-red-node-test-helper-0.3.5.tgz", + "integrity": "sha512-sUsg++CoO19UguqlK6j9q2VmluS7kpYgs45o+U3SAv4wW6BSoXwtuO7pJ+9KVQVmd27zwojw6uaeyLsDsRpL3Q==", "dev": true, + "license": "Apache-2.0", "dependencies": { - "body-parser": "^1.20.2", - "express": "^4.19.2", + "body-parser": "^1.20.3", + "express": "^4.21.0", "semver": "^7.5.4", "should": "^13.2.3", "should-sinon": "^0.0.6", "sinon": "^11.1.2", "stoppable": "^1.1.0", - "supertest": "^7.0.0" + "supertest": "^7.1.4" }, "engines": { "node": ">=14" } }, + "node_modules/node-red/node_modules/semver": { + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/node-watch": { "version": "0.7.4", "resolved": "https://registry.npmjs.org/node-watch/-/node-watch-0.7.4.tgz", @@ -6241,9 +6421,9 @@ } }, "node_modules/normalize-url": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-8.0.1.tgz", - "integrity": "sha512-IO9QvjUMWxPQQhs60oOu10CRkWCiZzSUkzbXGGV9pviYl1fXYcvkzQ5jV9z8Y6un8ARoVRl4EtC6v6jNqbaJ/w==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-8.1.0.tgz", + "integrity": "sha512-X06Mfd/5aKsRHc0O0J5CUedwnPmnDtLF2+nq+KN9KSDlJHkPuh0JUviWjEWMe0SW/9TDdSLVPuk7L5gGTIA1/w==", "dev": true, "license": "MIT", "engines": { @@ -6391,9 +6571,9 @@ } }, "node_modules/on-headers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", - "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.1.0.tgz", + "integrity": "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==", "dev": true, "license": "MIT", "engines": { @@ -6715,9 +6895,9 @@ } }, "node_modules/prettier": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.4.2.tgz", - "integrity": "sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==", + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz", + "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==", "dev": true, "license": "MIT", "bin": { @@ -7003,13 +7183,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/regenerator-runtime": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", - "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", - "dev": true, - "license": "MIT" - }, "node_modules/regexp.prototype.flags": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", @@ -7137,9 +7310,9 @@ } }, "node_modules/rimraf/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, "license": "MIT", "dependencies": { @@ -7147,9 +7320,9 @@ } }, "node_modules/rimraf/node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", "dev": true, "license": "ISC", "dependencies": { @@ -7237,9 +7410,9 @@ "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==" }, "node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -7540,6 +7713,32 @@ "node": ">=8" } }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks": { + "version": "2.8.7", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.7.tgz", + "integrity": "sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ip-address": "^10.0.1", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.0.0", + "npm": ">= 3.0.0" + } + }, "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -7753,20 +7952,21 @@ } }, "node_modules/superagent": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/superagent/-/superagent-9.0.2.tgz", - "integrity": "sha512-xuW7dzkUpcJq7QnhOsnNUgtYp3xRwpt2F7abdRYIpCsAt0hhUqia0EdxyXZQQpNmGtsCzYHryaKSV3q3GJnq7w==", + "version": "10.2.3", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-10.2.3.tgz", + "integrity": "sha512-y/hkYGeXAj7wUMjxRbB21g/l6aAEituGXM9Rwl4o20+SX3e8YOSV6BxFXl+dL3Uk0mjSL3kCbNkwURm8/gEDig==", "dev": true, + "license": "MIT", "dependencies": { - "component-emitter": "^1.3.0", + "component-emitter": "^1.3.1", "cookiejar": "^2.1.4", - "debug": "^4.3.4", + "debug": "^4.3.7", "fast-safe-stringify": "^2.1.1", - "form-data": "^4.0.0", - "formidable": "^3.5.1", + "form-data": "^4.0.4", + "formidable": "^3.5.4", "methods": "^1.1.2", "mime": "2.6.0", - "qs": "^6.11.0" + "qs": "^6.11.2" }, "engines": { "node": ">=14.18.0" @@ -7777,6 +7977,7 @@ "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", "dev": true, + "license": "MIT", "bin": { "mime": "cli.js" }, @@ -7785,13 +7986,14 @@ } }, "node_modules/supertest": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/supertest/-/supertest-7.0.0.tgz", - "integrity": "sha512-qlsr7fIC0lSddmA3tzojvzubYxvlGtzumcdHgPwbFWMISQwL22MhM2Y3LNt+6w9Yyx7559VW5ab70dgphm8qQA==", + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/supertest/-/supertest-7.1.4.tgz", + "integrity": "sha512-tjLPs7dVyqgItVFirHYqe2T+MfWc2VOBQ8QFKKbWTA3PU7liZR8zoSpAi/C1k1ilm9RsXIKYf197oap9wXGVYg==", "dev": true, + "license": "MIT", "dependencies": { "methods": "^1.1.2", - "superagent": "^9.0.1" + "superagent": "^10.2.3" }, "engines": { "node": ">=14.18.0" @@ -7822,19 +8024,19 @@ } }, "node_modules/synckit": { - "version": "0.8.8", - "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.8.tgz", - "integrity": "sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ==", + "version": "0.11.11", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.11.tgz", + "integrity": "sha512-MeQTA1r0litLUf0Rp/iisCaL8761lKAZHaimlbGK4j0HysC4PLfqygQj9srcs0m2RdtDYnF8UuYyKpbjHYp7Jw==", "dev": true, + "license": "MIT", "dependencies": { - "@pkgr/core": "^0.1.0", - "tslib": "^2.6.2" + "@pkgr/core": "^0.2.9" }, "engines": { "node": "^14.18.0 || >=16.0.0" }, "funding": { - "url": "https://opencollective.com/unts" + "url": "https://opencollective.com/synckit" } }, "node_modules/tar": { @@ -7899,22 +8101,22 @@ "license": "MIT" }, "node_modules/tldts": { - "version": "6.1.72", - "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.72.tgz", - "integrity": "sha512-QNtgIqSUb9o2CoUjX9T5TwaIvUUJFU1+12PJkgt42DFV2yf9J6549yTF2uGloQsJ/JOC8X+gIB81ind97hRiIQ==", + "version": "6.1.86", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.86.tgz", + "integrity": "sha512-WMi/OQ2axVTf/ykqCQgXiIct+mSQDFdH2fkwhPwgEwvJ1kSzZRiinb0zF2Xb8u4+OqPChmyI6MEu4EezNJz+FQ==", "dev": true, "license": "MIT", "dependencies": { - "tldts-core": "^6.1.72" + "tldts-core": "^6.1.86" }, "bin": { "tldts": "bin/cli.js" } }, "node_modules/tldts-core": { - "version": "6.1.72", - "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.72.tgz", - "integrity": "sha512-FW3H9aCaGTJ8l8RVCR3EX8GxsxDbQXuwetwwgXA2chYdsX+NY1ytCBl61narjjehWmCw92tc1AxlcY3668CU8g==", + "version": "6.1.86", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.86.tgz", + "integrity": "sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA==", "dev": true, "license": "MIT" }, @@ -7949,9 +8151,9 @@ } }, "node_modules/tough-cookie": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.1.0.tgz", - "integrity": "sha512-rvZUv+7MoBYTiDmFPBrhL7Ujx9Sk+q9wwm22x8c8T5IJaR+Wsyc7TNxbVxo84kZoRJZZMazowFLqpankBEQrGg==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.1.2.tgz", + "integrity": "sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -8125,10 +8327,11 @@ } }, "node_modules/uglify-js": { - "version": "3.17.4", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz", - "integrity": "sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==", + "version": "3.19.3", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", + "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==", "dev": true, + "license": "BSD-2-Clause", "bin": { "uglifyjs": "bin/uglifyjs" }, @@ -8157,16 +8360,18 @@ "license": "MIT" }, "node_modules/undici-types": { - "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", - "dev": true + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "dev": true, + "license": "MIT" }, "node_modules/universalify": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "dev": true, + "license": "MIT", "engines": { "node": ">= 10.0.0" } diff --git a/package.json b/package.json index 7b1f55ca..ae12a04a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "node-red-contrib-homekit-bridged", - "version": "1.7.3", + "version": "1.8.0-dev.0", "description": "Node-RED nodes to simulate Apple HomeKit devices.", "main": "build/nodes/nrchkb.js", "scripts": { @@ -43,20 +43,20 @@ "homepage": "https://github.com/NRCHKB/node-red-contrib-homekit-bridged#readme", "dependencies": { "@nrchkb/logger": "~3.1.1", - "hap-nodejs": "0.12.3", + "@homebridge/hap-nodejs": "2.0.2", "node-persist": "^3.1.3", - "semver": "~7.6.3", + "semver": "~7.7.3", "uuid": "~11.0.5" }, "devDependencies": { - "@homebridge/ciao": "~1.3.1", - "@node-red/registry": "^4.0.8", + "@homebridge/ciao": "~1.3.4", + "@node-red/registry": "^4.1.1", "@types/mocha": "^10.0.10", - "@types/node": "^18", + "@types/node": "^20", "@types/node-persist": "^3.1.8", "@types/node-red": "^1.3.5", - "@types/node-red-node-test-helper": "^0.3.4", - "@types/semver": "^7.5.8", + "@types/node-red-node-test-helper": "^0.3.5", + "@types/semver": "^7.7.1", "@types/uuid": "^10.0.0", "@typescript-eslint/eslint-plugin": "^7.16.0", "@typescript-eslint/parser": "^7.16.0", @@ -64,18 +64,18 @@ "del-cli": "^5.1.0", "eslint": "^8", "eslint-config-prettier": "^9.1.0", - "eslint-plugin-prettier": "^5.1.3", + "eslint-plugin-prettier": "^5.5.4", "eslint-plugin-simple-import-sort": "^12.1.1", - "husky": "^9.0.11", + "husky": "^9.1.7", "mocha": "^10.6.0", - "node-red": "^4.0.8", - "node-red-node-test-helper": "^0.3.4", - "prettier": "^3.4.2", + "node-red": "^4.1.1", + "node-red-node-test-helper": "^0.3.5", + "prettier": "^3.6.2", "ts-node": "^10.9.2", "typescript": "^5.7.3" }, "engines": { - "node": ">=18" + "node": "^20 || ^22 || ^24" }, "files": [ "/build", From 3b0d2f4a4c1bb5b7a945a455edb333045d996982 Mon Sep 17 00:00:00 2001 From: Shaquu Date: Sat, 22 Nov 2025 00:48:43 +0100 Subject: [PATCH 02/14] Camera is not working yet in this build! Due to major upgrade of hap-nodejs, some breaking changes might be present including Camera Service and MDNS Custom Configuration. --- CHANGELOG.md | 4 +- package.json | 4 +- src/lib/HAPHostNode.ts | 47 +- src/lib/HAPServiceNode.ts | 2 +- src/lib/HAPServiceNode2.ts | 2 +- src/lib/Storage.ts | 4 +- src/lib/api.ts | 12 +- src/lib/cameraSource/index.js | 575 ------------------ src/lib/hap/HAPCharacteristic.ts | 2 +- src/lib/hap/HAPService.ts | 2 +- src/lib/hap/eve-app/EveCharacteristics.ts | 2 +- src/lib/types/CustomCharacteristicType.ts | 2 +- src/lib/types/HAPHostConfigType.ts | 34 +- src/lib/types/HAPHostNodeType.ts | 4 +- src/lib/types/HAPServiceConfigType.ts | 2 +- src/lib/types/HAPServiceNodeType.ts | 11 +- .../hap-nodejs/BonjourMulticastOptions.ts | 11 - src/lib/types/storage/SerializedHostType.ts | 2 +- src/lib/utils/AccessoryUtils.ts | 4 +- src/lib/utils/CharacteristicUtils.ts | 6 +- src/lib/utils/CharacteristicUtils2.ts | 6 +- src/lib/utils/MdnsUtils.ts | 73 --- src/lib/utils/ServiceUtils.ts | 23 +- src/lib/utils/ServiceUtils2.ts | 25 +- src/lib/utils/index.ts | 2 - src/nodes/nrchkb.ts | 2 +- src/nodes/status.ts | 2 +- .../data/api.service.types.response.ts | 378 ++---------- 28 files changed, 108 insertions(+), 1135 deletions(-) delete mode 100644 src/lib/cameraSource/index.js delete mode 100644 src/lib/types/hap-nodejs/BonjourMulticastOptions.ts delete mode 100644 src/lib/utils/MdnsUtils.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 02807147..c1bd8284 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [1.8.0] - 2025-11-21 +## [2.0.0] - 2025-11-22 ### Changed @@ -18,6 +18,8 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - Dependencies upgrade - Node `18` no longer supported, use Node 24 [#578](https://github.com/NRCHKB/node-red-contrib-homekit-bridged/issues/578)! Or at least 20. +- Due to major upgrade of hap-nodejs, some breaking changes might be present including Camera Service and MDNS Custom + Configuration. ## [1.7.3] - 2025-01-16 diff --git a/package.json b/package.json index ae12a04a..e9beb891 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "node-red-contrib-homekit-bridged", - "version": "1.8.0-dev.0", + "version": "2.0.0-dev.0", "description": "Node-RED nodes to simulate Apple HomeKit devices.", "main": "build/nodes/nrchkb.js", "scripts": { @@ -8,7 +8,7 @@ "clean": "del-cli \"build/lib\" \"build/**/*.js\"", "test": "mocha -r ts-node/register './src/**/*.test.[tj]s' --exit --timeout 30000", "prettier": "prettier --write \"**/*.{js,ts}\"", - "eslint": "eslint \"src/**/*.ts\"", + "eslint": "eslint \"src/**/*.ts\" --fix", "prepare": "husky install" }, "repository": { diff --git a/src/lib/HAPHostNode.ts b/src/lib/HAPHostNode.ts index a00b173e..57b3a746 100644 --- a/src/lib/HAPHostNode.ts +++ b/src/lib/HAPHostNode.ts @@ -1,4 +1,3 @@ -import { logger } from '@nrchkb/logger' import { Accessory, Bridge, @@ -7,21 +6,19 @@ import { MDNSAdvertiser, Service, uuid, -} from 'hap-nodejs' +} from '@homebridge/hap-nodejs' +import { logger } from '@nrchkb/logger' import { NodeAPI } from 'node-red' import { SemVer } from 'semver' import semver from 'semver/preload' import NRCHKBError from './NRCHKBError' -import BonjourMulticastOptions from './types/hap-nodejs/BonjourMulticastOptions' import HapCategories from './types/hap-nodejs/HapCategories' import HAPHostConfigType from './types/HAPHostConfigType' import HAPHostNodeType from './types/HAPHostNodeType' import HostType from './types/HostType' module.exports = (RED: NodeAPI, hostType: HostType) => { - const MdnsUtils = require('./utils/MdnsUtils')() - const init = function (this: HAPHostNodeType, config: HAPHostConfigType) { const self = this const log = logger('NRCHKB', 'HAPHostNode', config.bridgeName, self) @@ -41,40 +38,6 @@ module.exports = (RED: NodeAPI, hostType: HostType) => { config.firmwareRev = new SemVer('0.0.0') } - if (!config.bind?.length && config.customMdnsConfig) { - log.error('Custom mdns config is deprecated, use bind instead!') - - self.mdnsConfig = {} as BonjourMulticastOptions - - if (MdnsUtils.checkMulticast(config.mdnsMulticast)) { - self.mdnsConfig.multicast = config.mdnsMulticast - } - - if (MdnsUtils.checkInterface(config.mdnsInterface)) { - self.mdnsConfig.interface = config.mdnsInterface - } - - if (MdnsUtils.checkPort(config.mdnsPort)) { - self.mdnsConfig.port = parseInt(config.mdnsPort?.toString()) - } - - if (MdnsUtils.checkIp(config.mdnsIp)) { - self.mdnsConfig.ip = config.mdnsIp - } - - if (MdnsUtils.checkTtl(config.mdnsTtl)) { - self.mdnsConfig.ttl = parseInt(config.mdnsTtl?.toString()) - } - - if (MdnsUtils.checkLoopback(config.mdnsLoopback)) { - self.mdnsConfig.loopback = config.mdnsLoopback - } - - if (MdnsUtils.checkReuseAddr(config.mdnsReuseAddr)) { - self.mdnsConfig.reuseAddr = config.mdnsReuseAddr - } - } - self.accessoryCategory = (self.hostType == HostType.BRIDGE ? HapCategories.BRIDGE : self.config.accessoryCategory) as unknown as Categories @@ -112,10 +75,7 @@ module.exports = (RED: NodeAPI, hostType: HostType) => { ) } - if ( - (self.config.port && self.config.port == 1880) || - (self.mdnsConfig?.port && self.mdnsConfig?.port == 1880) - ) { + if (self.config.port && self.config.port == 1880) { log.error( `Cannot publish on ${hostTypeName} port 1880 as it is reserved for node-red` ) @@ -149,7 +109,6 @@ module.exports = (RED: NodeAPI, hostType: HostType) => { : 0, pincode: oldPinCode, category: self.accessoryCategory, - mdns: self.mdnsConfig, bind: bind, advertiser: self.config.advertiser ?? MDNSAdvertiser.BONJOUR, diff --git a/src/lib/HAPServiceNode.ts b/src/lib/HAPServiceNode.ts index 759736de..7d96f496 100644 --- a/src/lib/HAPServiceNode.ts +++ b/src/lib/HAPServiceNode.ts @@ -1,5 +1,5 @@ +import { uuid } from '@homebridge/hap-nodejs' import { logger } from '@nrchkb/logger' -import { uuid } from 'hap-nodejs' import { NodeAPI } from 'node-red' import NRCHKBError from './NRCHKBError' diff --git a/src/lib/HAPServiceNode2.ts b/src/lib/HAPServiceNode2.ts index 230dbcaf..a8a77629 100644 --- a/src/lib/HAPServiceNode2.ts +++ b/src/lib/HAPServiceNode2.ts @@ -1,5 +1,5 @@ +import { uuid } from '@homebridge/hap-nodejs' import { logger } from '@nrchkb/logger' -import { uuid } from 'hap-nodejs' import { NodeAPI } from 'node-red' import NRCHKBError from './NRCHKBError' diff --git a/src/lib/Storage.ts b/src/lib/Storage.ts index d9186d7b..cb538254 100644 --- a/src/lib/Storage.ts +++ b/src/lib/Storage.ts @@ -1,9 +1,9 @@ -import { logger } from '@nrchkb/logger' import { CharacteristicEventTypes, SerializedAccessory, SerializedService, -} from 'hap-nodejs' +} from '@homebridge/hap-nodejs' +import { logger } from '@nrchkb/logger' import storage, { InitOptions } from 'node-persist' import path from 'path' import { diff --git a/src/lib/api.ts b/src/lib/api.ts index ce9dfa59..ecda48cb 100644 --- a/src/lib/api.ts +++ b/src/lib/api.ts @@ -1,6 +1,11 @@ +import { + Characteristic, + Perms, + SerializedService, + Service, +} from '@homebridge/hap-nodejs' import { logger } from '@nrchkb/logger' import express from 'express' -import { Characteristic, Perms, SerializedService, Service } from 'hap-nodejs' import { NodeAPI } from 'node-red' import EveCharacteristics from './hap/eve-app/EveCharacteristics' @@ -37,7 +42,10 @@ module.exports = function (RED: NodeAPI) { BridgingState: { nrchkbDisabledText: 'BridgingState (deprecated, unused)', }, - // CameraControl: {}, // This service is deprecated but used by nrchkb to link rtsp logic + CameraControl: { + //TODO: hmm, what is the replacement? + nrchkbDisabledText: 'CameraControl (deprecated, replaced by)', + }, CameraEventRecordingManagement: { nrchkbDisabledText: 'CameraEventRecordingManagement (deprecated, replaced by CameraRecordingManagement)', diff --git a/src/lib/cameraSource/index.js b/src/lib/cameraSource/index.js deleted file mode 100644 index 1bc19889..00000000 --- a/src/lib/cameraSource/index.js +++ /dev/null @@ -1,575 +0,0 @@ -import { logger } from '@nrchkb/logger' -import * as util from 'util' - -const HapNodeJS = require('hap-nodejs') -const uuid = HapNodeJS.uuid -const StreamController = HapNodeJS.StreamController - -const crypto = require('crypto') -const fs = require('fs') -const os = require('os') -const spawn = require('child_process').spawn - -const log = logger('CameraSource') - -module.exports = { - Camera: Camera, -} - -function Camera(cameraControlService, config, cameraNode) { - this.configure(config, cameraControlService) - this.cameraNode = cameraNode -} - -Camera.prototype.configure = function (config, cameraControlService) { - this.name = config.name - this.vcodec = config.cameraConfigVideoCodec - this.videoProcessor = config.cameraConfigVideoProcessor - this.audio = config.cameraConfigAudio - this.acodec = config.cameraConfigAudioCodec - this.packetsize = config.cameraConfigPacketSize - this.fps = config.cameraConfigMaxFPS - this.maxBitrate = config.cameraConfigMaxBitrate - this.debug = config.cameraConfigDebug - this.additionalCommandline = config.cameraConfigAdditionalCommandLine - this.vflip = config.cameraConfigVerticalFlip - this.hflip = config.cameraConfigHorizontalFlip - this.mapvideo = config.cameraConfigMapVideo - this.mapaudio = config.cameraConfigMapAudio - this.videoFilter = config.cameraConfigVideoFilter - this.uploader = config.cameraConfigSnapshotOutput - this.interfaceName = config.cameraConfigInterfaceName - - if (!config.cameraConfigSource) { - throw new NRCHKBError('Missing source for camera.') - } - - if (this.interfaceName !== '') { - if ( - !Object.keys(require('os').networkInterfaces()).includes( - this.interfaceName - ) - ) { - throw new NRCHKBError('Incorrect interface name for camera.') - } - } - - this.ffmpegSource = config.cameraConfigSource - this.ffmpegImageSource = config.cameraConfigStillImageSource - - this.services = [] - this.streamControllers = [] - - this.pendingSessions = {} - this.ongoingSessions = {} - - const numberOfStreams = config.cameraConfigMaxStreams - const videoResolutions = [] - - this.maxWidth = config.cameraConfigMaxWidth - this.maxHeight = config.cameraConfigMaxHeight - const maxFPS = this.fps > 30 ? 30 : this.fps - - if (this.maxWidth >= 320) { - if (this.maxHeight >= 240) { - videoResolutions.push([320, 240, maxFPS]) - if (maxFPS > 15) { - videoResolutions.push([320, 240, 15]) - } - } - - if (this.maxHeight >= 180) { - videoResolutions.push([320, 180, maxFPS]) - if (maxFPS > 15) { - videoResolutions.push([320, 180, 15]) - } - } - } - - if (this.maxWidth >= 480) { - if (this.maxHeight >= 360) { - videoResolutions.push([480, 360, maxFPS]) - } - - if (this.maxHeight >= 270) { - videoResolutions.push([480, 270, maxFPS]) - } - } - - if (this.maxWidth >= 640) { - if (this.maxHeight >= 480) { - videoResolutions.push([640, 480, maxFPS]) - } - - if (this.maxHeight >= 360) { - videoResolutions.push([640, 360, maxFPS]) - } - } - - if (this.maxWidth >= 1280) { - if (this.maxHeight >= 960) { - videoResolutions.push([1280, 960, maxFPS]) - } - - if (this.maxHeight >= 720) { - videoResolutions.push([1280, 720, maxFPS]) - } - } - - if (this.maxWidth >= 1920) { - if (this.maxHeight >= 1080) { - videoResolutions.push([1920, 1080, maxFPS]) - } - } - - let options = { - proxy: false, // Requires RTP/RTCP MUX Proxy TODO: Should I make it configurable? - srtp: true, // Supports SRTP AES_CM_128_HMAC_SHA1_80 encryption TODO: Should I make it configurable? - video: { - resolutions: videoResolutions, - codec: { - profiles: [0, 1, 2], // Enum, please refer StreamController.VideoCodecParamProfileIDTypes TODO: Should I make it configurable? - levels: [0, 1, 2], // Enum, please refer StreamController.VideoCodecParamLevelTypes TODO: Should I make it configurable? - }, - }, - audio: { - codecs: [ - { - type: 'OPUS', // Audio Codec TODO: Should I make it configurable? - samplerate: 24, // 8, 16, 24 KHz TODO: Should I make it configurable? - }, - { - type: 'AAC-eld', // TODO: Should I make it configurable? - samplerate: 16, // TODO: Should I make it configurable? - }, - ], - }, - } - - if (cameraControlService) { - this._createStreamControllers( - cameraControlService, - numberOfStreams, - options - ) - } else { - log.error( - 'Camera reconfigure on the fly is not yet supported. ' + - 'Please restart node-red to apply all changes to the Camera.' - ) - } -} - -Camera.prototype.handleCloseConnection = function (connectionID) { - this.streamControllers.forEach(function (controller) { - controller.handleCloseConnection(connectionID) - }) -} - -Camera.prototype.handleSnapshotRequest = function (request, callback) { - let resolution = request.width + 'x' + request.height - - let imageSource = this.ffmpegImageSource - - if (imageSource === undefined || !imageSource.trim()) { - imageSource = this.ffmpegSource - } - - let ffmpeg = spawn( - this.videoProcessor, - (imageSource + ' -t 1 -s ' + resolution + ' -f image2 -').split(' '), - { env: process.env } - ) - let imageBuffer = Buffer.alloc(0) - - log.debug('Snapshot from ' + this.name + ' at ' + resolution) - log.debug( - 'ffmpeg ' + imageSource + ' -t 1 -s ' + resolution + ' -f image2 -' - ) - - ffmpeg.stdout.on('data', function (data) { - imageBuffer = Buffer.concat([imageBuffer, data]) - }) - - ffmpeg.on('error', function (error) { - log.error('An error occurs while making snapshot request') - log.error(util.inspect(error)) - }) - - ffmpeg.on( - 'close', - // eslint-disable-next-line @typescript-eslint/no-unused-vars - function (code) { - let msg - - if (this.cameraNode) { - const topic = this.cameraNode.topic - ? this.cameraNode.topic - : this.cameraNode.topic_in - msg = { payload: {}, name: this.cameraNode.name, topic: topic } - } - - if (this.uploader !== 'disabled' && !this.cameraNode) { - log.error('Node required for camera to send snapshot!') - } else if (this.uploader === 'path') { - const filePath = - __dirname + '/../../cameraSnapshots/' + new Date().getTime() - log.debug('Saving camera snapshot to: ' + filePath) - - const self = this - - fs.writeFile(filePath, imageBuffer, function (err) { - if (err) { - log.error( - 'Camera snapshot file failed to save due to: ' + err - ) - return - } - - msg.payload['cameraSnapshot'] = filePath - log.debug( - 'Camera snapshot file has been saved! Sending to output... ' + - JSON.stringify(msg) - ) - self.cameraNode.send([null, msg]) - }) - } else if (this.uploader === 'content') { - msg.payload['cameraSnapshot'] = imageBuffer - log.debug( - 'Sending camera snapshot buffer to output...' + - JSON.stringify(msg) - ) - this.cameraNode.send([null, null, msg]) - } - - callback(undefined, imageBuffer) - }.bind(this) - ) -} - -Camera.prototype.prepareStream = function (request, callback) { - const sessionInfo = {} - - let sessionID = request['sessionID'] - sessionInfo['address'] = request['targetAddress'] - - const response = {} - - let videoInfo = request['video'] - if (videoInfo) { - let targetPort = videoInfo['port'] - let srtp_key = videoInfo['srtp_key'] - let srtp_salt = videoInfo['srtp_salt'] - - // SSRC is a 32 bit integer that is unique per stream - let ssrcSource = crypto.randomBytes(4) - ssrcSource[0] = 0 - let ssrc = ssrcSource.readInt32BE(0, true) - - response['video'] = { - port: targetPort, - ssrc: ssrc, - srtp_key: srtp_key, - srtp_salt: srtp_salt, - } - - sessionInfo['video_port'] = targetPort - sessionInfo['video_srtp'] = Buffer.concat([srtp_key, srtp_salt]) - sessionInfo['video_ssrc'] = ssrc - } - - let audioInfo = request['audio'] - if (audioInfo) { - let targetPort = audioInfo['port'] - let srtp_key = audioInfo['srtp_key'] - let srtp_salt = audioInfo['srtp_salt'] - - // SSRC is a 32 bit integer that is unique per stream - let ssrcSource = crypto.randomBytes(4) - ssrcSource[0] = 0 - let ssrc = ssrcSource.readInt32BE(0, true) - - response['audio'] = { - port: targetPort, - ssrc: ssrc, - srtp_key: srtp_key, - srtp_salt: srtp_salt, - } - - sessionInfo['audio_port'] = targetPort - sessionInfo['audio_srtp'] = Buffer.concat([srtp_key, srtp_salt]) - sessionInfo['audio_ssrc'] = ssrc - } - - const networkInterfaces = os.networkInterfaces() - - if (this.interfaceName && networkInterfaces[this.interfaceName]) { - const currentAddress = networkInterfaces[this.interfaceName] - - if (currentAddress?.[0]) { - response['address'] = { - address: currentAddress[0].address, - type: currentAddress[0].family === 'IPv4' ? 'v4' : 'v6', - } - } - } - - this.pendingSessions[uuid.unparse(sessionID)] = sessionInfo - - callback(response) -} - -Camera.prototype.handleStreamRequest = function (request) { - const sessionID = request['sessionID'] - const requestType = request['type'] - if (sessionID) { - let sessionIdentifier = uuid.unparse(sessionID) - - log.debug('Request type: ' + requestType) - - if (requestType === 'start') { - const sessionInfo = this.pendingSessions[sessionIdentifier] - if (sessionInfo) { - let width = 1280 - let height = 720 - let fps = this.fps || 30 - let vbitrate = this.maxBitrate - let abitrate = 32 - let asamplerate = 16 - const vcodec = this.vcodec - const acodec = this.acodec - const packetsize = this.packetsize || 1316 - const additionalCommandline = this.additionalCommandline - const mapvideo = this.mapvideo - const mapaudio = this.mapaudio - - let videoInfo = request['video'] - if (videoInfo) { - width = videoInfo['width'] - height = videoInfo['height'] - - let expectedFPS = videoInfo['fps'] - if (expectedFPS < fps) { - fps = expectedFPS - } - if (videoInfo['max_bit_rate'] < vbitrate) { - vbitrate = videoInfo['max_bit_rate'] - } - } - - let audioInfo = request['audio'] - if (audioInfo) { - abitrate = audioInfo['max_bit_rate'] - asamplerate = audioInfo['sample_rate'] - } - - let targetAddress = sessionInfo['address'] - let targetVideoPort = sessionInfo['video_port'] - let videoKey = sessionInfo['video_srtp'] - let videoSsrc = sessionInfo['video_ssrc'] - let targetAudioPort = sessionInfo['audio_port'] - let audioKey = sessionInfo['audio_srtp'] - let audioSsrc = sessionInfo['audio_ssrc'] - let vf = [] - - // Skip vf entirely if videoFilter is empty - if (this.videoFilter !== null && this.videoFilter !== '') { - vf.push(this.videoFilter) - - if (this.hflip) vf.push('hflip') - - if (this.vflip) vf.push('vflip') - } - - let fcmd = this.ffmpegSource - - let ffmpegVideoArgs = - ' -map ' + - mapvideo + - ' -vcodec ' + - vcodec + - ' -pix_fmt yuv420p' + - ' -r ' + - fps + - ' -f rawvideo' + - (additionalCommandline ? ' ' + additionalCommandline : '') + - (vf.length > 0 ? ' -vf ' + vf.join(',') : '') + - ' -b:v ' + - vbitrate + - 'k' + - ' -bufsize ' + - vbitrate + - 'k' + - ' -maxrate ' + - vbitrate + - 'k' + - ' -payload_type 99' - - let ffmpegVideoStream = - ' -ssrc ' + - videoSsrc + - ' -f rtp' + - ' -srtp_out_suite AES_CM_128_HMAC_SHA1_80' + - ' -srtp_out_params ' + - videoKey.toString('base64') + - ' srtp://' + - targetAddress + - ':' + - targetVideoPort + - '?rtcpport=' + - targetVideoPort + - '&localrtcpport=' + - targetVideoPort + - '&pkt_size=' + - packetsize - - // build required video arguments - fcmd += ffmpegVideoArgs - fcmd += ffmpegVideoStream - - // build optional audio arguments - if (this.audio) { - let ffmpegAudioArgs = - ' -map ' + - mapaudio + - ' -acodec ' + - acodec + - ' -profile:a aac_eld' + - ' -flags +global_header' + - ' -f null' + - ' -ar ' + - asamplerate + - 'k' + - ' -b:a ' + - abitrate + - 'k' + - ' -bufsize ' + - abitrate + - 'k' + - ' -ac 1' + - ' -payload_type 110' - - let ffmpegAudioStream = - ' -ssrc ' + - audioSsrc + - ' -f rtp' + - ' -srtp_out_suite AES_CM_128_HMAC_SHA1_80' + - ' -srtp_out_params ' + - audioKey.toString('base64') + - ' srtp://' + - targetAddress + - ':' + - targetAudioPort + - '?rtcpport=' + - targetAudioPort + - '&localrtcpport=' + - targetAudioPort + - '&pkt_size=' + - packetsize - - fcmd += ffmpegAudioArgs - fcmd += ffmpegAudioStream - } - - if (this.debug) { - fcmd += ' -loglevel debug' - } - - let ffmpeg = spawn(this.videoProcessor, fcmd.split(' '), { - env: process.env, - }) - log.debug( - 'Start streaming video from ' + - this.name + - ' with ' + - width + - 'x' + - height + - '@' + - vbitrate + - 'kBit' - ) - log.debug('ffmpeg ' + fcmd) - - ffmpeg.stderr.on( - 'data', - function (data) { - log.debug('ffmpeg data: ' + data.toString()) - }.bind(this) - ) - - let self = this - - ffmpeg.on('error', function (error) { - log.error('An error occurred while making stream request') - log.error(util.inspect(error)) - }) - - ffmpeg.on('close', (code) => { - if (code == null || code === 0 || code === 255) { - log.debug('Stopped streaming') - } else { - log.error('ERROR: FFmpeg exited with code ' + code) - - for ( - let i = 0; - i < self.streamControllers.length; - i++ - ) { - const controller = self.streamControllers[i] - if (controller.sessionIdentifier === sessionID) { - controller.forceStop() - } - } - } - }) - this.ongoingSessions[sessionIdentifier] = ffmpeg - } - - delete this.pendingSessions[sessionIdentifier] - } else if (requestType === 'stop') { - const ffmpegProcess = this.ongoingSessions[sessionIdentifier] - - if (ffmpegProcess) { - ffmpegProcess.kill('SIGTERM') - } - - delete this.ongoingSessions[sessionIdentifier] - } else if (requestType === 'reconfigure') { - //TODO: What to do here? - } - } -} - -Camera.prototype._createStreamControllers = function ( - cameraControlService, - maxStreams, - options -) { - let self = this - - log.debug('Configuring services for Camera...') - - self.services.push(cameraControlService) - log.debug('...added CameraControl Service') - - if (self.audio) { - log.debug('...audio available') - } else { - log.debug('...audio not available') - } - - log.debug( - 'Creating Camera Stream Controllers: ' + maxStreams + ' - Started' - ) - log.debug('Camera options: ' + JSON.stringify(options)) - - for (let i = 0; i < maxStreams; i++) { - const streamController = new StreamController(i, options, self) - - self.services.push(streamController.service) - self.streamControllers.push(streamController) - } - - log.debug('Creating Camera Stream Controllers - Finished') -} diff --git a/src/lib/hap/HAPCharacteristic.ts b/src/lib/hap/HAPCharacteristic.ts index 569f1898..02bd0101 100644 --- a/src/lib/hap/HAPCharacteristic.ts +++ b/src/lib/hap/HAPCharacteristic.ts @@ -1,4 +1,4 @@ -import { Characteristic } from 'hap-nodejs' +import { Characteristic } from '@homebridge/hap-nodejs' import { EveS2R1, diff --git a/src/lib/hap/HAPService.ts b/src/lib/hap/HAPService.ts index f6b45d26..3500384b 100644 --- a/src/lib/hap/HAPService.ts +++ b/src/lib/hap/HAPService.ts @@ -1,4 +1,4 @@ -import { Service } from 'hap-nodejs' +import { Service } from '@homebridge/hap-nodejs' import { EveHistoryData } from './eve-app/EveServices' diff --git a/src/lib/hap/eve-app/EveCharacteristics.ts b/src/lib/hap/eve-app/EveCharacteristics.ts index cf70784e..ceaf94a7 100644 --- a/src/lib/hap/eve-app/EveCharacteristics.ts +++ b/src/lib/hap/eve-app/EveCharacteristics.ts @@ -1,4 +1,4 @@ -import { Formats, Perms } from 'hap-nodejs/dist/lib/Characteristic' +import { Formats, Perms } from '@homebridge/hap-nodejs/dist/lib/Characteristic' import CustomCharacteristicType from '../../types/CustomCharacteristicType' import HAPCharacteristic from '../HAPCharacteristic' diff --git a/src/lib/types/CustomCharacteristicType.ts b/src/lib/types/CustomCharacteristicType.ts index f5bd1093..7a70d020 100644 --- a/src/lib/types/CustomCharacteristicType.ts +++ b/src/lib/types/CustomCharacteristicType.ts @@ -1,4 +1,4 @@ -import { CharacteristicProps } from 'hap-nodejs' +import { CharacteristicProps } from '@homebridge/hap-nodejs' type CustomCharacteristicType = CharacteristicProps & { UUID?: string diff --git a/src/lib/types/HAPHostConfigType.ts b/src/lib/types/HAPHostConfigType.ts index 8a9b2d72..606696da 100644 --- a/src/lib/types/HAPHostConfigType.ts +++ b/src/lib/types/HAPHostConfigType.ts @@ -1,4 +1,4 @@ -import { MDNSAdvertiser } from 'hap-nodejs' +import { MDNSAdvertiser } from '@homebridge/hap-nodejs' import { NodeDef } from 'node-red' import { SemVer } from 'semver' @@ -17,38 +17,6 @@ type HAPHostConfigType = NodeDef & { softwareRev: SemVer bind?: string bindType?: 'json' | 'str' - /** - * @deprecated use bind instead - */ - customMdnsConfig: boolean - /** - * @deprecated use bind instead - */ - mdnsMulticast: boolean - /** - * @deprecated use bind instead - */ - mdnsInterface: string - /** - * @deprecated use bind instead - */ - mdnsPort: number - /** - * @deprecated use bind instead - */ - mdnsIp: string - /** - * @deprecated use bind instead - */ - mdnsTtl: number - /** - * @deprecated use bind instead - */ - mdnsLoopback: boolean - /** - * @deprecated use bind instead - */ - mdnsReuseAddr: boolean allowMessagePassthrough: boolean accessoryCategory: HapCategories advertiser: MDNSAdvertiser diff --git a/src/lib/types/HAPHostNodeType.ts b/src/lib/types/HAPHostNodeType.ts index 83360a4d..0bc12592 100644 --- a/src/lib/types/HAPHostNodeType.ts +++ b/src/lib/types/HAPHostNodeType.ts @@ -1,13 +1,11 @@ -import { Accessory, Categories } from 'hap-nodejs' +import { Accessory, Categories } from '@homebridge/hap-nodejs' -import BonjourMulticastOptions from './hap-nodejs/BonjourMulticastOptions' import HAPHostConfigType from './HAPHostConfigType' import HostType from './HostType' import NodeType from './NodeType' type HAPHostNodeType = NodeType & { config: HAPHostConfigType - mdnsConfig: BonjourMulticastOptions accessoryCategory: Categories published: boolean bridgeUsername: string diff --git a/src/lib/types/HAPServiceConfigType.ts b/src/lib/types/HAPServiceConfigType.ts index 8a12de8e..e8f9540b 100644 --- a/src/lib/types/HAPServiceConfigType.ts +++ b/src/lib/types/HAPServiceConfigType.ts @@ -1,4 +1,4 @@ -import { AdaptiveLightingControllerMode } from 'hap-nodejs/dist/lib/controller/AdaptiveLightingController' +import { AdaptiveLightingControllerMode } from '@homebridge/hap-nodejs/dist/lib/controller/AdaptiveLightingController' import { NodeDef } from 'node-red' import CameraConfigType from './CameraConfigType' diff --git a/src/lib/types/HAPServiceNodeType.ts b/src/lib/types/HAPServiceNodeType.ts index 6f7e9e23..92f01c86 100644 --- a/src/lib/types/HAPServiceNodeType.ts +++ b/src/lib/types/HAPServiceNodeType.ts @@ -8,8 +8,9 @@ import { CharacteristicSetCallback, CharacteristicValue, Service, -} from 'hap-nodejs' -import { HAPConnection } from 'hap-nodejs/dist/lib/util/eventedhttp' +} from '@homebridge/hap-nodejs' +import { CharacteristicContext } from '@homebridge/hap-nodejs/dist/lib/Characteristic' +import { HAPConnection } from '@homebridge/hap-nodejs/dist/lib/util/eventedhttp' import { NodeAPI } from 'node-red' import { NodeStatusUtils } from '../utils/NodeStatusUtils' @@ -39,14 +40,14 @@ type HAPServiceNodeType = NodeType & { onCharacteristicGet: ( this: Characteristic, callback: CharacteristicGetCallback, - context: any, + context: CharacteristicContext, connection?: HAPConnection ) => void onCharacteristicSet: ( this: Characteristic, - newValue: CharacteristicValue, + value: CharacteristicValue, callback: CharacteristicSetCallback, - context: any, + context: CharacteristicContext, connection?: HAPConnection ) => void onCharacteristicChange: ( diff --git a/src/lib/types/hap-nodejs/BonjourMulticastOptions.ts b/src/lib/types/hap-nodejs/BonjourMulticastOptions.ts deleted file mode 100644 index aa6dc31b..00000000 --- a/src/lib/types/hap-nodejs/BonjourMulticastOptions.ts +++ /dev/null @@ -1,11 +0,0 @@ -type BonjourMulticastOptions = { - multicast?: boolean - interface?: string - port?: number - ip?: string - ttl?: number - loopback?: boolean - reuseAddr?: boolean -} - -export default BonjourMulticastOptions diff --git a/src/lib/types/storage/SerializedHostType.ts b/src/lib/types/storage/SerializedHostType.ts index 147244f1..1a8544bd 100644 --- a/src/lib/types/storage/SerializedHostType.ts +++ b/src/lib/types/storage/SerializedHostType.ts @@ -1,4 +1,4 @@ -import { SerializedAccessory } from 'hap-nodejs' +import { SerializedAccessory } from '@homebridge/hap-nodejs' type SerializedHostType = { _isBridge: boolean diff --git a/src/lib/utils/AccessoryUtils.ts b/src/lib/utils/AccessoryUtils.ts index ef7884e0..86989e1e 100644 --- a/src/lib/utils/AccessoryUtils.ts +++ b/src/lib/utils/AccessoryUtils.ts @@ -1,11 +1,11 @@ +import { Accessory, Service } from '@homebridge/hap-nodejs' import { logger } from '@nrchkb/logger' -import { Accessory, Service } from 'hap-nodejs' import AccessoryInformationType from '../types/AccessoryInformationType' import HAPServiceNodeType from '../types/HAPServiceNodeType' module.exports = function (node: HAPServiceNodeType) { - const HapNodeJS = require('hap-nodejs') + const HapNodeJS = require('@homebridge/hap-nodejs') const Accessory = HapNodeJS.Accessory const Service = HapNodeJS.Service const Characteristic = HapNodeJS.Characteristic diff --git a/src/lib/utils/CharacteristicUtils.ts b/src/lib/utils/CharacteristicUtils.ts index 778b30bc..978e3f57 100644 --- a/src/lib/utils/CharacteristicUtils.ts +++ b/src/lib/utils/CharacteristicUtils.ts @@ -1,5 +1,9 @@ +import { + Characteristic, + CharacteristicProps, + Service, +} from '@homebridge/hap-nodejs' import { logger } from '@nrchkb/logger' -import { Characteristic, CharacteristicProps, Service } from 'hap-nodejs' import HAPServiceConfigType from '../types/HAPServiceConfigType' import HAPServiceNodeType from '../types/HAPServiceNodeType' diff --git a/src/lib/utils/CharacteristicUtils2.ts b/src/lib/utils/CharacteristicUtils2.ts index f79737e5..e412c1a3 100644 --- a/src/lib/utils/CharacteristicUtils2.ts +++ b/src/lib/utils/CharacteristicUtils2.ts @@ -1,5 +1,9 @@ +import { + Characteristic, + CharacteristicProps, + Service, +} from '@homebridge/hap-nodejs' import { logger } from '@nrchkb/logger' -import { Characteristic, CharacteristicProps, Service } from 'hap-nodejs' import HAPService2ConfigType from '../types/HAPService2ConfigType' import HAPService2NodeType from '../types/HAPService2NodeType' diff --git a/src/lib/utils/MdnsUtils.ts b/src/lib/utils/MdnsUtils.ts deleted file mode 100644 index e43a1ec4..00000000 --- a/src/lib/utils/MdnsUtils.ts +++ /dev/null @@ -1,73 +0,0 @@ -import * as net from 'net' -import * as os from 'os' - -const MdnsUtils = () => { - let availableInterfaces: string[] - - const checkIp = function (value: string) { - return value.length > 0 && net.isIP(value) - } - - const checkInterface = function (value: string) { - if (value.length < 1) { - return false - } - - if (!availableInterfaces) { - availableInterfaces = [] - - const networkInterfaces = os.networkInterfaces() - - Object.keys(networkInterfaces).forEach((key) => - networkInterfaces[key]?.forEach((networkInterface) => - availableInterfaces.push(networkInterface.address) - ) - ) - } - - return availableInterfaces.indexOf(value) > -1 - } - - const checkMulticast = function (value: any) { - return checkBoolean(value) - } - - const checkPort = function (value: string) { - return value.length > 0 && checkNumber(value) - } - - const checkLoopback = function (value: any) { - return checkBoolean(value) - } - - const checkReuseAddr = function (value: any) { - return checkBoolean(value) - } - - const checkTtl = function (value: string) { - if (value.length > 0 && checkNumber(value)) { - const ttlInt = parseInt(value) - return ttlInt >= 0 && ttlInt <= 255 - } else return false - } - - const checkBoolean = function (value: any) { - return typeof value === 'boolean' - } - - const checkNumber = function (value: any) { - return !isNaN(value) - } - - return { - checkInterface, - checkIp, - checkMulticast, - checkPort, - checkLoopback, - checkReuseAddr, - checkTtl, - } -} - -module.exports = MdnsUtils diff --git a/src/lib/utils/ServiceUtils.ts b/src/lib/utils/ServiceUtils.ts index 4b8db647..158832fe 100644 --- a/src/lib/utils/ServiceUtils.ts +++ b/src/lib/utils/ServiceUtils.ts @@ -1,6 +1,5 @@ import * as util from 'node:util' -import { logger } from '@nrchkb/logger' import { Accessory, ActiveAdaptiveLightingTransition, @@ -15,8 +14,9 @@ import { HAPStatus, HapStatusError, Service, -} from 'hap-nodejs' -import { HAPConnection } from 'hap-nodejs/dist/lib/util/eventedhttp' +} from '@homebridge/hap-nodejs' +import { HAPConnection } from '@homebridge/hap-nodejs/dist/lib/util/eventedhttp' +import { logger } from '@nrchkb/logger' import NRCHKBError from '../NRCHKBError' import HAPServiceConfigType from '../types/HAPServiceConfigType' @@ -25,12 +25,10 @@ import HAPServiceNodeType from '../types/HAPServiceNodeType' module.exports = function (node: HAPServiceNodeType) { const log = logger('NRCHKB', 'ServiceUtils', node.config.name, node) - const HapNodeJS = require('hap-nodejs') + const HapNodeJS = require('@homebridge/hap-nodejs') const Service = HapNodeJS.Service const Characteristic = HapNodeJS.Characteristic - const CameraSource = require('../cameraSource').Camera - const NO_RESPONSE_MSG = 'NO_RESPONSE' const prepareHapData = (context?: any, connection?: HAPConnection) => { @@ -291,7 +289,7 @@ module.exports = function (node: HAPServiceNodeType) { ) if (context !== null) { - characteristic.setValue(value, undefined, context) + characteristic.setValue(value, context) } else { characteristic.setValue(value) } @@ -405,8 +403,8 @@ module.exports = function (node: HAPServiceNodeType) { } const configureCameraSource = function ( - accessory: Accessory, - service: Service, + _accessory: Accessory, + _service: Service, config: HAPServiceConfigType ) { if (config.cameraConfigSource) { @@ -418,9 +416,10 @@ module.exports = function (node: HAPServiceNodeType) { ) } else { // Use of deprecated method to be replaced with new Camera API - accessory.configureCameraSource( - new CameraSource(service, config, node) - ) + // TODO: https://github.com/homebridge/HAP-NodeJS/blob/latest/src/accessories/Camera_accessory.ts + // accessory.configureCameraSource( + // new CameraSource(service, config, node) + // ) } } else { log.error('Missing configuration for CameraControl.') diff --git a/src/lib/utils/ServiceUtils2.ts b/src/lib/utils/ServiceUtils2.ts index f60dd158..a6c5fc5e 100644 --- a/src/lib/utils/ServiceUtils2.ts +++ b/src/lib/utils/ServiceUtils2.ts @@ -1,4 +1,3 @@ -import { logger } from '@nrchkb/logger' import { Accessory, Characteristic, @@ -10,12 +9,13 @@ import { HAPStatus, HapStatusError, Service, -} from 'hap-nodejs' +} from '@homebridge/hap-nodejs' import { HAPConnection, HAPUsername, -} from 'hap-nodejs/dist/lib/util/eventedhttp' -import { SessionIdentifier } from 'hap-nodejs/dist/types' +} from '@homebridge/hap-nodejs/dist/lib/util/eventedhttp' +import { SessionIdentifier } from '@homebridge/hap-nodejs/dist/types' +import { logger } from '@nrchkb/logger' import NRCHKBError from '../NRCHKBError' import { Storage } from '../Storage' @@ -27,12 +27,10 @@ module.exports = function (node: HAPService2NodeType) { const ServiceUtilsLegacy = require('./ServiceUtils')(node) - const HapNodeJS = require('hap-nodejs') + const HapNodeJS = require('@homebridge/hap-nodejs') const Service = HapNodeJS.Service const Characteristic = HapNodeJS.Characteristic - const CameraSource = require('../cameraSource').Camera - const NO_RESPONSE_MSG = 'NO_RESPONSE' type HAPServiceNodeEvent = { @@ -338,7 +336,7 @@ module.exports = function (node: HAPService2NodeType) { ) if (context !== null) { - characteristic.setValue(value, undefined, context) + characteristic.setValue(value, context) } else { characteristic.setValue(value) } @@ -452,8 +450,8 @@ module.exports = function (node: HAPService2NodeType) { } const configureCameraSource = function ( - accessory: Accessory, - service: Service, + _accessory: Accessory, + _service: Service, config: HAPService2ConfigType ) { if (config.cameraConfigSource) { @@ -465,9 +463,10 @@ module.exports = function (node: HAPService2NodeType) { ) } else { // Use of deprecated method to be replaced with new Camera API - accessory.configureCameraSource( - new CameraSource(service, config, node) - ) + // TODO: https://github.com/homebridge/HAP-NodeJS/blob/latest/src/accessories/Camera_accessory.ts + // accessory.configureCameraSource( + // new CameraSource(service, config, node) + // ) } } else { log.error('Missing configuration for CameraControl.') diff --git a/src/lib/utils/index.ts b/src/lib/utils/index.ts index 8865469a..5964b992 100644 --- a/src/lib/utils/index.ts +++ b/src/lib/utils/index.ts @@ -5,13 +5,11 @@ module.exports = function (node: HAPServiceNodeType) { const BridgeUtils = require('./BridgeUtils')() const AccessoryUtils = require('./AccessoryUtils')(node) const CharacteristicUtils = require('./CharacteristicUtils')(node) - const MdnsUtils = require('./MdnsUtils')() return { ServiceUtils, BridgeUtils, AccessoryUtils, CharacteristicUtils, - MdnsUtils, } } diff --git a/src/nodes/nrchkb.ts b/src/nodes/nrchkb.ts index 23693369..f9392a2a 100644 --- a/src/nodes/nrchkb.ts +++ b/src/nodes/nrchkb.ts @@ -1,5 +1,5 @@ +import { HAPStorage } from '@homebridge/hap-nodejs' import { logger, loggerSetup } from '@nrchkb/logger' -import { HAPStorage } from 'hap-nodejs' import { NodeAPI } from 'node-red' import * as path from 'path' import semver from 'semver' diff --git a/src/nodes/status.ts b/src/nodes/status.ts index 341570b3..a5b900f1 100644 --- a/src/nodes/status.ts +++ b/src/nodes/status.ts @@ -1,5 +1,5 @@ +import { Service } from '@homebridge/hap-nodejs' import { logger } from '@nrchkb/logger' -import { Service } from 'hap-nodejs' import { NodeAPI } from 'node-red' import HAPServiceNodeType from '../lib/types/HAPServiceNodeType' diff --git a/src/test/test-utils/data/api.service.types.response.ts b/src/test/test-utils/data/api.service.types.response.ts index b5cfc68b..3b0aa1b9 100644 --- a/src/test/test-utils/data/api.service.types.response.ts +++ b/src/test/test-utils/data/api.service.types.response.ts @@ -189,6 +189,17 @@ export const serviceTypesResponse = { }, value: '', }, + { + UUID: '0000026D-0000-1000-8000-0026BB765291', + constructorName: 'MatterFirmwareRevisionNumber', + displayName: 'Matter Firmware Revision Number', + eventOnlyCharacteristic: false, + props: { + format: 'uint32', + perms: ['ev', 'pr'], + }, + value: 0, + }, { UUID: '0000026C-0000-1000-8000-0026BB765291', constructorName: 'HardwareFinish', @@ -817,299 +828,13 @@ export const serviceTypesResponse = { nrchkbDisabledText: 'BatteryService (deprecated, replaced by Battery)', }, BridgeConfiguration: { - UUID: '000000A1-0000-1000-8000-0026BB765291', - characteristics: [ - { - UUID: '0000009D-0000-1000-8000-0026BB765291', - constructorName: 'ConfigureBridgedAccessoryStatus', - displayName: 'Configure Bridged Accessory Status', - eventOnlyCharacteristic: false, - props: { - format: 'tlv8', - perms: ['ev', 'pr'], - }, - value: '', - }, - { - UUID: '0000009E-0000-1000-8000-0026BB765291', - constructorName: 'DiscoverBridgedAccessories', - displayName: 'Discover Bridged Accessories', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - perms: ['ev', 'pr', 'pw'], - }, - value: 0, - }, - { - UUID: '0000009F-0000-1000-8000-0026BB765291', - constructorName: 'DiscoveredBridgedAccessories', - displayName: 'Discovered Bridged Accessories', - eventOnlyCharacteristic: false, - props: { - format: 'uint16', - perms: ['ev', 'pr'], - }, - value: 0, - }, - { - UUID: '000000A0-0000-1000-8000-0026BB765291', - constructorName: 'ConfigureBridgedAccessory', - displayName: 'Configure Bridged Accessory', - eventOnlyCharacteristic: false, - props: { - format: 'tlv8', - perms: ['pw'], - }, - value: '', - }, - ], - constructorName: 'BridgeConfiguration', - displayName: 'BridgeConfiguration', - hiddenService: false, nrchkbDisabledText: 'BridgeConfiguration (deprecated, unused)', - optionalCharacteristics: [ - { - UUID: '00000023-0000-1000-8000-0026BB765291', - constructorName: 'Name', - displayName: 'Name', - eventOnlyCharacteristic: false, - props: { - format: 'string', - maxLen: 64, - perms: ['pr'], - }, - value: '', - }, - ], - primaryService: false, }, BridgingState: { - UUID: '00000062-0000-1000-8000-0026BB765291', - characteristics: [ - { - UUID: '00000063-0000-1000-8000-0026BB765291', - constructorName: 'Reachable', - displayName: 'Reachable', - eventOnlyCharacteristic: false, - props: { - format: 'bool', - perms: ['pr', 'pw'], - }, - value: false, - }, - { - UUID: '0000009C-0000-1000-8000-0026BB765291', - constructorName: 'LinkQuality', - displayName: 'Link Quality', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 4, - minValue: 1, - perms: ['ev', 'pr'], - }, - value: 1, - }, - { - UUID: '00000057-0000-1000-8000-0026BB765291', - constructorName: 'AccessoryIdentifier', - displayName: 'Accessory Identifier', - eventOnlyCharacteristic: false, - props: { - format: 'string', - perms: ['pr'], - }, - value: '', - }, - { - UUID: '000000A3-0000-1000-8000-0026BB765291', - constructorName: 'Category', - displayName: 'Category', - eventOnlyCharacteristic: false, - props: { - format: 'uint16', - maxValue: 16, - minValue: 1, - perms: ['ev', 'pr'], - }, - value: 1, - }, - ], - constructorName: 'BridgingState', - displayName: 'BridgingState', - hiddenService: false, nrchkbDisabledText: 'BridgingState (deprecated, unused)', - optionalCharacteristics: [ - { - UUID: '00000023-0000-1000-8000-0026BB765291', - constructorName: 'Name', - displayName: 'Name', - eventOnlyCharacteristic: false, - props: { - format: 'string', - maxLen: 64, - perms: ['pr'], - }, - value: '', - }, - ], - primaryService: false, }, CameraControl: { - UUID: '00000111-0000-1000-8000-0026BB765291', - characteristics: [ - { - UUID: '00000025-0000-1000-8000-0026BB765291', - constructorName: 'On', - displayName: 'On', - eventOnlyCharacteristic: false, - props: { - format: 'bool', - perms: ['ev', 'pr', 'pw'], - }, - value: false, - }, - ], - constructorName: 'CameraControl', - displayName: 'CameraControl', - hiddenService: false, - optionalCharacteristics: [ - { - UUID: '0000006C-0000-1000-8000-0026BB765291', - constructorName: 'CurrentHorizontalTiltAngle', - displayName: 'Current Horizontal Tilt Angle', - eventOnlyCharacteristic: false, - props: { - format: 'int', - maxValue: 90, - minStep: 1, - minValue: -90, - perms: ['ev', 'pr'], - unit: 'arcdegrees', - }, - value: -90, - }, - { - UUID: '0000006E-0000-1000-8000-0026BB765291', - constructorName: 'CurrentVerticalTiltAngle', - displayName: 'Current Vertical Tilt Angle', - eventOnlyCharacteristic: false, - props: { - format: 'int', - maxValue: 90, - minStep: 1, - minValue: -90, - perms: ['ev', 'pr'], - unit: 'arcdegrees', - }, - value: -90, - }, - { - UUID: '0000007B-0000-1000-8000-0026BB765291', - constructorName: 'TargetHorizontalTiltAngle', - displayName: 'Target Horizontal Tilt Angle', - eventOnlyCharacteristic: false, - props: { - format: 'int', - maxValue: 90, - minStep: 1, - minValue: -90, - perms: ['ev', 'pr', 'pw'], - unit: 'arcdegrees', - }, - value: -90, - }, - { - UUID: '0000007D-0000-1000-8000-0026BB765291', - constructorName: 'TargetVerticalTiltAngle', - displayName: 'Target Vertical Tilt Angle', - eventOnlyCharacteristic: false, - props: { - format: 'int', - maxValue: 90, - minStep: 1, - minValue: -90, - perms: ['ev', 'pr', 'pw'], - unit: 'arcdegrees', - }, - value: -90, - }, - { - UUID: '0000011B-0000-1000-8000-0026BB765291', - constructorName: 'NightVision', - displayName: 'Night Vision', - eventOnlyCharacteristic: false, - props: { - format: 'bool', - perms: ['ev', 'pr', 'pw', 'tw'], - }, - value: false, - }, - { - UUID: '0000011C-0000-1000-8000-0026BB765291', - constructorName: 'OpticalZoom', - displayName: 'Optical Zoom', - eventOnlyCharacteristic: false, - props: { - format: 'float', - minStep: 0.1, - perms: ['ev', 'pr', 'pw'], - }, - value: 0, - }, - { - UUID: '0000011D-0000-1000-8000-0026BB765291', - constructorName: 'DigitalZoom', - displayName: 'Digital Zoom', - eventOnlyCharacteristic: false, - props: { - format: 'float', - minStep: 0.1, - perms: ['ev', 'pr', 'pw'], - }, - value: 0, - }, - { - UUID: '0000011E-0000-1000-8000-0026BB765291', - constructorName: 'ImageRotation', - displayName: 'Image Rotation', - eventOnlyCharacteristic: false, - props: { - format: 'int', - maxValue: 360, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr', 'pw'], - unit: 'arcdegrees', - }, - value: 0, - }, - { - UUID: '0000011F-0000-1000-8000-0026BB765291', - constructorName: 'ImageMirroring', - displayName: 'Image Mirroring', - eventOnlyCharacteristic: false, - props: { - format: 'bool', - perms: ['ev', 'pr', 'pw'], - }, - value: false, - }, - { - UUID: '00000023-0000-1000-8000-0026BB765291', - constructorName: 'Name', - displayName: 'Name', - eventOnlyCharacteristic: false, - props: { - format: 'string', - maxLen: 64, - perms: ['pr'], - }, - value: '', - }, - ], - primaryService: false, + nrchkbDisabledText: 'CameraControl (deprecated, replaced by)', }, CameraEventRecordingManagement: { nrchkbDisabledText: @@ -2392,6 +2117,28 @@ export const serviceTypesResponse = { displayName: 'FirmwareUpdate', hiddenService: false, optionalCharacteristics: [ + { + UUID: '0000026F-0000-1000-8000-0026BB765291', + constructorName: 'FirmwareUpdateProtocolList', + displayName: 'Firmware Update Protocol List', + eventOnlyCharacteristic: false, + props: { + format: 'tlv8', + perms: ['pr'], + }, + value: '', + }, + { + UUID: '0000026E-0000-1000-8000-0026BB765291', + constructorName: 'MatterFirmwareUpdateStatus', + displayName: 'Matter Firmware Update Status', + eventOnlyCharacteristic: false, + props: { + format: 'tlv8', + perms: ['ev', 'pr'], + }, + value: '', + }, { UUID: '00000249-0000-1000-8000-0026BB765291', constructorName: 'StagedFirmwareVersion', @@ -4149,6 +3896,7 @@ export const serviceTypesResponse = { maxValue: 1, minStep: 1, minValue: 0, + validValues: [0, 1], perms: ['ev', 'pr'], }, value: 0, @@ -5730,63 +5478,7 @@ export const serviceTypesResponse = { primaryService: false, }, TimeInformation: { - UUID: '00000099-0000-1000-8000-0026BB765291', - characteristics: [ - { - UUID: '0000009B-0000-1000-8000-0026BB765291', - constructorName: 'CurrentTime', - displayName: 'Current Time', - eventOnlyCharacteristic: false, - props: { - format: 'string', - perms: ['pr', 'pw'], - }, - value: '', - }, - { - UUID: '00000098-0000-1000-8000-0026BB765291', - constructorName: 'DayoftheWeek', - displayName: 'Day of the Week', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 7, - minValue: 1, - perms: ['pr', 'pw'], - }, - value: 1, - }, - { - UUID: '0000009A-0000-1000-8000-0026BB765291', - constructorName: 'TimeUpdate', - displayName: 'Time Update', - eventOnlyCharacteristic: false, - props: { - format: 'bool', - perms: ['pr', 'pw'], - }, - value: false, - }, - ], - constructorName: 'TimeInformation', - displayName: 'TimeInformation', - hiddenService: false, nrchkbDisabledText: 'TimeInformation (deprecated, unused)', - optionalCharacteristics: [ - { - UUID: '00000023-0000-1000-8000-0026BB765291', - constructorName: 'Name', - displayName: 'Name', - eventOnlyCharacteristic: false, - props: { - format: 'string', - maxLen: 64, - perms: ['pr'], - }, - value: '', - }, - ], - primaryService: false, }, TransferTransportManagement: { UUID: '00000203-0000-1000-8000-0026BB765291', From f582ffeb77112b56a73f6ca003868047c3135cd8 Mon Sep 17 00:00:00 2001 From: Shaquu Date: Sun, 23 Nov 2025 23:04:35 +0100 Subject: [PATCH 03/14] Migrated from mocha to vitest for test running --- package-lock.json | 4037 ++++++++++++--------- package.json | 25 +- src/lib/api.ts | 2 - src/lib/types/hap-nodejs/HapCategories.ts | 3 +- src/lib/utils/AccessoryUtils.ts | 1 - src/lib/utils/ServiceUtils.ts | 1 - src/lib/utils/ServiceUtils2.ts | 1 - src/test/lib/HAPBridgeNode.test.ts | 33 +- src/test/lib/NodeStatusUtils.test.ts | 132 +- src/test/lib/api.test.ts | 120 +- src/test/nodes/service.test.ts | 212 +- src/test/nodes/service2.test.ts | 230 +- 12 files changed, 2583 insertions(+), 2214 deletions(-) diff --git a/package-lock.json b/package-lock.json index 03768841..af71cf03 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,24 +1,23 @@ { "name": "node-red-contrib-homekit-bridged", - "version": "1.8.0-dev.0", + "version": "2.0.0-dev.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "node-red-contrib-homekit-bridged", - "version": "1.8.0-dev.0", + "version": "2.0.0-dev.1", "license": "Apache-2.0", "dependencies": { "@homebridge/hap-nodejs": "2.0.2", "@nrchkb/logger": "~3.1.1", "node-persist": "^3.1.3", "semver": "~7.7.3", - "uuid": "~11.0.5" + "uuid": "~13.0.0" }, "devDependencies": { "@homebridge/ciao": "~1.3.4", "@node-red/registry": "^4.1.1", - "@types/mocha": "^10.0.10", "@types/node": "^20", "@types/node-persist": "^3.1.8", "@types/node-red": "^1.3.5", @@ -28,18 +27,18 @@ "@typescript-eslint/eslint-plugin": "^7.16.0", "@typescript-eslint/parser": "^7.16.0", "babel-eslint": "^10.1.0", - "del-cli": "^5.1.0", + "del-cli": "^7.0.0", "eslint": "^8", "eslint-config-prettier": "^9.1.0", "eslint-plugin-prettier": "^5.5.4", "eslint-plugin-simple-import-sort": "^12.1.1", "husky": "^9.1.7", - "mocha": "^10.6.0", "node-red": "^4.1.1", "node-red-node-test-helper": "^0.3.5", "prettier": "^3.6.2", "ts-node": "^10.9.2", - "typescript": "^5.7.3" + "typescript": "^5.9.3", + "vitest": "^4.0.13" }, "engines": { "node": "^20 || ^22 || ^24" @@ -287,581 +286,1024 @@ "tslib": "^2.4.0" } }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "node_modules/@esbuild/aix-ppc64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", + "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==", + "cpu": [ + "ppc64" + ], "dev": true, - "dependencies": { - "eslint-visitor-keys": "^3.3.0" - }, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + "node": ">=18" } }, - "node_modules/@eslint-community/regexpp": { - "version": "4.10.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.1.tgz", - "integrity": "sha512-Zm2NGpWELsQAD1xsJzGQpYfvICSsFkEpU0jxBjfdC6uNEWXcHnfs9hScFWtXVDVl+rBQJGrl4g1vcKIejpH9dA==", + "node_modules/@esbuild/android-arm": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz", + "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==", + "cpu": [ + "arm" + ], "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + "node": ">=18" } }, - "node_modules/@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "node_modules/@esbuild/android-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz", + "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "node": ">=18" } }, - "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "node_modules/@esbuild/android-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz", + "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=18" } }, - "node_modules/@eslint/eslintrc/node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "node_modules/@esbuild/darwin-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz", + "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==", + "cpu": [ + "arm64" + ], "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=18" } }, - "node_modules/@eslint/js": { - "version": "8.56.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.56.0.tgz", - "integrity": "sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==", + "node_modules/@esbuild/darwin-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz", + "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==", + "cpu": [ + "x64" + ], "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=18" } }, - "node_modules/@homebridge/ciao": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/@homebridge/ciao/-/ciao-1.3.4.tgz", - "integrity": "sha512-qK6ZgGx0wwOubq/MY6eTbhApQHBUQCvCOsTYpQE01uLvfA2/Prm6egySHlZouKaina1RPuDwfLhCmsRCxwHj3Q==", + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz", + "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==", + "cpu": [ + "arm64" + ], + "dev": true, "license": "MIT", - "dependencies": { - "debug": "^4.4.1", - "fast-deep-equal": "^3.1.3", - "source-map-support": "^0.5.21", - "tslib": "^2.8.1" - }, - "bin": { - "ciao-bcs": "lib/bonjour-conformance-testing.js" + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" } }, - "node_modules/@homebridge/hap-nodejs": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@homebridge/hap-nodejs/-/hap-nodejs-2.0.2.tgz", - "integrity": "sha512-HqlMqVQ8bzh7uFqL0vNI6a5PJHAmCyPzHuPbBxf6XcPVKn02ELwCMDQ8ud5oS1fPO5z20lvV7rIfAqTbSlZ7Uw==", - "license": "Apache-2.0", - "dependencies": { - "@homebridge/ciao": "^1.3.4", - "@homebridge/dbus-native": "^0.7.2", - "bonjour-hap": "^3.9.1", - "debug": "^4.4.3", - "fast-srp-hap": "^2.0.4", - "futoin-hkdf": "^1.5.3", - "node-persist": "^0.0.12", - "source-map-support": "^0.5.21", - "tslib": "^2.8.1", - "tweetnacl": "^1.0.3" - }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz", + "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": "^20 || ^22 || ^24" + "node": ">=18" } }, - "node_modules/@homebridge/hap-nodejs/node_modules/@homebridge/dbus-native": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/@homebridge/dbus-native/-/dbus-native-0.7.2.tgz", - "integrity": "sha512-BNVe6YNxiy5x/E5/ZXDIWMD6Njv9cjW59PM/1CMpYe0jLAJ8pJN+Tq/JhVs3gXwmTavz2S86/sspmHquChet8A==", + "node_modules/@esbuild/linux-arm": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz", + "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==", + "cpu": [ + "arm" + ], + "dev": true, "license": "MIT", - "dependencies": { - "event-stream": "^4.0.1", - "hexy": "^0.3.5", - "long": "^5.3.2", - "minimist": "^1.2.8", - "safe-buffer": "^5.1.2", - "xml2js": "^0.6.2" - }, - "bin": { - "dbus2js": "bin/dbus2js.js" + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" } }, - "node_modules/@homebridge/hap-nodejs/node_modules/node-persist": { - "version": "0.0.12", - "resolved": "https://registry.npmjs.org/node-persist/-/node-persist-0.0.12.tgz", - "integrity": "sha512-Fbia3FYnURzaql53wLu0t19dmAwQg/tXT6O7YPmdwNwysNKEyFmgoT2BQlPD3XXQnYeiQVNvR5lfvufGwKuxhg==", + "node_modules/@esbuild/linux-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz", + "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==", + "cpu": [ + "arm64" + ], + "dev": true, "license": "MIT", - "dependencies": { - "mkdirp": "~0.5.1", - "q": "~1.1.1" + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" } }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.11.13", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz", - "integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==", + "node_modules/@esbuild/linux-ia32": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz", + "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==", + "cpu": [ + "ia32" + ], "dev": true, - "dependencies": { - "@humanwhocodes/object-schema": "^2.0.1", - "debug": "^4.1.1", - "minimatch": "^3.0.5" - }, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=10.10.0" + "node": ">=18" } }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "node_modules/@esbuild/linux-loong64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz", + "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==", + "cpu": [ + "loong64" + ], "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=12.22" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" + "node": ">=18" } }, - "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz", - "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==", - "dev": true - }, - "node_modules/@isaacs/cliui": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", - "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "node_modules/@esbuild/linux-mips64el": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz", + "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==", + "cpu": [ + "mips64el" + ], "dev": true, - "license": "ISC", - "dependencies": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" - }, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=12" + "node": ">=18" } }, - "node_modules/@isaacs/cliui/node_modules/ansi-regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "node_modules/@esbuild/linux-ppc64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz", + "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==", + "cpu": [ + "ppc64" + ], "dev": true, "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" + "node": ">=18" } }, - "node_modules/@isaacs/cliui/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "node_modules/@esbuild/linux-riscv64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz", + "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==", + "cpu": [ + "riscv64" + ], "dev": true, "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": ">=18" } }, - "node_modules/@isaacs/cliui/node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "node_modules/@esbuild/linux-s390x": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz", + "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==", + "cpu": [ + "s390x" + ], "dev": true, - "license": "MIT" + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } }, - "node_modules/@isaacs/cliui/node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "node_modules/@esbuild/linux-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz", + "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=18" } }, - "node_modules/@isaacs/cliui/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz", + "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, + "optional": true, + "os": [ + "netbsd" + ], "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" + "node": ">=18" } }, - "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "node_modules/@esbuild/netbsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz", + "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", - "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - }, + "optional": true, + "os": [ + "netbsd" + ], "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + "node": ">=18" } }, - "node_modules/@isaacs/fs-minipass": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", - "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz", + "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "ISC", - "dependencies": { - "minipass": "^7.0.4" - }, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], "engines": { - "node": ">=18.0.0" + "node": ">=18" } }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", - "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "node_modules/@esbuild/openbsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz", + "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - }, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], "engines": { - "node": ">=6.0.0" + "node": ">=18" } }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", - "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz", + "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==", + "cpu": [ + "arm64" + ], "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], "engines": { - "node": ">=6.0.0" + "node": ">=18" } }, - "node_modules/@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "node_modules/@esbuild/sunos-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz", + "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==", + "cpu": [ + "x64" + ], "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], "engines": { - "node": ">=6.0.0" + "node": ">=18" } }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.15", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", - "dev": true - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.20", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz", - "integrity": "sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==", + "node_modules/@esbuild/win32-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz", + "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" } }, - "node_modules/@leichtgewicht/ip-codec": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz", - "integrity": "sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==", - "license": "MIT" - }, - "node_modules/@napi-rs/wasm-runtime": { - "version": "0.2.12", - "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz", - "integrity": "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==", + "node_modules/@esbuild/win32-ia32": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz", + "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==", + "cpu": [ + "ia32" + ], "dev": true, "license": "MIT", "optional": true, - "dependencies": { - "@emnapi/core": "^1.4.3", - "@emnapi/runtime": "^1.4.3", - "@tybys/wasm-util": "^0.10.0" + "os": [ + "win32" + ], + "engines": { + "node": ">=18" } }, - "node_modules/@noble/hashes": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz", - "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==", + "node_modules/@esbuild/win32-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz", + "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": "^14.21.3 || >=16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" + "node": ">=18" } }, - "node_modules/@node-red/editor-api": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/@node-red/editor-api/-/editor-api-4.1.1.tgz", - "integrity": "sha512-vev2s3NntphqinzP2e3WmPnQY8+cHfSrQyESis9Fy+prp+E8uSgT4yfLjHMFyT116xPMB5WIg6qSDciq5OV1tA==", + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", "dev": true, - "license": "Apache-2.0", "dependencies": { - "@node-red/editor-client": "4.1.1", - "@node-red/util": "4.1.1", - "bcryptjs": "3.0.2", - "body-parser": "1.20.3", - "clone": "2.1.2", - "cors": "2.8.5", - "express": "4.21.2", - "express-session": "1.18.2", - "memorystore": "1.6.7", - "mime": "3.0.0", - "multer": "2.0.2", - "mustache": "4.2.0", - "oauth2orize": "1.12.0", - "passport": "0.7.0", - "passport-http-bearer": "1.0.1", - "passport-oauth2-client-password": "0.1.2", - "ws": "7.5.10" + "eslint-visitor-keys": "^3.3.0" }, - "optionalDependencies": { - "@node-rs/bcrypt": "1.10.7" + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, - "node_modules/@node-red/editor-client": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/@node-red/editor-client/-/editor-client-4.1.1.tgz", - "integrity": "sha512-JIJirftuB0NrvsFvPZXW3R16c8mLRy2UQh0AyxGU8ZQyz/dmF8auINbbGpQ4qxssBOGFWf9j4ZXP7B8EdLIOBQ==", + "node_modules/@eslint-community/regexpp": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.1.tgz", + "integrity": "sha512-Zm2NGpWELsQAD1xsJzGQpYfvICSsFkEpU0jxBjfdC6uNEWXcHnfs9hScFWtXVDVl+rBQJGrl4g1vcKIejpH9dA==", "dev": true, - "license": "Apache-2.0" + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } }, - "node_modules/@node-red/nodes": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/@node-red/nodes/-/nodes-4.1.1.tgz", - "integrity": "sha512-zTTwxpnPebHA5PjDBZEcsGv0BoqMJEjhf27aQIhlGed40/PaNiR0tmc5f5P6HKflmS3Iv6kiwGsY12Mjvyx/3Q==", + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", "dev": true, - "license": "Apache-2.0", "dependencies": { - "acorn": "8.15.0", - "acorn-walk": "8.3.4", - "ajv": "8.17.1", - "body-parser": "1.20.3", - "cheerio": "1.0.0-rc.10", - "content-type": "1.0.5", - "cookie": "0.7.2", - "cookie-parser": "1.4.7", - "cors": "2.8.5", - "cronosjs": "1.7.1", - "denque": "2.1.0", - "form-data": "4.0.4", - "fs-extra": "11.3.0", - "got": "12.6.1", - "hash-sum": "2.0.0", - "hpagent": "1.2.0", - "https-proxy-agent": "5.0.1", - "iconv-lite": "0.6.3", - "is-utf8": "0.2.1", - "js-yaml": "4.1.0", - "media-typer": "1.1.0", - "mqtt": "5.11.0", - "multer": "2.0.2", - "mustache": "4.2.0", - "node-watch": "0.7.4", - "on-headers": "1.1.0", - "raw-body": "3.0.0", - "tough-cookie": "5.1.2", - "uuid": "9.0.1", - "ws": "7.5.10", - "xml2js": "0.6.2" + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/@node-red/nodes/node_modules/ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", "dev": true, - "license": "MIT", "dependencies": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@node-red/nodes/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "node_modules/@eslint/eslintrc/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", "dev": true, - "license": "MIT" + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, - "node_modules/@node-red/nodes/node_modules/raw-body": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.0.tgz", - "integrity": "sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==", + "node_modules/@eslint/js": { + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.56.0.tgz", + "integrity": "sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==", "dev": true, - "license": "MIT", - "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.6.3", - "unpipe": "1.0.0" - }, "engines": { - "node": ">= 0.8" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, - "node_modules/@node-red/nodes/node_modules/uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", - "dev": true, - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], + "node_modules/@homebridge/ciao": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/@homebridge/ciao/-/ciao-1.3.4.tgz", + "integrity": "sha512-qK6ZgGx0wwOubq/MY6eTbhApQHBUQCvCOsTYpQE01uLvfA2/Prm6egySHlZouKaina1RPuDwfLhCmsRCxwHj3Q==", "license": "MIT", + "dependencies": { + "debug": "^4.4.1", + "fast-deep-equal": "^3.1.3", + "source-map-support": "^0.5.21", + "tslib": "^2.8.1" + }, "bin": { - "uuid": "dist/bin/uuid" + "ciao-bcs": "lib/bonjour-conformance-testing.js" } }, - "node_modules/@node-red/registry": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/@node-red/registry/-/registry-4.1.1.tgz", - "integrity": "sha512-+5SvdL+6tXzfYW63TpsfgybNP7G4farM+2div5FYYPdMJULE1D9Z8BHD/fprieU5mTTTO100CeyGXHbkzRH+Qg==", - "dev": true, + "node_modules/@homebridge/hap-nodejs": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@homebridge/hap-nodejs/-/hap-nodejs-2.0.2.tgz", + "integrity": "sha512-HqlMqVQ8bzh7uFqL0vNI6a5PJHAmCyPzHuPbBxf6XcPVKn02ELwCMDQ8ud5oS1fPO5z20lvV7rIfAqTbSlZ7Uw==", "license": "Apache-2.0", "dependencies": { - "@node-red/util": "4.1.1", - "clone": "2.1.2", - "fs-extra": "11.3.0", - "semver": "7.7.1", - "tar": "7.4.3", - "uglify-js": "3.19.3" + "@homebridge/ciao": "^1.3.4", + "@homebridge/dbus-native": "^0.7.2", + "bonjour-hap": "^3.9.1", + "debug": "^4.4.3", + "fast-srp-hap": "^2.0.4", + "futoin-hkdf": "^1.5.3", + "node-persist": "^0.0.12", + "source-map-support": "^0.5.21", + "tslib": "^2.8.1", + "tweetnacl": "^1.0.3" + }, + "engines": { + "node": "^20 || ^22 || ^24" } }, - "node_modules/@node-red/registry/node_modules/semver": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", - "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "node_modules/@homebridge/hap-nodejs/node_modules/@homebridge/dbus-native": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/@homebridge/dbus-native/-/dbus-native-0.7.2.tgz", + "integrity": "sha512-BNVe6YNxiy5x/E5/ZXDIWMD6Njv9cjW59PM/1CMpYe0jLAJ8pJN+Tq/JhVs3gXwmTavz2S86/sspmHquChet8A==", + "license": "MIT", + "dependencies": { + "event-stream": "^4.0.1", + "hexy": "^0.3.5", + "long": "^5.3.2", + "minimist": "^1.2.8", + "safe-buffer": "^5.1.2", + "xml2js": "^0.6.2" }, - "engines": { - "node": ">=10" + "bin": { + "dbus2js": "bin/dbus2js.js" } }, - "node_modules/@node-red/runtime": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/@node-red/runtime/-/runtime-4.1.1.tgz", - "integrity": "sha512-NWV+u2GrLnaPjomJilwVhl5u6WLwJN7tvHEVm5r9/8quW0H8BuYfih5AwCzCl8aly1imhe1+kfiCExSfGVaQUA==", - "dev": true, - "license": "Apache-2.0", + "node_modules/@homebridge/hap-nodejs/node_modules/node-persist": { + "version": "0.0.12", + "resolved": "https://registry.npmjs.org/node-persist/-/node-persist-0.0.12.tgz", + "integrity": "sha512-Fbia3FYnURzaql53wLu0t19dmAwQg/tXT6O7YPmdwNwysNKEyFmgoT2BQlPD3XXQnYeiQVNvR5lfvufGwKuxhg==", + "license": "MIT", "dependencies": { - "@node-red/registry": "4.1.1", - "@node-red/util": "4.1.1", - "async-mutex": "0.5.0", - "clone": "2.1.2", - "cronosjs": "1.7.1", - "express": "4.21.2", - "fs-extra": "11.3.0", - "got": "12.6.1", - "json-stringify-safe": "5.0.1", - "rfdc": "^1.3.1", - "semver": "7.7.1" + "mkdirp": "~0.5.1", + "q": "~1.1.1" } }, - "node_modules/@node-red/runtime/node_modules/semver": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", - "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.13", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz", + "integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==", "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.1", + "debug": "^4.1.1", + "minimatch": "^3.0.5" }, "engines": { - "node": ">=10" + "node": ">=10.10.0" } }, - "node_modules/@node-red/util": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/@node-red/util/-/util-4.1.1.tgz", - "integrity": "sha512-gnkRXmz49rj2OXjJC/RAPbFUQvDATC3Oy6yGuhN/McPy8mmL7q4YTIflUwWKyrsd6TU3cK17JmmXtPTQBtS8jQ==", + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", "dev": true, - "license": "Apache-2.0", - "dependencies": { - "chalk": "^4.1.2", - "fs-extra": "11.3.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz", + "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==", + "dev": true + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/@isaacs/fs-minipass": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", + "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "minipass": "^7.0.4" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", + "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", + "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.20", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz", + "integrity": "sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@leichtgewicht/ip-codec": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz", + "integrity": "sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==", + "license": "MIT" + }, + "node_modules/@napi-rs/wasm-runtime": { + "version": "0.2.12", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz", + "integrity": "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "^1.4.3", + "@emnapi/runtime": "^1.4.3", + "@tybys/wasm-util": "^0.10.0" + } + }, + "node_modules/@noble/hashes": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz", + "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@node-red/editor-api": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@node-red/editor-api/-/editor-api-4.1.1.tgz", + "integrity": "sha512-vev2s3NntphqinzP2e3WmPnQY8+cHfSrQyESis9Fy+prp+E8uSgT4yfLjHMFyT116xPMB5WIg6qSDciq5OV1tA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@node-red/editor-client": "4.1.1", + "@node-red/util": "4.1.1", + "bcryptjs": "3.0.2", + "body-parser": "1.20.3", + "clone": "2.1.2", + "cors": "2.8.5", + "express": "4.21.2", + "express-session": "1.18.2", + "memorystore": "1.6.7", + "mime": "3.0.0", + "multer": "2.0.2", + "mustache": "4.2.0", + "oauth2orize": "1.12.0", + "passport": "0.7.0", + "passport-http-bearer": "1.0.1", + "passport-oauth2-client-password": "0.1.2", + "ws": "7.5.10" + }, + "optionalDependencies": { + "@node-rs/bcrypt": "1.10.7" + } + }, + "node_modules/@node-red/editor-client": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@node-red/editor-client/-/editor-client-4.1.1.tgz", + "integrity": "sha512-JIJirftuB0NrvsFvPZXW3R16c8mLRy2UQh0AyxGU8ZQyz/dmF8auINbbGpQ4qxssBOGFWf9j4ZXP7B8EdLIOBQ==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/@node-red/nodes": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@node-red/nodes/-/nodes-4.1.1.tgz", + "integrity": "sha512-zTTwxpnPebHA5PjDBZEcsGv0BoqMJEjhf27aQIhlGed40/PaNiR0tmc5f5P6HKflmS3Iv6kiwGsY12Mjvyx/3Q==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "acorn": "8.15.0", + "acorn-walk": "8.3.4", + "ajv": "8.17.1", + "body-parser": "1.20.3", + "cheerio": "1.0.0-rc.10", + "content-type": "1.0.5", + "cookie": "0.7.2", + "cookie-parser": "1.4.7", + "cors": "2.8.5", + "cronosjs": "1.7.1", + "denque": "2.1.0", + "form-data": "4.0.4", + "fs-extra": "11.3.0", + "got": "12.6.1", + "hash-sum": "2.0.0", + "hpagent": "1.2.0", + "https-proxy-agent": "5.0.1", + "iconv-lite": "0.6.3", + "is-utf8": "0.2.1", + "js-yaml": "4.1.0", + "media-typer": "1.1.0", + "mqtt": "5.11.0", + "multer": "2.0.2", + "mustache": "4.2.0", + "node-watch": "0.7.4", + "on-headers": "1.1.0", + "raw-body": "3.0.0", + "tough-cookie": "5.1.2", + "uuid": "9.0.1", + "ws": "7.5.10", + "xml2js": "0.6.2" + } + }, + "node_modules/@node-red/nodes/node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@node-red/nodes/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true, + "license": "MIT" + }, + "node_modules/@node-red/nodes/node_modules/raw-body": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.0.tgz", + "integrity": "sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.6.3", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/@node-red/nodes/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "dev": true, + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/@node-red/registry": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@node-red/registry/-/registry-4.1.1.tgz", + "integrity": "sha512-+5SvdL+6tXzfYW63TpsfgybNP7G4farM+2div5FYYPdMJULE1D9Z8BHD/fprieU5mTTTO100CeyGXHbkzRH+Qg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@node-red/util": "4.1.1", + "clone": "2.1.2", + "fs-extra": "11.3.0", + "semver": "7.7.1", + "tar": "7.4.3", + "uglify-js": "3.19.3" + } + }, + "node_modules/@node-red/registry/node_modules/semver": { + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@node-red/runtime": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@node-red/runtime/-/runtime-4.1.1.tgz", + "integrity": "sha512-NWV+u2GrLnaPjomJilwVhl5u6WLwJN7tvHEVm5r9/8quW0H8BuYfih5AwCzCl8aly1imhe1+kfiCExSfGVaQUA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@node-red/registry": "4.1.1", + "@node-red/util": "4.1.1", + "async-mutex": "0.5.0", + "clone": "2.1.2", + "cronosjs": "1.7.1", + "express": "4.21.2", + "fs-extra": "11.3.0", + "got": "12.6.1", + "json-stringify-safe": "5.0.1", + "rfdc": "^1.3.1", + "semver": "7.7.1" + } + }, + "node_modules/@node-red/runtime/node_modules/semver": { + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@node-red/util": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@node-red/util/-/util-4.1.1.tgz", + "integrity": "sha512-gnkRXmz49rj2OXjJC/RAPbFUQvDATC3Oy6yGuhN/McPy8mmL7q4YTIflUwWKyrsd6TU3cK17JmmXtPTQBtS8jQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "chalk": "^4.1.2", + "fs-extra": "11.3.0", "i18next": "24.2.3", "json-stringify-safe": "5.0.1", "jsonata": "2.0.6", @@ -870,127 +1312,443 @@ "moment-timezone": "0.5.48" } }, - "node_modules/@node-red/util/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/@node-red/util/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@node-red/util/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@node-red/util/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@node-red/util/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@node-red/util/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@node-red/util/node_modules/jsonata": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/jsonata/-/jsonata-2.0.6.tgz", + "integrity": "sha512-WhQB5tXQ32qjkx2GYHFw2XbL90u+LLzjofAYwi+86g6SyZeXHz9F1Q0amy3dWRYczshOC3Haok9J4pOCgHtwyQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@node-red/util/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "license": "MIT", "dependencies": { - "color-convert": "^2.0.1" + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@node-rs/bcrypt": { + "version": "1.10.7", + "resolved": "https://registry.npmjs.org/@node-rs/bcrypt/-/bcrypt-1.10.7.tgz", + "integrity": "sha512-1wk0gHsUQC/ap0j6SJa2K34qNhomxXRcEe3T8cI5s+g6fgHBgLTN7U9LzWTG/HE6G4+2tWWLeCabk1wiYGEQSA==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + }, + "optionalDependencies": { + "@node-rs/bcrypt-android-arm-eabi": "1.10.7", + "@node-rs/bcrypt-android-arm64": "1.10.7", + "@node-rs/bcrypt-darwin-arm64": "1.10.7", + "@node-rs/bcrypt-darwin-x64": "1.10.7", + "@node-rs/bcrypt-freebsd-x64": "1.10.7", + "@node-rs/bcrypt-linux-arm-gnueabihf": "1.10.7", + "@node-rs/bcrypt-linux-arm64-gnu": "1.10.7", + "@node-rs/bcrypt-linux-arm64-musl": "1.10.7", + "@node-rs/bcrypt-linux-x64-gnu": "1.10.7", + "@node-rs/bcrypt-linux-x64-musl": "1.10.7", + "@node-rs/bcrypt-wasm32-wasi": "1.10.7", + "@node-rs/bcrypt-win32-arm64-msvc": "1.10.7", + "@node-rs/bcrypt-win32-ia32-msvc": "1.10.7", + "@node-rs/bcrypt-win32-x64-msvc": "1.10.7" + } + }, + "node_modules/@node-rs/bcrypt-android-arm-eabi": { + "version": "1.10.7", + "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-android-arm-eabi/-/bcrypt-android-arm-eabi-1.10.7.tgz", + "integrity": "sha512-8dO6/PcbeMZXS3VXGEtct9pDYdShp2WBOWlDvSbcRwVqyB580aCBh0BEFmKYtXLzLvUK8Wf+CG3U6sCdILW1lA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@node-rs/bcrypt-android-arm64": { + "version": "1.10.7", + "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-android-arm64/-/bcrypt-android-arm64-1.10.7.tgz", + "integrity": "sha512-UASFBS/CucEMHiCtL/2YYsAY01ZqVR1N7vSb94EOvG5iwW7BQO06kXXCTgj+Xbek9azxixrCUmo3WJnkJZ0hTQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@node-rs/bcrypt-darwin-arm64": { + "version": "1.10.7", + "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-darwin-arm64/-/bcrypt-darwin-arm64-1.10.7.tgz", + "integrity": "sha512-DgzFdAt455KTuiJ/zYIyJcKFobjNDR/hnf9OS7pK5NRS13Nq4gLcSIIyzsgHwZHxsJWbLpHmFc1H23Y7IQoQBw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@node-rs/bcrypt-darwin-x64": { + "version": "1.10.7", + "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-darwin-x64/-/bcrypt-darwin-x64-1.10.7.tgz", + "integrity": "sha512-SPWVfQ6sxSokoUWAKWD0EJauvPHqOGQTd7CxmYatcsUgJ/bruvEHxZ4bIwX1iDceC3FkOtmeHO0cPwR480n/xA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@node-rs/bcrypt-freebsd-x64": { + "version": "1.10.7", + "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-freebsd-x64/-/bcrypt-freebsd-x64-1.10.7.tgz", + "integrity": "sha512-gpa+Ixs6GwEx6U6ehBpsQetzUpuAGuAFbOiuLB2oo4N58yU4AZz1VIcWyWAHrSWRs92O0SHtmo2YPrMrwfBbSw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@node-rs/bcrypt-linux-arm-gnueabihf": { + "version": "1.10.7", + "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-linux-arm-gnueabihf/-/bcrypt-linux-arm-gnueabihf-1.10.7.tgz", + "integrity": "sha512-kYgJnTnpxrzl9sxYqzflobvMp90qoAlaX1oDL7nhNTj8OYJVDIk0jQgblj0bIkjmoPbBed53OJY/iu4uTS+wig==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@node-rs/bcrypt-linux-arm64-gnu": { + "version": "1.10.7", + "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-linux-arm64-gnu/-/bcrypt-linux-arm64-gnu-1.10.7.tgz", + "integrity": "sha512-7cEkK2RA+gBCj2tCVEI1rDSJV40oLbSq7bQ+PNMHNI6jCoXGmj9Uzo7mg7ZRbNZ7piIyNH5zlJqutjo8hh/tmA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@node-rs/bcrypt-linux-arm64-musl": { + "version": "1.10.7", + "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-linux-arm64-musl/-/bcrypt-linux-arm64-musl-1.10.7.tgz", + "integrity": "sha512-X7DRVjshhwxUqzdUKDlF55cwzh+wqWJ2E/tILvZPboO3xaNO07Um568Vf+8cmKcz+tiZCGP7CBmKbBqjvKN/Pw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@node-rs/bcrypt-linux-x64-gnu": { + "version": "1.10.7", + "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-linux-x64-gnu/-/bcrypt-linux-x64-gnu-1.10.7.tgz", + "integrity": "sha512-LXRZsvG65NggPD12hn6YxVgH0W3VR5fsE/o1/o2D5X0nxKcNQGeLWnRzs5cP8KpoFOuk1ilctXQJn8/wq+Gn/Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@node-rs/bcrypt-linux-x64-musl": { + "version": "1.10.7", + "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-linux-x64-musl/-/bcrypt-linux-x64-musl-1.10.7.tgz", + "integrity": "sha512-tCjHmct79OfcO3g5q21ME7CNzLzpw1MAsUXCLHLGWH+V6pp/xTvMbIcLwzkDj6TI3mxK6kehTn40SEjBkZ3Rog==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@node-rs/bcrypt-wasm32-wasi": { + "version": "1.10.7", + "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-wasm32-wasi/-/bcrypt-wasm32-wasi-1.10.7.tgz", + "integrity": "sha512-4qXSihIKeVXYglfXZEq/QPtYtBUvR8d3S85k15Lilv3z5B6NSGQ9mYiNleZ7QHVLN2gEc5gmi7jM353DMH9GkA==", + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@napi-rs/wasm-runtime": "^0.2.5" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": ">=14.0.0" + } + }, + "node_modules/@node-rs/bcrypt-win32-arm64-msvc": { + "version": "1.10.7", + "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-win32-arm64-msvc/-/bcrypt-win32-arm64-msvc-1.10.7.tgz", + "integrity": "sha512-FdfUQrqmDfvC5jFhntMBkk8EI+fCJTx/I1v7Rj+Ezlr9rez1j1FmuUnywbBj2Cg15/0BDhwYdbyZ5GCMFli2aQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@node-rs/bcrypt-win32-ia32-msvc": { + "version": "1.10.7", + "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-win32-ia32-msvc/-/bcrypt-win32-ia32-msvc-1.10.7.tgz", + "integrity": "sha512-lZLf4Cx+bShIhU071p5BZft4OvP4PGhyp542EEsb3zk34U5GLsGIyCjOafcF/2DGewZL6u8/aqoxbSuROkgFXg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" } }, - "node_modules/@node-red/util/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/@node-rs/bcrypt-win32-x64-msvc": { + "version": "1.10.7", + "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-win32-x64-msvc/-/bcrypt-win32-x64-msvc-1.10.7.tgz", + "integrity": "sha512-hdw7tGmN1DxVAMTzICLdaHpXjy+4rxaxnBMgI8seG1JL5e3VcRGsd1/1vVDogVp2cbsmgq+6d6yAY+D9lW/DCg==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "node": ">= 10" } }, - "node_modules/@node-red/util/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", "dev": true, - "license": "MIT", "dependencies": { - "color-name": "~1.1.4" + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" }, "engines": { - "node": ">=7.0.0" + "node": ">= 8" } }, - "node_modules/@node-red/util/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@node-red/util/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", "dev": true, - "license": "MIT", "engines": { - "node": ">=8" + "node": ">= 8" } }, - "node_modules/@node-red/util/node_modules/jsonata": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/jsonata/-/jsonata-2.0.6.tgz", - "integrity": "sha512-WhQB5tXQ32qjkx2GYHFw2XbL90u+LLzjofAYwi+86g6SyZeXHz9F1Q0amy3dWRYczshOC3Haok9J4pOCgHtwyQ==", + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "dev": true, - "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, "engines": { "node": ">= 8" } }, - "node_modules/@node-red/util/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/@nrchkb/logger": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@nrchkb/logger/-/logger-3.1.1.tgz", + "integrity": "sha512-37m4lq7Jemg7qzkBflD+VZ1HnFdZv10k9hgglonFXTBMrLmXxkXllWelCKDGABVkfx1hjijAz6IpQoIF+Oo9yw==", + "license": "Apache-2.0", + "dependencies": { + "debug": "^4.3.5" + } + }, + "node_modules/@paralleldrive/cuid2": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/@paralleldrive/cuid2/-/cuid2-2.3.1.tgz", + "integrity": "sha512-XO7cAxhnTZl0Yggq6jOgjiOHhbgcO4NqFqwSmQpjK3b6TEE6Uj/jfSk6wzYyemh3+I0sHirKSetjQwn5cZktFw==", "dev": true, "license": "MIT", "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" + "@noble/hashes": "^1.1.5" } }, - "node_modules/@node-rs/bcrypt": { - "version": "1.10.7", - "resolved": "https://registry.npmjs.org/@node-rs/bcrypt/-/bcrypt-1.10.7.tgz", - "integrity": "sha512-1wk0gHsUQC/ap0j6SJa2K34qNhomxXRcEe3T8cI5s+g6fgHBgLTN7U9LzWTG/HE6G4+2tWWLeCabk1wiYGEQSA==", + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", "dev": true, "license": "MIT", "optional": true, "engines": { - "node": ">= 10" + "node": ">=14" + } + }, + "node_modules/@pkgr/core": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.9.tgz", + "integrity": "sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/Brooooooklyn" - }, - "optionalDependencies": { - "@node-rs/bcrypt-android-arm-eabi": "1.10.7", - "@node-rs/bcrypt-android-arm64": "1.10.7", - "@node-rs/bcrypt-darwin-arm64": "1.10.7", - "@node-rs/bcrypt-darwin-x64": "1.10.7", - "@node-rs/bcrypt-freebsd-x64": "1.10.7", - "@node-rs/bcrypt-linux-arm-gnueabihf": "1.10.7", - "@node-rs/bcrypt-linux-arm64-gnu": "1.10.7", - "@node-rs/bcrypt-linux-arm64-musl": "1.10.7", - "@node-rs/bcrypt-linux-x64-gnu": "1.10.7", - "@node-rs/bcrypt-linux-x64-musl": "1.10.7", - "@node-rs/bcrypt-wasm32-wasi": "1.10.7", - "@node-rs/bcrypt-win32-arm64-msvc": "1.10.7", - "@node-rs/bcrypt-win32-ia32-msvc": "1.10.7", - "@node-rs/bcrypt-win32-x64-msvc": "1.10.7" + "url": "https://opencollective.com/pkgr" } }, - "node_modules/@node-rs/bcrypt-android-arm-eabi": { - "version": "1.10.7", - "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-android-arm-eabi/-/bcrypt-android-arm-eabi-1.10.7.tgz", - "integrity": "sha512-8dO6/PcbeMZXS3VXGEtct9pDYdShp2WBOWlDvSbcRwVqyB580aCBh0BEFmKYtXLzLvUK8Wf+CG3U6sCdILW1lA==", + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.53.3.tgz", + "integrity": "sha512-mRSi+4cBjrRLoaal2PnqH82Wqyb+d3HsPUN/W+WslCXsZsyHa9ZeQQX/pQsZaVIWDkPcpV6jJ+3KLbTbgnwv8w==", "cpu": [ "arm" ], @@ -999,15 +1757,12 @@ "optional": true, "os": [ "android" - ], - "engines": { - "node": ">= 10" - } + ] }, - "node_modules/@node-rs/bcrypt-android-arm64": { - "version": "1.10.7", - "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-android-arm64/-/bcrypt-android-arm64-1.10.7.tgz", - "integrity": "sha512-UASFBS/CucEMHiCtL/2YYsAY01ZqVR1N7vSb94EOvG5iwW7BQO06kXXCTgj+Xbek9azxixrCUmo3WJnkJZ0hTQ==", + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.53.3.tgz", + "integrity": "sha512-CbDGaMpdE9sh7sCmTrTUyllhrg65t6SwhjlMJsLr+J8YjFuPmCEjbBSx4Z/e4SmDyH3aB5hGaJUP2ltV/vcs4w==", "cpu": [ "arm64" ], @@ -1016,15 +1771,12 @@ "optional": true, "os": [ "android" - ], - "engines": { - "node": ">= 10" - } + ] }, - "node_modules/@node-rs/bcrypt-darwin-arm64": { - "version": "1.10.7", - "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-darwin-arm64/-/bcrypt-darwin-arm64-1.10.7.tgz", - "integrity": "sha512-DgzFdAt455KTuiJ/zYIyJcKFobjNDR/hnf9OS7pK5NRS13Nq4gLcSIIyzsgHwZHxsJWbLpHmFc1H23Y7IQoQBw==", + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.53.3.tgz", + "integrity": "sha512-Nr7SlQeqIBpOV6BHHGZgYBuSdanCXuw09hon14MGOLGmXAFYjx1wNvquVPmpZnl0tLjg25dEdr4IQ6GgyToCUA==", "cpu": [ "arm64" ], @@ -1033,15 +1785,12 @@ "optional": true, "os": [ "darwin" - ], - "engines": { - "node": ">= 10" - } + ] }, - "node_modules/@node-rs/bcrypt-darwin-x64": { - "version": "1.10.7", - "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-darwin-x64/-/bcrypt-darwin-x64-1.10.7.tgz", - "integrity": "sha512-SPWVfQ6sxSokoUWAKWD0EJauvPHqOGQTd7CxmYatcsUgJ/bruvEHxZ4bIwX1iDceC3FkOtmeHO0cPwR480n/xA==", + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.53.3.tgz", + "integrity": "sha512-DZ8N4CSNfl965CmPktJ8oBnfYr3F8dTTNBQkRlffnUarJ2ohudQD17sZBa097J8xhQ26AwhHJ5mvUyQW8ddTsQ==", "cpu": [ "x64" ], @@ -1050,15 +1799,26 @@ "optional": true, "os": [ "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.53.3.tgz", + "integrity": "sha512-yMTrCrK92aGyi7GuDNtGn2sNW+Gdb4vErx4t3Gv/Tr+1zRb8ax4z8GWVRfr3Jw8zJWvpGHNpss3vVlbF58DZ4w==", + "cpu": [ + "arm64" ], - "engines": { - "node": ">= 10" - } + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] }, - "node_modules/@node-rs/bcrypt-freebsd-x64": { - "version": "1.10.7", - "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-freebsd-x64/-/bcrypt-freebsd-x64-1.10.7.tgz", - "integrity": "sha512-gpa+Ixs6GwEx6U6ehBpsQetzUpuAGuAFbOiuLB2oo4N58yU4AZz1VIcWyWAHrSWRs92O0SHtmo2YPrMrwfBbSw==", + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.53.3.tgz", + "integrity": "sha512-lMfF8X7QhdQzseM6XaX0vbno2m3hlyZFhwcndRMw8fbAGUGL3WFMBdK0hbUBIUYcEcMhVLr1SIamDeuLBnXS+Q==", "cpu": [ "x64" ], @@ -1067,15 +1827,26 @@ "optional": true, "os": [ "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.53.3.tgz", + "integrity": "sha512-k9oD15soC/Ln6d2Wv/JOFPzZXIAIFLp6B+i14KhxAfnq76ajt0EhYc5YPeX6W1xJkAdItcVT+JhKl1QZh44/qw==", + "cpu": [ + "arm" ], - "engines": { - "node": ">= 10" - } + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/@node-rs/bcrypt-linux-arm-gnueabihf": { - "version": "1.10.7", - "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-linux-arm-gnueabihf/-/bcrypt-linux-arm-gnueabihf-1.10.7.tgz", - "integrity": "sha512-kYgJnTnpxrzl9sxYqzflobvMp90qoAlaX1oDL7nhNTj8OYJVDIk0jQgblj0bIkjmoPbBed53OJY/iu4uTS+wig==", + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.53.3.tgz", + "integrity": "sha512-vTNlKq+N6CK/8UktsrFuc+/7NlEYVxgaEgRXVUVK258Z5ymho29skzW1sutgYjqNnquGwVUObAaxae8rZ6YMhg==", "cpu": [ "arm" ], @@ -1084,49 +1855,110 @@ "optional": true, "os": [ "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.53.3.tgz", + "integrity": "sha512-RGrFLWgMhSxRs/EWJMIFM1O5Mzuz3Xy3/mnxJp/5cVhZ2XoCAxJnmNsEyeMJtpK+wu0FJFWz+QF4mjCA7AUQ3w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.53.3.tgz", + "integrity": "sha512-kASyvfBEWYPEwe0Qv4nfu6pNkITLTb32p4yTgzFCocHnJLAHs+9LjUu9ONIhvfT/5lv4YS5muBHyuV84epBo/A==", + "cpu": [ + "arm64" ], - "engines": { - "node": ">= 10" - } + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.53.3.tgz", + "integrity": "sha512-JiuKcp2teLJwQ7vkJ95EwESWkNRFJD7TQgYmCnrPtlu50b4XvT5MOmurWNrCj3IFdyjBQ5p9vnrX4JM6I8OE7g==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.53.3.tgz", + "integrity": "sha512-EoGSa8nd6d3T7zLuqdojxC20oBfNT8nexBbB/rkxgKj5T5vhpAQKKnD+h3UkoMuTyXkP5jTjK/ccNRmQrPNDuw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.53.3.tgz", + "integrity": "sha512-4s+Wped2IHXHPnAEbIB0YWBv7SDohqxobiiPA1FIWZpX+w9o2i4LezzH/NkFUl8LRci/8udci6cLq+jJQlh+0g==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/@node-rs/bcrypt-linux-arm64-gnu": { - "version": "1.10.7", - "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-linux-arm64-gnu/-/bcrypt-linux-arm64-gnu-1.10.7.tgz", - "integrity": "sha512-7cEkK2RA+gBCj2tCVEI1rDSJV40oLbSq7bQ+PNMHNI6jCoXGmj9Uzo7mg7ZRbNZ7piIyNH5zlJqutjo8hh/tmA==", + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.53.3.tgz", + "integrity": "sha512-68k2g7+0vs2u9CxDt5ktXTngsxOQkSEV/xBbwlqYcUrAVh6P9EgMZvFsnHy4SEiUl46Xf0IObWVbMvPrr2gw8A==", "cpu": [ - "arm64" + "riscv64" ], "dev": true, "license": "MIT", "optional": true, "os": [ "linux" - ], - "engines": { - "node": ">= 10" - } + ] }, - "node_modules/@node-rs/bcrypt-linux-arm64-musl": { - "version": "1.10.7", - "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-linux-arm64-musl/-/bcrypt-linux-arm64-musl-1.10.7.tgz", - "integrity": "sha512-X7DRVjshhwxUqzdUKDlF55cwzh+wqWJ2E/tILvZPboO3xaNO07Um568Vf+8cmKcz+tiZCGP7CBmKbBqjvKN/Pw==", + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.53.3.tgz", + "integrity": "sha512-VYsFMpULAz87ZW6BVYw3I6sWesGpsP9OPcyKe8ofdg9LHxSbRMd7zrVrr5xi/3kMZtpWL/wC+UIJWJYVX5uTKg==", "cpu": [ - "arm64" + "s390x" ], "dev": true, "license": "MIT", "optional": true, "os": [ "linux" - ], - "engines": { - "node": ">= 10" - } + ] }, - "node_modules/@node-rs/bcrypt-linux-x64-gnu": { - "version": "1.10.7", - "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-linux-x64-gnu/-/bcrypt-linux-x64-gnu-1.10.7.tgz", - "integrity": "sha512-LXRZsvG65NggPD12hn6YxVgH0W3VR5fsE/o1/o2D5X0nxKcNQGeLWnRzs5cP8KpoFOuk1ilctXQJn8/wq+Gn/Q==", + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.53.3.tgz", + "integrity": "sha512-3EhFi1FU6YL8HTUJZ51imGJWEX//ajQPfqWLI3BQq4TlvHy4X0MOr5q3D2Zof/ka0d5FNdPwZXm3Yyib/UEd+w==", "cpu": [ "x64" ], @@ -1135,15 +1967,12 @@ "optional": true, "os": [ "linux" - ], - "engines": { - "node": ">= 10" - } + ] }, - "node_modules/@node-rs/bcrypt-linux-x64-musl": { - "version": "1.10.7", - "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-linux-x64-musl/-/bcrypt-linux-x64-musl-1.10.7.tgz", - "integrity": "sha512-tCjHmct79OfcO3g5q21ME7CNzLzpw1MAsUXCLHLGWH+V6pp/xTvMbIcLwzkDj6TI3mxK6kehTn40SEjBkZ3Rog==", + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.53.3.tgz", + "integrity": "sha512-eoROhjcc6HbZCJr+tvVT8X4fW3/5g/WkGvvmwz/88sDtSJzO7r/blvoBDgISDiCjDRZmHpwud7h+6Q9JxFwq1Q==", "cpu": [ "x64" ], @@ -1152,32 +1981,26 @@ "optional": true, "os": [ "linux" - ], - "engines": { - "node": ">= 10" - } + ] }, - "node_modules/@node-rs/bcrypt-wasm32-wasi": { - "version": "1.10.7", - "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-wasm32-wasi/-/bcrypt-wasm32-wasi-1.10.7.tgz", - "integrity": "sha512-4qXSihIKeVXYglfXZEq/QPtYtBUvR8d3S85k15Lilv3z5B6NSGQ9mYiNleZ7QHVLN2gEc5gmi7jM353DMH9GkA==", + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.53.3.tgz", + "integrity": "sha512-OueLAWgrNSPGAdUdIjSWXw+u/02BRTcnfw9PN41D2vq/JSEPnJnVuBgw18VkN8wcd4fjUs+jFHVM4t9+kBSNLw==", "cpu": [ - "wasm32" + "arm64" ], "dev": true, "license": "MIT", "optional": true, - "dependencies": { - "@napi-rs/wasm-runtime": "^0.2.5" - }, - "engines": { - "node": ">=14.0.0" - } + "os": [ + "openharmony" + ] }, - "node_modules/@node-rs/bcrypt-win32-arm64-msvc": { - "version": "1.10.7", - "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-win32-arm64-msvc/-/bcrypt-win32-arm64-msvc-1.10.7.tgz", - "integrity": "sha512-FdfUQrqmDfvC5jFhntMBkk8EI+fCJTx/I1v7Rj+Ezlr9rez1j1FmuUnywbBj2Cg15/0BDhwYdbyZ5GCMFli2aQ==", + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.53.3.tgz", + "integrity": "sha512-GOFuKpsxR/whszbF/bzydebLiXIHSgsEUp6M0JI8dWvi+fFa1TD6YQa4aSZHtpmh2/uAlj/Dy+nmby3TJ3pkTw==", "cpu": [ "arm64" ], @@ -1186,15 +2009,12 @@ "optional": true, "os": [ "win32" - ], - "engines": { - "node": ">= 10" - } + ] }, - "node_modules/@node-rs/bcrypt-win32-ia32-msvc": { - "version": "1.10.7", - "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-win32-ia32-msvc/-/bcrypt-win32-ia32-msvc-1.10.7.tgz", - "integrity": "sha512-lZLf4Cx+bShIhU071p5BZft4OvP4PGhyp542EEsb3zk34U5GLsGIyCjOafcF/2DGewZL6u8/aqoxbSuROkgFXg==", + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.53.3.tgz", + "integrity": "sha512-iah+THLcBJdpfZ1TstDFbKNznlzoxa8fmnFYK4V67HvmuNYkVdAywJSoteUszvBQ9/HqN2+9AZghbajMsFT+oA==", "cpu": [ "ia32" ], @@ -1203,15 +2023,12 @@ "optional": true, "os": [ "win32" - ], - "engines": { - "node": ">= 10" - } + ] }, - "node_modules/@node-rs/bcrypt-win32-x64-msvc": { - "version": "1.10.7", - "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-win32-x64-msvc/-/bcrypt-win32-x64-msvc-1.10.7.tgz", - "integrity": "sha512-hdw7tGmN1DxVAMTzICLdaHpXjy+4rxaxnBMgI8seG1JL5e3VcRGsd1/1vVDogVp2cbsmgq+6d6yAY+D9lW/DCg==", + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.53.3.tgz", + "integrity": "sha512-J9QDiOIZlZLdcot5NXEepDkstocktoVjkaKUtqzgzpt2yWjGlbYiKyp05rWwk4nypbYUNoFAztEgixoLaSETkg==", "cpu": [ "x64" ], @@ -1220,100 +2037,46 @@ "optional": true, "os": [ "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nrchkb/logger": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@nrchkb/logger/-/logger-3.1.1.tgz", - "integrity": "sha512-37m4lq7Jemg7qzkBflD+VZ1HnFdZv10k9hgglonFXTBMrLmXxkXllWelCKDGABVkfx1hjijAz6IpQoIF+Oo9yw==", - "license": "Apache-2.0", - "dependencies": { - "debug": "^4.3.5" - } - }, - "node_modules/@paralleldrive/cuid2": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/@paralleldrive/cuid2/-/cuid2-2.3.1.tgz", - "integrity": "sha512-XO7cAxhnTZl0Yggq6jOgjiOHhbgcO4NqFqwSmQpjK3b6TEE6Uj/jfSk6wzYyemh3+I0sHirKSetjQwn5cZktFw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@noble/hashes": "^1.1.5" - } + ] }, - "node_modules/@pkgjs/parseargs": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.53.3.tgz", + "integrity": "sha512-UhTd8u31dXadv0MopwGgNOBpUVROFKWVQgAg5N1ESyCz8AuBcMqm4AuTjrwgQKGDfoFuz02EuMRHQIw/frmYKQ==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", "optional": true, - "engines": { - "node": ">=14" - } + "os": [ + "win32" + ] }, - "node_modules/@pkgr/core": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.9.tgz", - "integrity": "sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==", + "node_modules/@sindresorhus/is": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-5.6.0.tgz", + "integrity": "sha512-TV7t8GKYaJWsn00tFDqBw8+Uqmr8A0fRU1tvTQhyZzGv0sJCGRQL3JGMI3ucuKo3XIZdUP+Lx7/gh2t3lewy7g==", "dev": true, "license": "MIT", "engines": { - "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + "node": ">=14.16" }, "funding": { - "url": "https://opencollective.com/pkgr" + "url": "https://github.com/sindresorhus/is?sponsor=1" } }, - "node_modules/@sindresorhus/is": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-5.6.0.tgz", - "integrity": "sha512-TV7t8GKYaJWsn00tFDqBw8+Uqmr8A0fRU1tvTQhyZzGv0sJCGRQL3JGMI3ucuKo3XIZdUP+Lx7/gh2t3lewy7g==", + "node_modules/@sindresorhus/merge-streams": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-2.3.0.tgz", + "integrity": "sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==", "dev": true, "license": "MIT", "engines": { - "node": ">=14.16" + "node": ">=18" }, "funding": { - "url": "https://github.com/sindresorhus/is?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/@sinonjs/commons": { @@ -1351,6 +2114,13 @@ "integrity": "sha512-sXXKG+uL9IrKqViTtao2Ws6dy0znu9sOaP1di/jKGW1M6VssO8vlpXCQcpZ+jisQ1tTFAC5Jo/EOzFbggBagFQ==", "dev": true }, + "node_modules/@standard-schema/spec": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.0.0.tgz", + "integrity": "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==", + "dev": true, + "license": "MIT" + }, "node_modules/@szmarczak/http-timer": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-5.0.1.tgz", @@ -1415,6 +2185,17 @@ "@types/node": "*" } }, + "node_modules/@types/chai": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz", + "integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/deep-eql": "*", + "assertion-error": "^2.0.1" + } + }, "node_modules/@types/connect": { "version": "3.4.35", "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", @@ -1439,6 +2220,20 @@ "@types/node": "*" } }, + "node_modules/@types/deep-eql": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", + "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/express": { "version": "4.17.17", "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.17.tgz", @@ -1491,19 +2286,6 @@ "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==", "dev": true }, - "node_modules/@types/minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==", - "dev": true - }, - "node_modules/@types/mocha": { - "version": "10.0.10", - "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.10.tgz", - "integrity": "sha512-xPyYSz1cMPnJQhl0CLMH68j3gprKZaTjG3s5Vi+fDgx+uhG9NOXwbVt52eFS8ECyXhyKcjDLCBEqBExKuiZb7Q==", - "dev": true, - "license": "MIT" - }, "node_modules/@types/node": { "version": "20.19.25", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.25.tgz", @@ -1609,12 +2391,6 @@ "@types/supertest": "*" } }, - "node_modules/@types/normalize-package-data": { - "version": "2.4.4", - "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", - "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==", - "dev": true - }, "node_modules/@types/passport": { "version": "1.0.12", "resolved": "https://registry.npmjs.org/@types/passport/-/passport-1.0.12.tgz", @@ -1955,6 +2731,117 @@ "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", "dev": true }, + "node_modules/@vitest/expect": { + "version": "4.0.13", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.0.13.tgz", + "integrity": "sha512-zYtcnNIBm6yS7Gpr7nFTmq8ncowlMdOJkWLqYvhr/zweY6tFbDkDi8BPPOeHxEtK1rSI69H7Fd4+1sqvEGli6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@standard-schema/spec": "^1.0.0", + "@types/chai": "^5.2.2", + "@vitest/spy": "4.0.13", + "@vitest/utils": "4.0.13", + "chai": "^6.2.1", + "tinyrainbow": "^3.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/mocker": { + "version": "4.0.13", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.0.13.tgz", + "integrity": "sha512-eNCwzrI5djoauklwP1fuslHBjrbR8rqIVbvNlAnkq1OTa6XT+lX68mrtPirNM9TnR69XUPt4puBCx2Wexseylg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/spy": "4.0.13", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.21" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "msw": "^2.4.9", + "vite": "^6.0.0 || ^7.0.0-0" + }, + "peerDependenciesMeta": { + "msw": { + "optional": true + }, + "vite": { + "optional": true + } + } + }, + "node_modules/@vitest/pretty-format": { + "version": "4.0.13", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.0.13.tgz", + "integrity": "sha512-ooqfze8URWbI2ozOeLDMh8YZxWDpGXoeY3VOgcDnsUxN0jPyPWSUvjPQWqDGCBks+opWlN1E4oP1UYl3C/2EQA==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyrainbow": "^3.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner": { + "version": "4.0.13", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.0.13.tgz", + "integrity": "sha512-9IKlAru58wcVaWy7hz6qWPb2QzJTKt+IOVKjAx5vb5rzEFPTL6H4/R9BMvjZ2ppkxKgTrFONEJFtzvnyEpiT+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/utils": "4.0.13", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/snapshot": { + "version": "4.0.13", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.0.13.tgz", + "integrity": "sha512-hb7Usvyika1huG6G6l191qu1urNPsq1iFc2hmdzQY3F5/rTgqQnwwplyf8zoYHkpt7H6rw5UfIw6i/3qf9oSxQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "4.0.13", + "magic-string": "^0.30.21", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/spy": { + "version": "4.0.13", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.0.13.tgz", + "integrity": "sha512-hSu+m4se0lDV5yVIcNWqjuncrmBgwaXa2utFLIrBkQCQkt+pSwyZTPFQAZiiF/63j8jYa8uAeUZ3RSfcdWaYWw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils": { + "version": "4.0.13", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.0.13.tgz", + "integrity": "sha512-ydozWyQ4LZuu8rLp47xFUWis5VOKMdHjXCWhs1LuJsTNKww+pTHQNK4e0assIB9K80TxFyskENL6vCu3j34EYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "4.0.13", + "tinyrainbow": "^3.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, "node_modules/abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", @@ -2027,28 +2914,12 @@ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", "dev": true, - "license": "MIT", - "dependencies": { - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/aggregate-error": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-4.0.1.tgz", - "integrity": "sha512-0poP0T7el6Vq3rstR8Mn4V/IQrpBLO6POkUSrN7RhyY+GF/InCFShQzsQ39T25gkHhLgSLByyAz+Kjb+c2L98w==", - "dev": true, + "license": "MIT", "dependencies": { - "clean-stack": "^4.0.0", - "indent-string": "^5.0.0" + "debug": "4" }, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 6.0.0" } }, "node_modules/ajv": { @@ -2098,19 +2969,6 @@ "node": ">=4" } }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, "node_modules/append-field": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", @@ -2162,15 +3020,6 @@ "node": ">=8" } }, - "node_modules/arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/asap": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", @@ -2178,6 +3027,16 @@ "dev": true, "license": "MIT" }, + "node_modules/assertion-error": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + } + }, "node_modules/async-mutex": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/async-mutex/-/async-mutex-0.5.0.tgz", @@ -2307,15 +3166,6 @@ "bcrypt": "bin/bcrypt" } }, - "node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/bl": { "version": "6.1.4", "resolved": "https://registry.npmjs.org/bl/-/bl-6.1.4.tgz", @@ -2423,12 +3273,6 @@ "node": ">=8" } }, - "node_modules/browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true - }, "node_modules/buffer": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", @@ -2549,34 +3393,14 @@ "node": ">=6" } }, - "node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/camelcase-keys": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-7.0.2.tgz", - "integrity": "sha512-Rjs1H+A9R+Ig+4E/9oyB66UC5Mj9Xq3N//vcLf2WzgdTi/3gUu3Z9KoqmlrEG4VuuLK8wJHofxzdQXz/knhiYg==", + "node_modules/chai": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/chai/-/chai-6.2.1.tgz", + "integrity": "sha512-p4Z49OGG5W/WBCPSS/dH3jQ73kD6tiMmUM+bckNK6Jr5JHMG3k9bg/BvKR8lKmtVBKmOiuVaV2ws8s9oSbwysg==", "dev": true, - "dependencies": { - "camelcase": "^6.3.0", - "map-obj": "^4.1.0", - "quick-lru": "^5.1.1", - "type-fest": "^1.2.1" - }, + "license": "MIT", "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=18" } }, "node_modules/chalk": { @@ -2632,45 +3456,6 @@ "url": "https://github.com/sponsors/fb55" } }, - "node_modules/chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/chokidar/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/chownr": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", @@ -2681,33 +3466,6 @@ "node": ">=18" } }, - "node_modules/clean-stack": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-4.2.0.tgz", - "integrity": "sha512-LYv6XPxoyODi36Dp976riBtSY27VmFo+MKqEU9QCCWyTrdEPDog+RWA7xQWHi6Vbp61j5c4cdzzX1NidnwtUWg==", - "dev": true, - "dependencies": { - "escape-string-regexp": "5.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/clean-stack/node_modules/escape-string-regexp": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", - "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/cli-table": { "version": "0.3.11", "resolved": "https://registry.npmjs.org/cli-table/-/cli-table-0.3.11.tgz", @@ -2720,17 +3478,6 @@ "node": ">= 0.2.0" } }, - "node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, "node_modules/clone": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", @@ -2982,52 +3729,6 @@ } } }, - "node_modules/decamelize": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", - "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/decamelize-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.1.tgz", - "integrity": "sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==", - "dev": true, - "dependencies": { - "decamelize": "^1.1.0", - "map-obj": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/decamelize-keys/node_modules/decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/decamelize-keys/node_modules/map-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", - "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/decompress-response": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", @@ -3139,71 +3840,86 @@ } }, "node_modules/del": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/del/-/del-7.1.0.tgz", - "integrity": "sha512-v2KyNk7efxhlyHpjEvfyxaAihKKK0nWCuf6ZtqZcFFpQRG0bJ12Qsr0RpvsICMjAAZ8DOVCxrlqpxISlMHC4Kg==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/del/-/del-8.0.1.tgz", + "integrity": "sha512-gPqh0mKTPvaUZGAuHbrBUYKZWBNAeHG7TU3QH5EhVwPMyKvmfJaNXhcD2jTcXsJRRcffuho4vaYweu80dRrMGA==", "dev": true, + "license": "MIT", "dependencies": { - "globby": "^13.1.2", - "graceful-fs": "^4.2.10", + "globby": "^14.0.2", "is-glob": "^4.0.3", "is-path-cwd": "^3.0.0", "is-path-inside": "^4.0.0", - "p-map": "^5.5.0", - "rimraf": "^3.0.2", - "slash": "^4.0.0" + "p-map": "^7.0.2", + "presentable-error": "^0.0.1", + "slash": "^5.1.0" }, "engines": { - "node": ">=14.16" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/del-cli": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/del-cli/-/del-cli-5.1.0.tgz", - "integrity": "sha512-xwMeh2acluWeccsfzE7VLsG3yTr7nWikbfw+xhMnpRrF15pGSkw+3/vJZWlGoE4I86UiLRNHicmKt4tkIX9Jtg==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/del-cli/-/del-cli-7.0.0.tgz", + "integrity": "sha512-fRl4pWJYu9WFQH8jXdQUYvcD0IMtij9WEc7qmB7xOyJEweNJNuE7iKmqNeoOT1DbBUjtRjxlw8Y63qKBI/NQ1g==", "dev": true, + "license": "MIT", "dependencies": { - "del": "^7.1.0", - "meow": "^10.1.3" + "del": "^8.0.1", + "meow": "^14.0.0", + "presentable-error": "^0.0.1" }, "bin": { "del": "cli.js", "del-cli": "cli.js" }, "engines": { - "node": ">=14.16" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/del/node_modules/globby": { - "version": "13.2.2", - "resolved": "https://registry.npmjs.org/globby/-/globby-13.2.2.tgz", - "integrity": "sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==", + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-14.1.0.tgz", + "integrity": "sha512-0Ia46fDOaT7k4og1PDW4YbodWWr3scS2vAr2lTbsplOt2WkKp0vQbkI9wKis/T5LV/dqPjO3bpS/z6GTJB82LA==", "dev": true, + "license": "MIT", "dependencies": { - "dir-glob": "^3.0.1", - "fast-glob": "^3.3.0", - "ignore": "^5.2.4", - "merge2": "^1.4.1", - "slash": "^4.0.0" + "@sindresorhus/merge-streams": "^2.1.0", + "fast-glob": "^3.3.3", + "ignore": "^7.0.3", + "path-type": "^6.0.0", + "slash": "^5.1.0", + "unicorn-magic": "^0.3.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/del/node_modules/ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, "node_modules/del/node_modules/is-path-inside": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-4.0.0.tgz", "integrity": "sha512-lJJV/5dYS+RcL8uQdBDW9c9uWFLLBNRyFhnAKXw5tVqLlKZ4RMGZKv+YQ/IA3OhD+RpbJa1LLFM1FQPGyIXvOA==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -3211,29 +3927,27 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/del/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", + "node_modules/del/node_modules/path-type": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-6.0.0.tgz", + "integrity": "sha512-Vj7sf++t5pBD637NSfkxpHSMfWaeig5+DKWLhcqIYx6mWQz5hdJTGDVMQiJcw1ZYkhs7AazKDGpRVji1LJCZUQ==", "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" + "license": "MIT", + "engines": { + "node": ">=18" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/del/node_modules/slash": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", - "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", + "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", "dev": true, + "license": "MIT", "engines": { - "node": ">=12" + "node": ">=14.16" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -3466,15 +4180,6 @@ "url": "https://github.com/fb55/entities?sponsor=1" } }, - "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "dependencies": { - "is-arrayish": "^0.2.1" - } - }, "node_modules/es-define-property": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", @@ -3512,6 +4217,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/es-module-lexer": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", + "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", + "dev": true, + "license": "MIT" + }, "node_modules/es-object-atoms": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", @@ -3540,13 +4252,46 @@ "node": ">= 0.4" } }, - "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "node_modules/esbuild": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz", + "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==", "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, "engines": { - "node": ">=6" + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.12", + "@esbuild/android-arm": "0.25.12", + "@esbuild/android-arm64": "0.25.12", + "@esbuild/android-x64": "0.25.12", + "@esbuild/darwin-arm64": "0.25.12", + "@esbuild/darwin-x64": "0.25.12", + "@esbuild/freebsd-arm64": "0.25.12", + "@esbuild/freebsd-x64": "0.25.12", + "@esbuild/linux-arm": "0.25.12", + "@esbuild/linux-arm64": "0.25.12", + "@esbuild/linux-ia32": "0.25.12", + "@esbuild/linux-loong64": "0.25.12", + "@esbuild/linux-mips64el": "0.25.12", + "@esbuild/linux-ppc64": "0.25.12", + "@esbuild/linux-riscv64": "0.25.12", + "@esbuild/linux-s390x": "0.25.12", + "@esbuild/linux-x64": "0.25.12", + "@esbuild/netbsd-arm64": "0.25.12", + "@esbuild/netbsd-x64": "0.25.12", + "@esbuild/openbsd-arm64": "0.25.12", + "@esbuild/openbsd-x64": "0.25.12", + "@esbuild/openharmony-arm64": "0.25.12", + "@esbuild/sunos-x64": "0.25.12", + "@esbuild/win32-arm64": "0.25.12", + "@esbuild/win32-ia32": "0.25.12", + "@esbuild/win32-x64": "0.25.12" } }, "node_modules/escape-html": { @@ -3860,6 +4605,16 @@ "node": ">=4.0" } }, + "node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + } + }, "node_modules/esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", @@ -3913,6 +4668,16 @@ "node": ">=0.8.x" } }, + "node_modules/expect-type": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.2.2.tgz", + "integrity": "sha512-JhFGDVJ7tmDJItKhYgJCGLOWjuK9vPxiXoUFLwLDc99NlmklilbiQJwoctZtt13+xMw91MCk/REan6MWHqDjyA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/express": { "version": "4.21.2", "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", @@ -4047,16 +4812,17 @@ "dev": true }, "node_modules/fast-glob": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", - "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", "dev": true, + "license": "MIT", "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", - "micromatch": "^4.0.4" + "micromatch": "^4.0.8" }, "engines": { "node": ">=8.6.0" @@ -4217,15 +4983,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/flat": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", - "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", - "dev": true, - "bin": { - "flat": "cli.js" - } - }, "node_modules/flat-cache": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", @@ -4397,6 +5154,21 @@ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", "dev": true }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, "node_modules/function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", @@ -4422,15 +5194,6 @@ "node": ">=8" } }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true, - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, "node_modules/get-intrinsic": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", @@ -4593,15 +5356,6 @@ "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", "dev": true }, - "node_modules/hard-rejection": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", - "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, "node_modules/has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", @@ -4689,15 +5443,6 @@ "node": ">= 0.4" } }, - "node_modules/he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "dev": true, - "bin": { - "he": "bin/he" - } - }, "node_modules/help-me": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/help-me/-/help-me-5.0.0.tgz", @@ -4705,47 +5450,17 @@ "dev": true, "license": "MIT" }, - "node_modules/hexy": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/hexy/-/hexy-0.3.5.tgz", - "integrity": "sha512-UCP7TIZPXz5kxYJnNOym+9xaenxCLor/JyhKieo8y8/bJWunGh9xbhy3YrgYJUQ87WwfXGm05X330DszOfINZw==", - "bin": { - "hexy": "bin/hexy_cmd.js" - }, - "engines": { - "node": ">=10.4" - } - }, - "node_modules/hosted-git-info": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", - "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/hosted-git-info/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" + "node_modules/hexy": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/hexy/-/hexy-0.3.5.tgz", + "integrity": "sha512-UCP7TIZPXz5kxYJnNOym+9xaenxCLor/JyhKieo8y8/bJWunGh9xbhy3YrgYJUQ87WwfXGm05X330DszOfINZw==", + "bin": { + "hexy": "bin/hexy_cmd.js" }, "engines": { - "node": ">=10" + "node": ">=10.4" } }, - "node_modules/hosted-git-info/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, "node_modules/hpagent": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/hpagent/-/hpagent-1.2.0.tgz", @@ -4943,18 +5658,6 @@ "node": ">=0.8.19" } }, - "node_modules/indent-string": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-5.0.0.tgz", - "integrity": "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -5036,12 +5739,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "dev": true - }, "node_modules/is-bigint": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", @@ -5054,18 +5751,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/is-boolean-object": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", @@ -5192,6 +5877,7 @@ "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-3.0.0.tgz", "integrity": "sha512-kyiNFFLU0Ampr6SDZitD/DwUo4Zs1nSdnygUBqsu3LooL00Qvb5j+UnvApUn/TTj1J3OuE6BTdQ5rudKmU2ZaA==", "dev": true, + "license": "MIT", "engines": { "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, @@ -5208,15 +5894,6 @@ "node": ">=8" } }, - "node_modules/is-plain-obj": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/is-regex": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", @@ -5290,18 +5967,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/is-utf8": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", @@ -5413,12 +6078,6 @@ "dev": true, "license": "MIT" }, - "node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true - }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -5477,15 +6136,6 @@ "json-buffer": "3.0.1" } }, - "node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -5499,12 +6149,6 @@ "node": ">= 0.8.0" } }, - "node_modules/lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true - }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -5539,92 +6183,6 @@ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, - "node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-symbols/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/log-symbols/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/log-symbols/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/log-symbols/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/log-symbols/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/log-symbols/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/long": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz", @@ -5655,24 +6213,22 @@ "yallist": "^2.1.2" } }, + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, "node_modules/make-error": { "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", "dev": true }, - "node_modules/map-obj": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", - "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/map-stream": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.0.7.tgz", @@ -5712,38 +6268,13 @@ } }, "node_modules/meow": { - "version": "10.1.5", - "resolved": "https://registry.npmjs.org/meow/-/meow-10.1.5.tgz", - "integrity": "sha512-/d+PQ4GKmGvM9Bee/DPa8z3mXs/pkvJE2KEThngVNOqtmljC6K7NMPxtc2JeZYTmpWb9k/TmxjeL18ez3h7vCw==", - "dev": true, - "dependencies": { - "@types/minimist": "^1.2.2", - "camelcase-keys": "^7.0.0", - "decamelize": "^5.0.0", - "decamelize-keys": "^1.1.0", - "hard-rejection": "^2.1.0", - "minimist-options": "4.1.0", - "normalize-package-data": "^3.0.2", - "read-pkg-up": "^8.0.0", - "redent": "^4.0.0", - "trim-newlines": "^4.0.2", - "type-fest": "^1.2.2", - "yargs-parser": "^20.2.9" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/meow/node_modules/decamelize": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-5.0.1.tgz", - "integrity": "sha512-VfxadyCECXgQlkoEAjeghAr5gY3Hf+IKjKb+X8tGVDtveCjN+USwprd2q3QXBR9T1+x2DG0XZF5/w+7HAtSaXA==", + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-14.0.0.tgz", + "integrity": "sha512-JhC3R1f6dbspVtmF3vKjAWz1EVIvwFrGGPLSdU6rK79xBwHWTuHoLnRX/t1/zHS1Ch1Y2UtIrih7DAHuH9JFJA==", "dev": true, + "license": "MIT", "engines": { - "node": ">=10" + "node": ">=20" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -5838,15 +6369,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/min-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", - "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -5867,29 +6389,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/minimist-options": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", - "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", - "dev": true, - "dependencies": { - "arrify": "^1.0.1", - "is-plain-obj": "^1.1.0", - "kind-of": "^6.0.3" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/minimist-options/node_modules/is-plain-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/minipass": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", @@ -5922,121 +6421,7 @@ "minimist": "^1.2.6" }, "bin": { - "mkdirp": "bin/cmd.js" - } - }, - "node_modules/mocha": { - "version": "10.6.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.6.0.tgz", - "integrity": "sha512-hxjt4+EEB0SA0ZDygSS015t65lJw/I2yRCS3Ae+SJ5FrbzrXgfYwJr96f0OvIXdj7h4lv/vLCrH3rkiuizFSvw==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-colors": "^4.1.3", - "browser-stdout": "^1.3.1", - "chokidar": "^3.5.3", - "debug": "^4.3.5", - "diff": "^5.2.0", - "escape-string-regexp": "^4.0.0", - "find-up": "^5.0.0", - "glob": "^8.1.0", - "he": "^1.2.0", - "js-yaml": "^4.1.0", - "log-symbols": "^4.1.0", - "minimatch": "^5.1.6", - "ms": "^2.1.3", - "serialize-javascript": "^6.0.2", - "strip-json-comments": "^3.1.1", - "supports-color": "^8.1.1", - "workerpool": "^6.5.1", - "yargs": "^16.2.0", - "yargs-parser": "^20.2.9", - "yargs-unparser": "^2.0.0" - }, - "bin": { - "_mocha": "bin/_mocha", - "mocha": "bin/mocha.js" - }, - "engines": { - "node": ">= 14.0.0" - } - }, - "node_modules/mocha/node_modules/brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/mocha/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mocha/node_modules/glob": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/mocha/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/mocha/node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/mocha/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" + "mkdirp": "bin/cmd.js" } }, "node_modules/moment": { @@ -6201,6 +6586,25 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -6396,30 +6800,6 @@ "node": ">=6" } }, - "node_modules/normalize-package-data": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", - "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", - "dev": true, - "dependencies": { - "hosted-git-info": "^4.0.1", - "is-core-module": "^2.5.0", - "semver": "^7.3.4", - "validate-npm-package-license": "^3.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/normalize-url": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-8.1.0.tgz", @@ -6647,15 +7027,13 @@ } }, "node_modules/p-map": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-5.5.0.tgz", - "integrity": "sha512-VFqfGDHlx87K66yZrNdI4YGtD70IRyd+zSvgks6mzHPRNkoKy+9EKP4SFC77/vTTQYmRmti7dvqC+m5jBrBAcg==", + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-7.0.4.tgz", + "integrity": "sha512-tkAQEw8ysMzmkhgw8k+1U/iPhWNhykKnSk4Rd5zLoPJCuJaGRPo6YposrZgaxHKzDHdDWWZvE/Sk7hsL2X/CpQ==", "dev": true, - "dependencies": { - "aggregate-error": "^4.0.0" - }, + "license": "MIT", "engines": { - "node": ">=12" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -6680,24 +7058,6 @@ "node": ">=6" } }, - "node_modules/parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/parse5": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", @@ -6850,6 +7210,13 @@ "node": ">=8" } }, + "node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "dev": true, + "license": "MIT" + }, "node_modules/pause": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", @@ -6864,6 +7231,13 @@ "through": "~2.3" } }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, "node_modules/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", @@ -6885,6 +7259,35 @@ "node": ">= 0.4" } }, + "node_modules/postcss": { + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -6894,6 +7297,19 @@ "node": ">= 0.8.0" } }, + "node_modules/presentable-error": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/presentable-error/-/presentable-error-0.0.1.tgz", + "integrity": "sha512-E6rsNU1QNJgB3sjj7OANinGncFKuK+164sLXw1/CqBjj/EkXSoSdHCtWQGBNlREIGLnL7IEUEGa08YFVUbrhVg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/prettier": { "version": "3.6.2", "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz", @@ -7043,16 +7459,6 @@ "node": ">= 0.8" } }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, "node_modules/range-parser": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", @@ -7103,41 +7509,6 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/read-pkg": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-6.0.0.tgz", - "integrity": "sha512-X1Fu3dPuk/8ZLsMhEj5f4wFAF0DWoK7qhGJvgaijocXxBmSToKfbFtqbxMO7bVjNA1dmE5huAzjXj/ey86iw9Q==", - "dev": true, - "dependencies": { - "@types/normalize-package-data": "^2.4.0", - "normalize-package-data": "^3.0.2", - "parse-json": "^5.2.0", - "type-fest": "^1.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/read-pkg-up": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-8.0.0.tgz", - "integrity": "sha512-snVCqPczksT0HS2EC+SxUndvSzn6LRCwpfSvLrIfR5BKDQQZMaI6jPRC9dYvYFDRAuFEAnkwww8kBBNE/3VvzQ==", - "dev": true, - "dependencies": { - "find-up": "^5.0.0", - "read-pkg": "^6.0.0", - "type-fest": "^1.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/readable-stream": { "version": "4.7.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz", @@ -7155,34 +7526,6 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/redent": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-4.0.0.tgz", - "integrity": "sha512-tYkDkVVtYkSVhuQ4zBgfvciymHaeuel+zFKXShfDnFP5SyVEP7qo70Rf1jTOTCx3vGNAbnEi/xFkcfQVMIBWag==", - "dev": true, - "dependencies": { - "indent-string": "^5.0.0", - "strip-indent": "^4.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/regexp.prototype.flags": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", @@ -7208,15 +7551,6 @@ "dev": true, "license": "MIT" }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/require-from-string": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", @@ -7356,6 +7690,48 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/rollup": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.53.3.tgz", + "integrity": "sha512-w8GmOxZfBmKknvdXU1sdM9NHcoQejwF/4mNgj2JuEEdRaHwwF12K7e9eXn1nLZ07ad+du76mkVsyeb2rKGllsA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.8" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.53.3", + "@rollup/rollup-android-arm64": "4.53.3", + "@rollup/rollup-darwin-arm64": "4.53.3", + "@rollup/rollup-darwin-x64": "4.53.3", + "@rollup/rollup-freebsd-arm64": "4.53.3", + "@rollup/rollup-freebsd-x64": "4.53.3", + "@rollup/rollup-linux-arm-gnueabihf": "4.53.3", + "@rollup/rollup-linux-arm-musleabihf": "4.53.3", + "@rollup/rollup-linux-arm64-gnu": "4.53.3", + "@rollup/rollup-linux-arm64-musl": "4.53.3", + "@rollup/rollup-linux-loong64-gnu": "4.53.3", + "@rollup/rollup-linux-ppc64-gnu": "4.53.3", + "@rollup/rollup-linux-riscv64-gnu": "4.53.3", + "@rollup/rollup-linux-riscv64-musl": "4.53.3", + "@rollup/rollup-linux-s390x-gnu": "4.53.3", + "@rollup/rollup-linux-x64-gnu": "4.53.3", + "@rollup/rollup-linux-x64-musl": "4.53.3", + "@rollup/rollup-openharmony-arm64": "4.53.3", + "@rollup/rollup-win32-arm64-msvc": "4.53.3", + "@rollup/rollup-win32-ia32-msvc": "4.53.3", + "@rollup/rollup-win32-x64-gnu": "4.53.3", + "@rollup/rollup-win32-x64-msvc": "4.53.3", + "fsevents": "~2.3.2" + } + }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -7486,16 +7862,6 @@ "node": ">=4" } }, - "node_modules/serialize-javascript": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", - "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "randombytes": "^2.1.0" - } - }, "node_modules/serve-static": { "version": "1.16.2", "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", @@ -7651,6 +8017,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/siginfo": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", + "dev": true, + "license": "ISC" + }, "node_modules/signal-exit": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", @@ -7747,6 +8120,16 @@ "node": ">=0.10.0" } }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/source-map-support": { "version": "0.5.21", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", @@ -7756,38 +8139,6 @@ "source-map": "^0.6.0" } }, - "node_modules/spdx-correct": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", - "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", - "dev": true, - "dependencies": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-exceptions": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", - "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", - "dev": true - }, - "node_modules/spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "dev": true, - "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-license-ids": { - "version": "3.0.18", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.18.tgz", - "integrity": "sha512-xxRs31BqRYHwiMzudOrpSiHtZ8i/GeionCBDSilhYRj+9gIcI8wCZTlXZKu9vZIVqViP3dcp9qE5G6AlIaD+TQ==", - "dev": true - }, "node_modules/split": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", @@ -7809,6 +8160,13 @@ "node": ">= 10.x" } }, + "node_modules/stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", + "dev": true, + "license": "MIT" + }, "node_modules/statuses": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", @@ -7818,6 +8176,13 @@ "node": ">= 0.8" } }, + "node_modules/std-env": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz", + "integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==", + "dev": true, + "license": "MIT" + }, "node_modules/stop-iteration-iterator": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz", @@ -7924,21 +8289,6 @@ "node": ">=8" } }, - "node_modules/strip-indent": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-4.0.0.tgz", - "integrity": "sha512-mnVSV2l+Zv6BLpSD/8V87CW/y9EmmbYzGCIavsnsI6/nwn26DwffM/yztm30Z/I2DY9wdS3vXVCMnHDgZaVNoA==", - "dev": true, - "dependencies": { - "min-indent": "^1.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -8067,39 +8417,111 @@ "mkdirp": "dist/cjs/src/bin.js" }, "engines": { - "node": ">=10" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/tar/node_modules/yallist": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", + "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==" + }, + "node_modules/thunky": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", + "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", + "license": "MIT" + }, + "node_modules/tinybench": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", + "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinyexec": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz", + "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinyglobby": { + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyglobby/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/tinyglobby/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/tar/node_modules/yallist": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", - "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", + "node_modules/tinyrainbow": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.0.3.tgz", + "integrity": "sha512-PSkbLUoxOFRzJYjjxHJt9xro7D+iilgMX/C9lawzVuYiIdcihh9DXmVibBe8lmcFrRi/VzlPjBxbN7rH24q8/Q==", "dev": true, - "license": "BlueOak-1.0.0", + "license": "MIT", "engines": { - "node": ">=18" + "node": ">=14.0.0" } }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true - }, - "node_modules/through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==" - }, - "node_modules/thunky": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", - "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", - "license": "MIT" - }, "node_modules/tldts": { "version": "6.1.86", "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.86.tgz", @@ -8163,18 +8585,6 @@ "node": ">=16" } }, - "node_modules/trim-newlines": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-4.1.1.tgz", - "integrity": "sha512-jRKj0n0jXWo6kh62nA5TEh3+4igKDXLvzBJcPpiizP7oOolUrYIxmVBG9TOtHYFHoddUk6YvAkGeGoSVTXfQXQ==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/ts-api-utils": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", @@ -8192,6 +8602,7 @@ "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", "dev": true, + "license": "MIT", "dependencies": { "@cspotcode/source-map-support": "^0.8.0", "@tsconfig/node10": "^1.0.7", @@ -8271,18 +8682,6 @@ "node": ">=4" } }, - "node_modules/type-fest": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", - "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/type-is": { "version": "1.6.18", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", @@ -8313,9 +8712,9 @@ "license": "MIT" }, "node_modules/typescript": { - "version": "5.7.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz", - "integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==", + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, "license": "Apache-2.0", "bin": { @@ -8366,6 +8765,19 @@ "dev": true, "license": "MIT" }, + "node_modules/unicorn-magic": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.3.0.tgz", + "integrity": "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/universalify": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", @@ -8411,16 +8823,16 @@ } }, "node_modules/uuid": { - "version": "11.0.5", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.0.5.tgz", - "integrity": "sha512-508e6IcKLrhxKdBbcA2b4KQZlLVp2+J5UwQ6F7Drckkc5N9ZJwFa4TgWtsww9UG8fGHbm6gbV19TdM5pQ4GaIA==", + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-13.0.0.tgz", + "integrity": "sha512-XQegIaBTVUjSHliKqcnFqYypAd4S+WCYt5NIeRs6w/UAry7z8Y9j5ZwRRL4kzq9U3sD6v+85er9FvkEaBpji2w==", "funding": [ "https://github.com/sponsors/broofa", "https://github.com/sponsors/ctavan" ], "license": "MIT", "bin": { - "uuid": "dist/esm/bin/uuid" + "uuid": "dist-node/bin/uuid" } }, "node_modules/v8-compile-cache-lib": { @@ -8429,16 +8841,6 @@ "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", "dev": true }, - "node_modules/validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "dependencies": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, "node_modules/vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", @@ -8448,6 +8850,207 @@ "node": ">= 0.8" } }, + "node_modules/vite": { + "version": "7.2.4", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.2.4.tgz", + "integrity": "sha512-NL8jTlbo0Tn4dUEXEsUg8KeyG/Lkmc4Fnzb8JXN/Ykm9G4HNImjtABMJgkQoVjOBN/j2WAwDTRytdqJbZsah7w==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.25.0", + "fdir": "^6.5.0", + "picomatch": "^4.0.3", + "postcss": "^8.5.6", + "rollup": "^4.43.0", + "tinyglobby": "^0.2.15" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^20.19.0 || >=22.12.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "lightningcss": "^1.21.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/vite/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/vite/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/vitest": { + "version": "4.0.13", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.0.13.tgz", + "integrity": "sha512-QSD4I0fN6uZQfftryIXuqvqgBxTvJ3ZNkF6RWECd82YGAYAfhcppBLFXzXJHQAAhVFyYEuFTrq6h0hQqjB7jIQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/expect": "4.0.13", + "@vitest/mocker": "4.0.13", + "@vitest/pretty-format": "4.0.13", + "@vitest/runner": "4.0.13", + "@vitest/snapshot": "4.0.13", + "@vitest/spy": "4.0.13", + "@vitest/utils": "4.0.13", + "debug": "^4.4.3", + "es-module-lexer": "^1.7.0", + "expect-type": "^1.2.2", + "magic-string": "^0.30.21", + "pathe": "^2.0.3", + "picomatch": "^4.0.3", + "std-env": "^3.10.0", + "tinybench": "^2.9.0", + "tinyexec": "^0.3.2", + "tinyglobby": "^0.2.15", + "tinyrainbow": "^3.0.3", + "vite": "^6.0.0 || ^7.0.0", + "why-is-node-running": "^2.3.0" + }, + "bin": { + "vitest": "vitest.mjs" + }, + "engines": { + "node": "^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@opentelemetry/api": "^1.9.0", + "@types/debug": "^4.1.12", + "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", + "@vitest/browser-playwright": "4.0.13", + "@vitest/browser-preview": "4.0.13", + "@vitest/browser-webdriverio": "4.0.13", + "@vitest/ui": "4.0.13", + "happy-dom": "*", + "jsdom": "*" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@opentelemetry/api": { + "optional": true + }, + "@types/debug": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser-playwright": { + "optional": true + }, + "@vitest/browser-preview": { + "optional": true + }, + "@vitest/browser-webdriverio": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + } + } + }, + "node_modules/vitest/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -8516,6 +9119,23 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/why-is-node-running": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", + "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", + "dev": true, + "license": "MIT", + "dependencies": { + "siginfo": "^2.0.0", + "stackback": "0.0.2" + }, + "bin": { + "why-is-node-running": "cli.js" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/worker-timers": { "version": "7.1.8", "resolved": "https://registry.npmjs.org/worker-timers/-/worker-timers-7.1.8.tgz", @@ -8553,30 +9173,6 @@ "tslib": "^2.6.2" } }, - "node_modules/workerpool": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.5.1.tgz", - "integrity": "sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA==", - "dev": true, - "license": "Apache-2.0" - }, - "node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, "node_modules/wrap-ansi-cjs": { "name": "wrap-ansi", "version": "7.0.0", @@ -8632,39 +9228,6 @@ "dev": true, "license": "MIT" }, - "node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/wrap-ansi/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -8723,15 +9286,6 @@ "node": ">=0.4" } }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, "node_modules/yallist": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", @@ -8739,49 +9293,6 @@ "dev": true, "license": "ISC" }, - "node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs-unparser": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", - "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", - "dev": true, - "dependencies": { - "camelcase": "^6.0.0", - "decamelize": "^4.0.0", - "flat": "^5.0.2", - "is-plain-obj": "^2.1.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/yn": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", diff --git a/package.json b/package.json index e9beb891..231d9972 100644 --- a/package.json +++ b/package.json @@ -1,12 +1,13 @@ { "name": "node-red-contrib-homekit-bridged", - "version": "2.0.0-dev.0", + "version": "2.0.0-dev.1", "description": "Node-RED nodes to simulate Apple HomeKit devices.", "main": "build/nodes/nrchkb.js", "scripts": { "build": "npm run clean && tsc", "clean": "del-cli \"build/lib\" \"build/**/*.js\"", - "test": "mocha -r ts-node/register './src/**/*.test.[tj]s' --exit --timeout 30000", + "test": "vitest run", + "test:watch": "vitest", "prettier": "prettier --write \"**/*.{js,ts}\"", "eslint": "eslint \"src/**/*.ts\" --fix", "prepare": "husky install" @@ -42,16 +43,15 @@ }, "homepage": "https://github.com/NRCHKB/node-red-contrib-homekit-bridged#readme", "dependencies": { - "@nrchkb/logger": "~3.1.1", "@homebridge/hap-nodejs": "2.0.2", + "@nrchkb/logger": "~3.1.1", "node-persist": "^3.1.3", "semver": "~7.7.3", - "uuid": "~11.0.5" + "uuid": "~13.0.0" }, "devDependencies": { "@homebridge/ciao": "~1.3.4", "@node-red/registry": "^4.1.1", - "@types/mocha": "^10.0.10", "@types/node": "^20", "@types/node-persist": "^3.1.8", "@types/node-red": "^1.3.5", @@ -61,18 +61,27 @@ "@typescript-eslint/eslint-plugin": "^7.16.0", "@typescript-eslint/parser": "^7.16.0", "babel-eslint": "^10.1.0", - "del-cli": "^5.1.0", + "del-cli": "^7.0.0", "eslint": "^8", "eslint-config-prettier": "^9.1.0", "eslint-plugin-prettier": "^5.5.4", "eslint-plugin-simple-import-sort": "^12.1.1", "husky": "^9.1.7", - "mocha": "^10.6.0", "node-red": "^4.1.1", "node-red-node-test-helper": "^0.3.5", "prettier": "^3.6.2", "ts-node": "^10.9.2", - "typescript": "^5.7.3" + "typescript": "^5.9.3", + "vitest": "^4.0.13" + }, + "vitest": { + "test": { + "environment": "node", + "testTimeout": 30000, + "include": [ + "src/**/*.test.ts" + ] + } }, "engines": { "node": "^20 || ^22 || ^24" diff --git a/src/lib/api.ts b/src/lib/api.ts index ecda48cb..8cac507f 100644 --- a/src/lib/api.ts +++ b/src/lib/api.ts @@ -248,11 +248,9 @@ module.exports = function (RED: NodeAPI) { } class CustomCharacteristic extends Characteristic { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion static readonly UUID: string = UUID! constructor() { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion super(name!, CustomCharacteristic.UUID, { ...validatedProps, perms: validatedProps.perms ?? [ diff --git a/src/lib/types/hap-nodejs/HapCategories.ts b/src/lib/types/hap-nodejs/HapCategories.ts index 1e7e2e99..1f5b5f1d 100644 --- a/src/lib/types/hap-nodejs/HapCategories.ts +++ b/src/lib/types/hap-nodejs/HapCategories.ts @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/no-duplicate-enum-values */ // hap-nodejs declared this as const enum which makes it difficult to iterate key-value // Known category values. Category is a hint to iOS clients about what "type" of Accessory this represents, for UI only. enum HapCategories { @@ -13,6 +12,7 @@ enum HapCategories { THERMOSTAT = 9, SENSOR = 10, ALARM_SYSTEM = 11, + // eslint-disable-next-line @typescript-eslint/no-duplicate-enum-values SECURITY_SYSTEM = 11, //Added to conform to HAP naming DOOR = 12, WINDOW = 13, @@ -20,6 +20,7 @@ enum HapCategories { PROGRAMMABLE_SWITCH = 15, RANGE_EXTENDER = 16, CAMERA = 17, + // eslint-disable-next-line @typescript-eslint/no-duplicate-enum-values IP_CAMERA = 17, //Added to conform to HAP naming VIDEO_DOORBELL = 18, AIR_PURIFIER = 19, diff --git a/src/lib/utils/AccessoryUtils.ts b/src/lib/utils/AccessoryUtils.ts index 86989e1e..45cbbdbe 100644 --- a/src/lib/utils/AccessoryUtils.ts +++ b/src/lib/utils/AccessoryUtils.ts @@ -158,7 +158,6 @@ module.exports = function (node: HAPServiceNodeType) { } // Adding new accessory to the bridge. - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion host.addBridgedAccessories([accessory!]) } else { accessoryInformationService = diff --git a/src/lib/utils/ServiceUtils.ts b/src/lib/utils/ServiceUtils.ts index 158832fe..bf7833bd 100644 --- a/src/lib/utils/ServiceUtils.ts +++ b/src/lib/utils/ServiceUtils.ts @@ -159,7 +159,6 @@ module.exports = function (node: HAPServiceNodeType) { } } - // eslint-disable-next-line no-unused-vars const onCharacteristicSet = (allCharacteristics: Characteristic[]) => function ( this: Characteristic, diff --git a/src/lib/utils/ServiceUtils2.ts b/src/lib/utils/ServiceUtils2.ts index a6c5fc5e..23d53255 100644 --- a/src/lib/utils/ServiceUtils2.ts +++ b/src/lib/utils/ServiceUtils2.ts @@ -209,7 +209,6 @@ module.exports = function (node: HAPService2NodeType) { } } - // eslint-disable-next-line no-unused-vars const onCharacteristicSet = (allCharacteristics: Characteristic[]) => function ( this: Characteristic, diff --git a/src/test/lib/HAPBridgeNode.test.ts b/src/test/lib/HAPBridgeNode.test.ts index 371b8c4c..f51e4ab4 100644 --- a/src/test/lib/HAPBridgeNode.test.ts +++ b/src/test/lib/HAPBridgeNode.test.ts @@ -1,10 +1,7 @@ -import 'should' - import { loggerSetup } from '@nrchkb/logger' -import { describe, it } from 'mocha' -import should from 'should' +import { describe, expect, it } from 'vitest' -const HAPHostNode = require('../../lib/HAPHostNode')() +const HAPHostNode = require('../../../build/lib/HAPHostNode')() loggerSetup({ debugEnabled: true, @@ -13,35 +10,31 @@ loggerSetup({ }) describe('HAPHostNode', function () { - this.timeout(30000) + // allow longer for this suite (configured via package.json vitest.test.testTimeout) - it('string macify should pass', function (done) { + it('string macify should pass', function () { const stringToMacify = 'BRIDGE NAME' HAPHostNode.macify(stringToMacify) - done() }) - it('null string macify should fail', function (done) { + it('null string macify should fail', function () { const stringToMacify = null as unknown as string - should.throws(() => { + expect(() => { HAPHostNode.macify(stringToMacify) - }, 'nodeId cannot be empty in macify process') - done() + }).toThrow('nodeId cannot be empty in macify process') }) - it('undefined string macify should fail', function (done) { + it('undefined string macify should fail', function () { const stringToMacify = undefined as unknown as string - should.throws(() => { + expect(() => { HAPHostNode.macify(stringToMacify) - }, 'nodeId cannot be empty in macify process') - done() + }).toThrow('nodeId cannot be empty in macify process') }) - it('empty string macify should fail', function (done) { + it('empty string macify should fail', function () { const stringToMacify = '' - should.throws(() => { + expect(() => { HAPHostNode.macify(stringToMacify) - }, 'nodeId cannot be empty in macify process') - done() + }).toThrow('nodeId cannot be empty in macify process') }) }) diff --git a/src/test/lib/NodeStatusUtils.test.ts b/src/test/lib/NodeStatusUtils.test.ts index e34f0e4b..12a36f23 100644 --- a/src/test/lib/NodeStatusUtils.test.ts +++ b/src/test/lib/NodeStatusUtils.test.ts @@ -1,9 +1,13 @@ -import 'should' - import { NodeStatus } from '@node-red/registry' -import assert from 'assert' -import { after, before, beforeEach, describe, it } from 'mocha' -import sinon, { SinonFakeTimers } from 'sinon' +import { + afterAll, + beforeAll, + beforeEach, + describe, + expect, + it, + vi, +} from 'vitest' import { NodeStatusUtils } from '../../lib/utils/NodeStatusUtils' @@ -17,99 +21,67 @@ class NodeWithStatusMock { describe('NodeStatusUtils', function () { let node: NodeWithStatusMock let nodeStatusUtils: NodeStatusUtils - let clock: SinonFakeTimers - before(function () { - clock = sinon.useFakeTimers() + beforeAll(function () { + vi.useFakeTimers() }) - after(function () { - clock.restore() + afterAll(function () { + vi.useRealTimers() }) - beforeEach(function (done) { + beforeEach(function () { node = new NodeWithStatusMock() nodeStatusUtils = new NodeStatusUtils(node) - done() }) - it('setStatus', function (done) { - try { - nodeStatusUtils.setStatus('test') - assert.strictEqual(node.currentStatus, 'test') - done() - } catch (error: any) { - done(new Error(error)) - } + it('setStatus', function () { + nodeStatusUtils.setStatus('test') + expect(node.currentStatus).toBe('test') }) - it('clearStatus', function (done) { - try { - nodeStatusUtils.setStatus('test') - assert.strictEqual(node.currentStatus, 'test') - nodeStatusUtils.clearStatus() - assert.strictEqual(node.currentStatus, '') - done() - } catch (error: any) { - done(new Error(error)) - } + it('clearStatus', function () { + nodeStatusUtils.setStatus('test') + expect(node.currentStatus).toBe('test') + nodeStatusUtils.clearStatus() + expect(node.currentStatus).toBe('') }) - it('setStatusWithTimeout', function (done) { - try { - nodeStatusUtils.setStatus('test', 2000) - assert.strictEqual(node.currentStatus, 'test') - clock.tick(1000) - assert.strictEqual(node.currentStatus, 'test') - clock.tick(1000) - assert.strictEqual(node.currentStatus, '') - done() - } catch (error: any) { - done(new Error(error)) - } + it('setStatusWithTimeout', function () { + nodeStatusUtils.setStatus('test', 2000) + expect(node.currentStatus).toBe('test') + vi.advanceTimersByTime(1000) + expect(node.currentStatus).toBe('test') + vi.advanceTimersByTime(1000) + expect(node.currentStatus).toBe('') }) - it('setStatusWithTimeout - should not clear status with different id', function (done) { - try { - nodeStatusUtils.setStatus('test', 2000) - assert.strictEqual(node.currentStatus, 'test') - clock.tick(1000) - assert.strictEqual(node.currentStatus, 'test') - nodeStatusUtils.setStatus('test2', 2000) - clock.tick(1000) - assert.strictEqual(node.currentStatus, 'test2') - clock.tick(1000) - assert.strictEqual(node.currentStatus, '') - done() - } catch (error: any) { - done(new Error(error)) - } + it('setStatusWithTimeout - should not clear status with different id', function () { + nodeStatusUtils.setStatus('test', 2000) + expect(node.currentStatus).toBe('test') + vi.advanceTimersByTime(1000) + expect(node.currentStatus).toBe('test') + nodeStatusUtils.setStatus('test2', 2000) + vi.advanceTimersByTime(1000) + expect(node.currentStatus).toBe('test2') + vi.advanceTimersByTime(1000) + expect(node.currentStatus).toBe('') }) - it('clearStatusByType - should not clear other type', function (done) { - try { - nodeStatusUtils.setStatus({ text: 'test' }) - assert.deepStrictEqual(node.currentStatus, { text: 'test' }) - nodeStatusUtils.clearStatusByType('NO_RESPONSE') - assert.deepStrictEqual(node.currentStatus, { text: 'test' }) - done() - } catch (error: any) { - done(new Error(error)) - } + it('clearStatusByType - should not clear other type', function () { + nodeStatusUtils.setStatus({ text: 'test' }) + expect(node.currentStatus).toStrictEqual({ text: 'test' }) + nodeStatusUtils.clearStatusByType('NO_RESPONSE') + expect(node.currentStatus).toStrictEqual({ text: 'test' }) }) - it('clearStatusByType - should clear same type', function (done) { - try { - nodeStatusUtils.setStatus({ text: 'test', type: 'NO_RESPONSE' }) - assert.deepStrictEqual(node.currentStatus, { - text: 'test', - type: 'NO_RESPONSE', - }) - nodeStatusUtils.clearStatusByType('NO_RESPONSE') - assert.deepStrictEqual(node.currentStatus, '') - done() - } catch (error: any) { - done(new Error(error)) - } + it('clearStatusByType - should clear same type', function () { + nodeStatusUtils.setStatus({ text: 'test', type: 'NO_RESPONSE' }) + expect(node.currentStatus).toStrictEqual({ + text: 'test', + type: 'NO_RESPONSE', + }) + nodeStatusUtils.clearStatusByType('NO_RESPONSE') + expect(node.currentStatus).toStrictEqual('') }) }) diff --git a/src/test/lib/api.test.ts b/src/test/lib/api.test.ts index e5fe2f4a..69d00a2d 100644 --- a/src/test/lib/api.test.ts +++ b/src/test/lib/api.test.ts @@ -1,9 +1,6 @@ -import 'should' - import { loggerSetup } from '@nrchkb/logger' -import assert from 'assert' -import { afterEach, before, describe, it } from 'mocha' import helper from 'node-red-node-test-helper' +import { afterAll, afterEach, beforeAll, describe, expect, it } from 'vitest' import { version } from '../../../package.json' import { @@ -11,8 +8,8 @@ import { serviceTypesResponse, } from '../test-utils/data' -const API = require('../../lib/api')() -const nrchkb = require('../../nodes/nrchkb') +const API = require('../../../build/lib/api')() +const nrchkb = require('../../../build/nodes/nrchkb') process.env.NRCHKB_EXPERIMENTAL = 'true' @@ -23,103 +20,68 @@ loggerSetup({ }) describe('api', function () { - this.timeout(30000) - - before(function (done) { - helper.startServer(done) + beforeAll(function () { + return new Promise((resolve) => helper.startServer(resolve)) }) - after(function (done) { - helper.stopServer(done) + afterAll(function () { + return new Promise((resolve) => helper.stopServer(resolve)) }) afterEach(function () { helper.unload() }) - it('Service API', function (done) { - helper - .load([nrchkb], [], function () { - helper - .request() - .get('/nrchkb/service/types') - .expect('Content-Type', /json/) - .expect(200) - .then((response) => { - assert.deepStrictEqual( - response.body, - serviceTypesResponse - ) - done() - }) - .catch((err) => done(err)) - }) - .catch((error: any) => { - done(new Error(error)) - }) + it('Service API', async function () { + await helper.load([nrchkb], []) + const response = await helper + .request() + .get('/nrchkb/service/types') + .expect('Content-Type', /json/) + .expect(200) + expect(response.body).toStrictEqual(serviceTypesResponse) }) describe('stringifyVersion', function () { - it('release', function (done) { + it('release', function () { const input = '1.2.3' const expected = '1.2.3' const result = API.stringifyVersion(input) - assert.strictEqual(result, expected) - done() + expect(result).toBe(expected) }) - it('dev', function (done) { + it('dev', function () { const input = '1.2.3-dev.45' const expected = '0.123.45' const result = API.stringifyVersion(input) - assert.strictEqual(result, expected) - done() + expect(result).toBe(expected) }) }) - it('NRCHKB Info API', function (done) { - helper - .load([nrchkb], [], function () { - const xyzVersion = API.stringifyVersion(version) + it('NRCHKB Info API', async function () { + await helper.load([nrchkb], []) + const xyzVersion = API.stringifyVersion(version) + + const response = await helper + .request() + .get('/nrchkb/info') + .expect('Content-Type', /json/) + .expect(200) - helper - .request() - .get('/nrchkb/info') - .expect('Content-Type', /json/) - .expect(200) - .then((response) => { - assert.deepStrictEqual(response.body, { - experimental: true, - version: xyzVersion, - }) - done() - }) - .catch((err) => done(err)) - }) - .catch((error: any) => { - done(new Error(error)) - }) + expect(response.body).toStrictEqual({ + experimental: true, + version: xyzVersion, + }) }) - it('Accessory API', function (done) { - helper - .load([nrchkb], [], function () { - helper - .request() - .get('/nrchkb/accessory/categories') - .expect('Content-Type', /json/) - .expect(200) - .then((response) => { - assert.deepStrictEqual( - response.body, - accessoryCategoriesResponse - ) - done() - }) - .catch((err) => done(err)) - }) - .catch((error: any) => { - done(new Error(error)) - }) + it('Accessory API', async function () { + await helper.load([nrchkb], []) + const response = await helper + .request() + .get('/nrchkb/accessory/categories') + .expect('Content-Type', /json/) + .expect(200) + + expect(response.body).toStrictEqual(accessoryCategoriesResponse) }) }) diff --git a/src/test/nodes/service.test.ts b/src/test/nodes/service.test.ts index 7642bf39..d8c61349 100644 --- a/src/test/nodes/service.test.ts +++ b/src/test/nodes/service.test.ts @@ -1,13 +1,19 @@ -import 'should' - import { loggerSetup } from '@nrchkb/logger' -import { afterEach, before, describe, it } from 'mocha' import helper from 'node-red-node-test-helper' +import { + afterAll, + afterEach, + beforeAll, + describe, + expect, + it, + vi, +} from 'vitest' import { switchServiceBridgeFlow } from '../test-utils/data' -const homekitBridgeNode = require('../../nodes/bridge') -const nrchkb = require('../../nodes/nrchkb') -const homekitServiceNode = require('../../nodes/service') +const homekitBridgeNode = require('../../../build/nodes/bridge') +const nrchkb = require('../../../build/nodes/nrchkb') +const homekitServiceNode = require('../../../build/nodes/service') loggerSetup({ debugEnabled: true, @@ -16,157 +22,107 @@ loggerSetup({ }) describe('Service Node', function () { - before(function (done) { - helper.startServer(done) + beforeAll(function () { + return new Promise((resolve) => helper.startServer(resolve)) }) - after(function (done) { - helper.stopServer(done) + afterAll(function () { + return new Promise((resolve) => helper.stopServer(resolve)) }) afterEach(function () { helper.unload() }) - it('should be loaded', function (done) { + it('should be loaded', async function () { const { serviceId, flow } = switchServiceBridgeFlow() - helper - .load( - [nrchkb, homekitBridgeNode, homekitServiceNode], - flow, - function () { - try { - const s1 = helper.getNode(serviceId) - s1.should.have.property('type', 'homekit-service') - done() - } catch (err) { - done(err) - } - } - ) - .catch((error: any) => { - done(new Error(error)) - }) + await helper.load([nrchkb, homekitBridgeNode, homekitServiceNode], flow) + const s1 = helper.getNode(serviceId) + expect(s1).toHaveProperty('type', 'homekit-service') }) - it('should output ON:true payload', function (done) { + it('should output ON:true payload', async function () { const { serviceId, flow } = switchServiceBridgeFlow() - helper - .load( - [nrchkb, homekitBridgeNode, homekitServiceNode], - flow, - function () { - const s1 = helper.getNode(serviceId) - - s1.on('input', (msg: any) => { - try { - msg.payload.should.have.property('On', true) - done() - } catch (err) { - done(err) - } - }) + await helper.load([nrchkb, homekitBridgeNode, homekitServiceNode], flow) + const s1 = helper.getNode(serviceId) - s1.receive({ payload: { On: true } }) - } - ) - .catch((error: any) => { - done(new Error(error)) + await new Promise((resolve) => { + s1.on('input', (msg: any) => { + expect(msg.payload).toHaveProperty('On', true) + resolve() }) + + s1.receive({ payload: { On: true } }) + }) }) - it('should output ON:false payload', function (done) { + it('should output ON:false payload', async function () { const { serviceId, flow } = switchServiceBridgeFlow() - helper - .load( - [nrchkb, homekitBridgeNode, homekitServiceNode], - flow, - function () { - const s1 = helper.getNode(serviceId) - - s1.on('input', function (msg: any) { - try { - msg.payload.should.have.property('On', false) - done() - } catch (err) { - done(err) - } - }) + await helper.load([nrchkb, homekitBridgeNode, homekitServiceNode], flow) + const s1 = helper.getNode(serviceId) - s1.receive({ payload: { On: false } }) - } - ) - .catch((error: any) => { - done(new Error(error)) + await new Promise((resolve) => { + s1.on('input', function (msg: any) { + expect(msg.payload).toHaveProperty('On', false) + resolve() }) + + s1.receive({ payload: { On: false } }) + }) }) - it('should output reachable true', function (done) { + it('should output reachable true', async function () { const { serviceId, flow } = switchServiceBridgeFlow() - helper - .load( - [nrchkb, homekitBridgeNode, homekitServiceNode], - flow, - function () { - const s1 = helper.getNode(serviceId) - const h1 = helper.getNode('h1') - - let count = 0 - - h1.on('input', function (msg: any) { - if (count === 0) { - try { - msg.payload.should.have.property('On', true) - msg.hap.should.have.property('newValue', true) - msg.hap.should.have.property('reachable', true) - done() - } catch (err) { - done(err) - } - count++ - } - }) - - s1.receive({ payload: { On: true } }) + await helper.load([nrchkb, homekitBridgeNode, homekitServiceNode], flow) + const s1 = helper.getNode(serviceId) + const h1 = helper.getNode('h1') + + let count = 0 + + await new Promise((resolve) => { + h1.on('input', function (msg: any) { + if (count === 0) { + expect(msg.payload).toHaveProperty('On', true) + expect(msg.hap).toHaveProperty('newValue', true) + expect(msg.hap).toHaveProperty('reachable', true) + resolve() + count++ } - ) - .catch((error: any) => { - done(new Error(error)) }) + + s1.receive({ payload: { On: true } }) + }) }) - it('should output reachable false', function (done) { + it('should output reachable false', async function () { const { serviceId, flow } = switchServiceBridgeFlow() - helper - .load( - [nrchkb, homekitBridgeNode, homekitServiceNode], - flow, - function () { - const s1 = helper.getNode(serviceId) - const h1 = helper.getNode('h1') - - h1.on('input', function (msg: any) { - try { - msg.payload.should.have.property('On', false) - msg.hap.should.have.property('reachable', false) - // @ts-ignore - s1.status.should.be.calledWithExactly({ - fill: 'red', - shape: 'ring', - text: 'Not reachable', - type: 'NO_RESPONSE', - }) - done() - } catch (err) { - done(err) - } + await helper.load([nrchkb, homekitBridgeNode, homekitServiceNode], flow) + const s1 = helper.getNode(serviceId) + const h1 = helper.getNode('h1') + + await new Promise((resolve, reject) => { + // spy status so we can assert it was called + const statusSpy = vi + .spyOn(s1 as any, 'status') + .mockImplementation(() => {}) + + h1.on('input', function (msg: any) { + try { + expect(msg.payload).toHaveProperty('On', false) + expect(msg.hap).toHaveProperty('reachable', false) + expect(statusSpy).toHaveBeenCalledWith({ + fill: 'red', + shape: 'ring', + text: 'Not reachable', + type: 'NO_RESPONSE', }) - - s1.receive({ payload: { On: 'NO_RESPONSE' } }) + resolve() + } catch (err) { + reject(err) } - ) - .catch((error: any) => { - done(new Error(error)) }) + + s1.receive({ payload: { On: 'NO_RESPONSE' } }) + }) }) }) diff --git a/src/test/nodes/service2.test.ts b/src/test/nodes/service2.test.ts index 29156f1f..b5d4cf59 100644 --- a/src/test/nodes/service2.test.ts +++ b/src/test/nodes/service2.test.ts @@ -1,13 +1,19 @@ -import 'should' - import { loggerSetup } from '@nrchkb/logger' -import { afterEach, before, describe, it } from 'mocha' import helper from 'node-red-node-test-helper' +import { + afterAll, + afterEach, + beforeAll, + describe, + expect, + it, + vi, +} from 'vitest' import { switchService2BridgeFlow } from '../test-utils/data' -const homekitBridgeNode = require('../../nodes/bridge') -const nrchkb = require('../../nodes/nrchkb') -const homekitService2Node = require('../../nodes/service2') +const homekitBridgeNode = require('../../../build/nodes/bridge') +const nrchkb = require('../../../build/nodes/nrchkb') +const homekitService2Node = require('../../../build/nodes/service2') process.env.NRCHKB_EXPERIMENTAL = 'true' @@ -18,157 +24,121 @@ loggerSetup({ }) describe('Service Node', function () { - before(function (done) { - helper.startServer(done) + beforeAll(function () { + return new Promise((resolve) => helper.startServer(resolve)) }) - after(function (done) { - helper.stopServer(done) + afterAll(function () { + return new Promise((resolve) => helper.stopServer(resolve)) }) afterEach(function () { helper.unload() }) - it('should be loaded', function (done) { + it('should be loaded', async function () { const { serviceId, flow } = switchService2BridgeFlow() - helper - .load( - [nrchkb, homekitBridgeNode, homekitService2Node], - flow, - function () { - try { - const s1 = helper.getNode(serviceId) - s1.should.have.property('type', 'homekit-service2') - done() - } catch (err) { - done(err) - } - } - ) - .catch((error: any) => { - done(new Error(error)) - }) + await helper.load( + [nrchkb, homekitBridgeNode, homekitService2Node], + flow + ) + const s1 = helper.getNode(serviceId) + expect(s1).toHaveProperty('type', 'homekit-service2') }) - it('should output ON:true payload', function (done) { + it('should output ON:true payload', async function () { const { serviceId, flow } = switchService2BridgeFlow() - helper - .load( - [nrchkb, homekitBridgeNode, homekitService2Node], - flow, - function () { - const s1 = helper.getNode(serviceId) - - s1.on('input', (msg: any) => { - try { - msg.payload.should.have.property('On', true) - done() - } catch (err) { - done(err) - } - }) - - s1.receive({ payload: { On: true } }) - } - ) - .catch((error: any) => { - done(new Error(error)) + await helper.load( + [nrchkb, homekitBridgeNode, homekitService2Node], + flow + ) + const s1 = helper.getNode(serviceId) + + await new Promise((resolve) => { + s1.on('input', (msg: any) => { + expect(msg.payload).toHaveProperty('On', true) + resolve() }) + + s1.receive({ payload: { On: true } }) + }) }) - it('should output ON:false payload', function (done) { + it('should output ON:false payload', async function () { const { serviceId, flow } = switchService2BridgeFlow() - helper - .load( - [nrchkb, homekitBridgeNode, homekitService2Node], - flow, - function () { - const s1 = helper.getNode(serviceId) - - s1.on('input', function (msg: any) { - try { - msg.payload.should.have.property('On', false) - done() - } catch (err) { - done(err) - } - }) - - s1.receive({ payload: { On: false } }) - } - ) - .catch((error: any) => { - done(new Error(error)) + await helper.load( + [nrchkb, homekitBridgeNode, homekitService2Node], + flow + ) + const s1 = helper.getNode(serviceId) + + await new Promise((resolve) => { + s1.on('input', function (msg: any) { + expect(msg.payload).toHaveProperty('On', false) + resolve() }) + + s1.receive({ payload: { On: false } }) + }) }) - it('should output reachable true', function (done) { + it('should output reachable true', async function () { const { serviceId, flow } = switchService2BridgeFlow() - helper - .load( - [nrchkb, homekitBridgeNode, homekitService2Node], - flow, - function () { - const s1 = helper.getNode(serviceId) - const h1 = helper.getNode('h1') - - let count = 0 - - h1.on('input', function (msg: any) { - if (count === 0) { - try { - msg.payload.should.have.property('On', true) - msg.hap.should.have.property('newValue', true) - msg.hap.should.have.property('reachable', true) - done() - } catch (err) { - done(err) - } - count++ - } - }) - - s1.receive({ payload: { On: true } }) + await helper.load( + [nrchkb, homekitBridgeNode, homekitService2Node], + flow + ) + const s1 = helper.getNode(serviceId) + const h1 = helper.getNode('h1') + + let count = 0 + + await new Promise((resolve) => { + h1.on('input', function (msg: any) { + if (count === 0) { + expect(msg.payload).toHaveProperty('On', true) + expect(msg.hap).toHaveProperty('newValue', true) + expect(msg.hap).toHaveProperty('reachable', true) + resolve() + count++ } - ) - .catch((error: any) => { - done(new Error(error)) }) + + s1.receive({ payload: { On: true } }) + }) }) - it('should output reachable false', function (done) { + it('should output reachable false', async function () { const { serviceId, flow } = switchService2BridgeFlow() - helper - .load( - [nrchkb, homekitBridgeNode, homekitService2Node], - flow, - function () { - const s1 = helper.getNode(serviceId) - const h1 = helper.getNode('h1') - - h1.on('input', function (msg: any) { - try { - msg.payload.should.have.property('On', false) - msg.hap.should.have.property('reachable', false) - // @ts-ignore - s1.status.should.be.calledWithExactly({ - fill: 'red', - shape: 'ring', - text: 'Not reachable', - type: 'NO_RESPONSE', - }) - done() - } catch (err) { - done(err) - } + await helper.load( + [nrchkb, homekitBridgeNode, homekitService2Node], + flow + ) + const s1 = helper.getNode(serviceId) + const h1 = helper.getNode('h1') + + await new Promise((resolve, reject) => { + const statusSpy = vi + .spyOn(s1 as any, 'status') + .mockImplementation(() => {}) + + h1.on('input', function (msg: any) { + try { + expect(msg.payload).toHaveProperty('On', false) + expect(msg.hap).toHaveProperty('reachable', false) + expect(statusSpy).toHaveBeenCalledWith({ + fill: 'red', + shape: 'ring', + text: 'Not reachable', + type: 'NO_RESPONSE', }) - - s1.receive({ payload: { On: 'NO_RESPONSE' } }) + resolve() + } catch (err) { + reject(err) } - ) - .catch((error: any) => { - done(new Error(error)) }) + + s1.receive({ payload: { On: 'NO_RESPONSE' } }) + }) }) }) From f6329e459a0ec9fde0d9c3b23402c74e36abd9ea Mon Sep 17 00:00:00 2001 From: Shaquu Date: Sun, 23 Nov 2025 23:26:32 +0100 Subject: [PATCH 04/14] Migrated from eslint and prettier to biome.js --- .eslintrc.js | 41 - .gitattributes | 2 +- .github/workflows/tests.yml | 1 + .gitignore | 3 - .husky/pre-commit | 2 +- .prettierrc.js | 8 - CHANGELOG.md | 6 +- biome.json | 36 + .../demo/01 - ALL Demos single import.json | 382 +- examples/demo/02 - Air Purifier.json | 607 +- .../03 - Air Quality sensor with Battery.json | 536 +- examples/demo/04 - Dimmable Bulb.json | 361 +- examples/demo/05 - Color Bulb (HSV).json | 411 +- .../demo/06 - Fan (simple, 3 speeds).json | 505 +- ...speed, oscillate, rotation direction).json | 367 +- examples/demo/08 - CO2 detector.json | 479 +- .../09 - CO (carbon monoxide) example.json | 545 +- .../demo/10 - Door window contact sensor.json | 499 +- ... - Television with inputs and speaker.json | 1148 +- examples/switch/01 - Plain Switch.json | 34 +- package-lock.json | 16947 +++++++--------- package.json | 172 +- src/lib/HAPHostNode.ts | 333 +- src/lib/HAPServiceNode.ts | 498 +- src/lib/HAPServiceNode2.ts | 498 +- src/lib/Storage.ts | 246 +- src/lib/api.ts | 731 +- src/lib/hap/HAPCharacteristic.ts | 16 +- src/lib/hap/HAPService.ts | 2 +- src/lib/hap/eve-app/EveCharacteristics.ts | 129 +- src/lib/hap/eve-app/EveServices.ts | 20 +- src/lib/types/AccessoryInformationType.ts | 16 +- src/lib/types/CameraConfigType.ts | 42 +- src/lib/types/CustomCharacteristicType.ts | 4 +- src/lib/types/HAPHostConfigType.ts | 30 +- src/lib/types/HAPHostNodeType.ts | 14 +- src/lib/types/HAPService2ConfigType.ts | 6 +- src/lib/types/HAPService2NodeType.ts | 6 +- src/lib/types/HAPServiceConfigType.ts | 46 +- src/lib/types/HAPServiceNodeType.ts | 94 +- src/lib/types/HAPStatusConfigType.ts | 2 +- src/lib/types/HAPStatusNodeType.ts | 8 +- src/lib/types/HostType.ts | 4 +- src/lib/types/PublishTimersType.ts | 2 +- .../HapAdaptiveLightingControllerMode.ts | 18 +- src/lib/types/hap-nodejs/HapCategories.ts | 78 +- src/lib/types/storage/SerializedHostType.ts | 2 +- src/lib/types/storage/StorageType.ts | 10 +- src/lib/utils/AccessoryUtils.ts | 387 +- src/lib/utils/BridgeUtils.ts | 82 +- src/lib/utils/CharacteristicUtils.ts | 171 +- src/lib/utils/CharacteristicUtils2.ts | 175 +- src/lib/utils/NodeStatusUtils.ts | 104 +- src/lib/utils/ServiceUtils.ts | 981 +- src/lib/utils/ServiceUtils2.ts | 940 +- src/lib/utils/index.ts | 20 +- src/nodes/bridge.ts | 6 +- src/nodes/nrchkb.ts | 100 +- src/nodes/service.ts | 6 +- src/nodes/service2.ts | 10 +- src/nodes/standalone.ts | 6 +- src/nodes/status.ts | 88 +- src/test/lib/HAPBridgeNode.test.ts | 52 +- src/test/lib/NodeStatusUtils.test.ts | 132 +- src/test/lib/api.test.ts | 114 +- src/test/nodes/service.test.ts | 212 +- src/test/nodes/service2.test.ts | 225 +- .../data/api.accessory.categories.response.ts | 72 +- .../data/api.service.types.response.ts | 12291 ++++++----- .../data/switch.service.bridge.flow.ts | 162 +- .../data/switch.service2.bridge.flow.ts | 164 +- tsconfig.json | 14 +- 72 files changed, 20014 insertions(+), 22447 deletions(-) delete mode 100644 .eslintrc.js delete mode 100644 .prettierrc.js create mode 100644 biome.json diff --git a/.eslintrc.js b/.eslintrc.js deleted file mode 100644 index 97db310c..00000000 --- a/.eslintrc.js +++ /dev/null @@ -1,41 +0,0 @@ -module.exports = { - parser: '@typescript-eslint/parser', - env: { - browser: true, - commonjs: true, - es6: true, - node: true, - }, - extends: [ - 'plugin:@typescript-eslint/recommended', - 'plugin:prettier/recommended', - 'prettier', - ], - plugins: ['@typescript-eslint', 'prettier', 'simple-import-sort'], - globals: { - Atomics: 'readonly', - SharedArrayBuffer: 'readonly', - }, - parserOptions: { - ecmaVersion: 2020, - sourceType: 'module', - allowImportExportEverywhere: true, - }, - rules: { - 'prettier/prettier': 'off', - 'linebreak-style': ['error', 'unix'], - quotes: ['error', 'single', { avoidEscape: true }], - semi: ['error', 'never'], - 'no-prototype-builtins': 'off', - '@typescript-eslint/no-this-alias': 'off', - '@typescript-eslint/no-var-requires': 'off', - '@typescript-eslint/no-explicit-any': 'off', - '@typescript-eslint/ban-ts-comment': 'off', - 'simple-import-sort/imports': 'error', - 'simple-import-sort/exports': 'error', - '@typescript-eslint/no-unused-vars': [ - 'error', - { argsIgnorePattern: '^_', destructuredArrayIgnorePattern: '^_' }, - ], - }, -} diff --git a/.gitattributes b/.gitattributes index 21256661..94f480de 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1 +1 @@ -* text=auto \ No newline at end of file +* text=auto eol=lf \ No newline at end of file diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index b0b3d55b..adfca9ec 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -17,6 +17,7 @@ jobs: - name: build and test run: | npm ci + biome ci npm run build npm run test env: diff --git a/.gitignore b/.gitignore index b24ae2ac..d64e1dc1 100644 --- a/.gitignore +++ b/.gitignore @@ -175,9 +175,6 @@ typings/ # Optional npm cache directory .npm -# Optional eslint cache -.eslintcache - # Optional REPL history .node_repl_history diff --git a/.husky/pre-commit b/.husky/pre-commit index 36404cc6..f6a428cb 100644 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -6,4 +6,4 @@ . "$(dirname -- "$0")/_/husky.sh" -npm run prettier && npm test && npm run eslint +npm run format && npm test diff --git a/.prettierrc.js b/.prettierrc.js deleted file mode 100644 index a3a46860..00000000 --- a/.prettierrc.js +++ /dev/null @@ -1,8 +0,0 @@ -module.exports = { - tabWidth: 4, - useTabs: false, - semi: false, - singleQuote: true, - trailingComma: 'es5', - endOfLine: 'lf', -} diff --git a/CHANGELOG.md b/CHANGELOG.md index c1bd8284..53f19930 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ #### ⚠️ CAUTION ⚠️ -##### Before upgrading make sure that you are using the latest version of [Node-RED](https://nodered.org/docs/getting-started/local) and latest LTS version of [Node.js](https://nodejs.org/en/download/) +##### Before upgrading make sure that you are using the latest version of [Node-RED](https://nodered.org/docs/getting-started/local) and the latest LTS version of [Node.js](https://nodejs.org/en/download/) # Changelog @@ -11,6 +11,8 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [2.0.0] - 2025-11-22 +Lost backward compatibility for Camera Service and MDNS Custom Configuration. + ### Changed - Updated hap-nodejs [0.12.3 to 2.0.2](https://github.com/homebridge/HAP-NodeJS/blob/latest/CHANGELOG.md) (features @@ -18,7 +20,7 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - Dependencies upgrade - Node `18` no longer supported, use Node 24 [#578](https://github.com/NRCHKB/node-red-contrib-homekit-bridged/issues/578)! Or at least 20. -- Due to major upgrade of hap-nodejs, some breaking changes might be present including Camera Service and MDNS Custom +- Due to a major upgrade of hap-nodejs, some breaking changes might be present, including Camera Service and MDNS Custom Configuration. ## [1.7.3] - 2025-01-16 diff --git a/biome.json b/biome.json new file mode 100644 index 00000000..cb2bf71f --- /dev/null +++ b/biome.json @@ -0,0 +1,36 @@ +{ + "$schema": "https://biomejs.dev/schemas/2.3.7/schema.json", + "vcs": { + "enabled": true, + "clientKind": "git", + "useIgnoreFile": true + }, + "files": { + "ignoreUnknown": false + }, + "formatter": { + "enabled": true, + "indentStyle": "space" + }, + "linter": { + "enabled": true, + "rules": { + "recommended": true + } + }, + "javascript": { + "formatter": { + "quoteStyle": "single", + "semicolons": "asNeeded", + "trailingCommas": "none" + } + }, + "assist": { + "enabled": true, + "actions": { + "source": { + "organizeImports": "on" + } + } + } +} diff --git a/examples/demo/01 - ALL Demos single import.json b/examples/demo/01 - ALL Demos single import.json index 8076caf8..21bad810 100644 --- a/examples/demo/01 - ALL Demos single import.json +++ b/examples/demo/01 - ALL Demos single import.json @@ -83,12 +83,7 @@ "outputs": 2, "x": 500, "y": 1600, - "wires": [ - [ - "b7778e52.220a5" - ], - [] - ] + "wires": [["b7778e52.220a5"], []] }, { "id": "c717b796.0735b8", @@ -105,11 +100,7 @@ "payloadType": "json", "x": 220, "y": 1700, - "wires": [ - [ - "fd8aff55.91d41" - ] - ] + "wires": [["fd8aff55.91d41"]] }, { "id": "f56a2f96.509c1", @@ -135,11 +126,7 @@ "payloadType": "json", "x": 200, "y": 1600, - "wires": [ - [ - "fd8aff55.91d41" - ] - ] + "wires": [["fd8aff55.91d41"]] }, { "id": "d945ba75.897998", @@ -165,11 +152,7 @@ "payloadType": "json", "x": 200, "y": 1640, - "wires": [ - [ - "fd8aff55.91d41" - ] - ] + "wires": [["fd8aff55.91d41"]] }, { "id": "409001a1.3e7a78", @@ -279,12 +262,7 @@ "outputs": 2, "x": 490, "y": 720, - "wires": [ - [ - "d838176b.dbaf7" - ], - [] - ] + "wires": [["d838176b.dbaf7"], []] }, { "id": "ee1452a5.08edd", @@ -306,11 +284,7 @@ "payloadType": "json", "x": 420, "y": 640, - "wires": [ - [ - "7bf880d4.3cd4d" - ] - ] + "wires": [["7bf880d4.3cd4d"]] }, { "id": "c6ed2a2a.90a01", @@ -332,11 +306,7 @@ "payloadType": "json", "x": 190, "y": 640, - "wires": [ - [ - "7bf880d4.3cd4d" - ] - ] + "wires": [["7bf880d4.3cd4d"]] }, { "id": "8cdfae2b.2f2ce8", @@ -358,11 +328,7 @@ "payloadType": "json", "x": 200, "y": 720, - "wires": [ - [ - "7bf880d4.3cd4d" - ] - ] + "wires": [["7bf880d4.3cd4d"]] }, { "id": "1758401b.6c62e8", @@ -384,11 +350,7 @@ "payloadType": "json", "x": 190, "y": 680, - "wires": [ - [ - "7bf880d4.3cd4d" - ] - ] + "wires": [["7bf880d4.3cd4d"]] }, { "id": "3a57bebe.a3b222", @@ -461,12 +423,7 @@ "outputs": 2, "x": 460, "y": 540, - "wires": [ - [ - "379657db.a99df8" - ], - [] - ] + "wires": [["379657db.a99df8"], []] }, { "id": "379657db.a99df8", @@ -504,11 +461,7 @@ "payloadType": "json", "x": 400, "y": 500, - "wires": [ - [ - "459254fe.49c72c" - ] - ] + "wires": [["459254fe.49c72c"]] }, { "id": "253b3550.729caa", @@ -530,11 +483,7 @@ "payloadType": "json", "x": 190, "y": 500, - "wires": [ - [ - "459254fe.49c72c" - ] - ] + "wires": [["459254fe.49c72c"]] }, { "id": "b9bc7f3d.51acf", @@ -556,11 +505,7 @@ "payloadType": "json", "x": 190, "y": 540, - "wires": [ - [ - "459254fe.49c72c" - ] - ] + "wires": [["459254fe.49c72c"]] }, { "id": "60e44fde.c914f8", @@ -613,11 +558,7 @@ "payloadType": "json", "x": 190, "y": 100, - "wires": [ - [ - "5302e4aa.1b466c" - ] - ] + "wires": [["5302e4aa.1b466c"]] }, { "id": "5302e4aa.1b466c", @@ -662,13 +603,7 @@ "outputs": 2, "x": 370, "y": 100, - "wires": [ - [ - "bfe1c73d.c165a8", - "9739d842.a402f" - ], - [] - ] + "wires": [["bfe1c73d.c165a8", "9739d842.a402f"], []] }, { "id": "bfe1c73d.c165a8", @@ -699,19 +634,8 @@ "finalize": "", "x": 530, "y": 100, - "wires": [ - [ - "664dadf9.85d0d4", - "d7cd8a56.628178" - ], - [ - "3de34c4c.1871a4" - ] - ], - "outputLabels": [ - "On", - "Off" - ] + "wires": [["664dadf9.85d0d4", "d7cd8a56.628178"], ["3de34c4c.1871a4"]], + "outputLabels": ["On", "Off"] }, { "id": "87048a6e.df64e8", @@ -733,11 +657,7 @@ "payloadType": "json", "x": 190, "y": 140, - "wires": [ - [ - "5302e4aa.1b466c" - ] - ] + "wires": [["5302e4aa.1b466c"]] }, { "id": "db412cea.4a62f8", @@ -759,11 +679,7 @@ "payloadType": "json", "x": 190, "y": 180, - "wires": [ - [ - "5302e4aa.1b466c" - ] - ] + "wires": [["5302e4aa.1b466c"]] }, { "id": "46418e19.aa6d6", @@ -771,16 +687,10 @@ "z": "eeb8b00c.2c18c", "g": "60e44fde.c914f8", "name": "", - "links": [ - "ee8894e4.f1855" - ], + "links": ["ee8894e4.f1855"], "x": 315, "y": 180, - "wires": [ - [ - "5302e4aa.1b466c" - ] - ] + "wires": [["5302e4aa.1b466c"]] }, { "id": "664dadf9.85d0d4", @@ -801,11 +711,7 @@ "outputs": 1, "x": 730, "y": 100, - "wires": [ - [ - "ee8894e4.f1855" - ] - ] + "wires": [["ee8894e4.f1855"]] }, { "id": "d7cd8a56.628178", @@ -826,11 +732,7 @@ "outputs": 1, "x": 730, "y": 140, - "wires": [ - [ - "ee8894e4.f1855" - ] - ] + "wires": [["ee8894e4.f1855"]] }, { "id": "3de34c4c.1871a4", @@ -851,11 +753,7 @@ "outputs": 1, "x": 730, "y": 180, - "wires": [ - [ - "ee8894e4.f1855" - ] - ] + "wires": [["ee8894e4.f1855"]] }, { "id": "ee8894e4.f1855", @@ -863,9 +761,7 @@ "z": "eeb8b00c.2c18c", "g": "60e44fde.c914f8", "name": "", - "links": [ - "46418e19.aa6d6" - ], + "links": ["46418e19.aa6d6"], "x": 875, "y": 140, "wires": [] @@ -945,10 +841,7 @@ "outputs": 2, "x": 750, "y": 1040, - "wires": [ - [], - [] - ] + "wires": [[], []] }, { "id": "79889759.8219c", @@ -963,11 +856,7 @@ "finalize": "", "x": 460, "y": 1200, - "wires": [ - [ - "2e6738a6.ef5dd8" - ] - ] + "wires": [["2e6738a6.ef5dd8"]] }, { "id": "7f53465b.356a68", @@ -982,11 +871,7 @@ "finalize": "", "x": 470, "y": 1080, - "wires": [ - [ - "2e6738a6.ef5dd8" - ] - ] + "wires": [["2e6738a6.ef5dd8"]] }, { "id": "97aff586.786ff8", @@ -1012,11 +897,7 @@ "payloadType": "json", "x": 480, "y": 1040, - "wires": [ - [ - "2e6738a6.ef5dd8" - ] - ] + "wires": [["2e6738a6.ef5dd8"]] }, { "id": "659ff3da.236404", @@ -1038,11 +919,7 @@ "payloadType": "num", "x": 220, "y": 1200, - "wires": [ - [ - "79889759.8219c" - ] - ] + "wires": [["79889759.8219c"]] }, { "id": "e6105066.f8911", @@ -1059,11 +936,7 @@ "payloadType": "num", "x": 210, "y": 1040, - "wires": [ - [ - "7f53465b.356a68" - ] - ] + "wires": [["7f53465b.356a68"]] }, { "id": "b433a780.665a7", @@ -1085,11 +958,7 @@ "payloadType": "str", "x": 200, "y": 1240, - "wires": [ - [ - "79889759.8219c" - ] - ] + "wires": [["79889759.8219c"]] }, { "id": "d4b30334.a19e58", @@ -1111,11 +980,7 @@ "payloadType": "str", "x": 220, "y": 1080, - "wires": [ - [ - "7f53465b.356a68" - ] - ] + "wires": [["7f53465b.356a68"]] }, { "id": "b0eeeb34.2dde8", @@ -1137,11 +1002,7 @@ "payloadType": "str", "x": 230, "y": 1120, - "wires": [ - [ - "7f53465b.356a68" - ] - ] + "wires": [["7f53465b.356a68"]] }, { "id": "a875cc7.a4c42b", @@ -1217,10 +1078,7 @@ "outputs": 2, "x": 740, "y": 1340, - "wires": [ - [], - [] - ] + "wires": [[], []] }, { "id": "2f9bc0d.42a73c", @@ -1237,11 +1095,7 @@ "payloadType": "json", "x": 200, "y": 1460, - "wires": [ - [ - "a5194c26.18c628" - ] - ] + "wires": [["a5194c26.18c628"]] }, { "id": "dfca0b2d.8b8e8", @@ -1258,11 +1112,7 @@ "payloadType": "json", "x": 220, "y": 1500, - "wires": [ - [ - "a5194c26.18c628" - ] - ] + "wires": [["a5194c26.18c628"]] }, { "id": "d74a610c.09a36", @@ -1279,11 +1129,7 @@ "payloadType": "json", "x": 560, "y": 1460, - "wires": [ - [ - "a5194c26.18c628" - ] - ] + "wires": [["a5194c26.18c628"]] }, { "id": "c15b6468.ae2eb8", @@ -1300,11 +1146,7 @@ "payloadType": "json", "x": 560, "y": 1500, - "wires": [ - [ - "a5194c26.18c628" - ] - ] + "wires": [["a5194c26.18c628"]] }, { "id": "6f7bc7fa.7f4f6", @@ -1330,11 +1172,7 @@ "payloadType": "json", "x": 220, "y": 1400, - "wires": [ - [ - "a5194c26.18c628" - ] - ] + "wires": [["a5194c26.18c628"]] }, { "id": "99b55eb3.e31bf8", @@ -1355,11 +1193,7 @@ "outputs": 1, "x": 430, "y": 1340, - "wires": [ - [ - "a5194c26.18c628" - ] - ] + "wires": [["a5194c26.18c628"]] }, { "id": "508d9ccf.29e404", @@ -1385,11 +1219,7 @@ "payloadType": "json", "x": 190, "y": 1340, - "wires": [ - [ - "99b55eb3.e31bf8" - ] - ] + "wires": [["99b55eb3.e31bf8"]] }, { "id": "ab48426e.25466", @@ -1465,10 +1295,7 @@ "outputs": 2, "x": 750, "y": 820, - "wires": [ - [], - [] - ] + "wires": [[], []] }, { "id": "3611c654.8a42f2", @@ -1483,11 +1310,7 @@ "finalize": "", "x": 480, "y": 820, - "wires": [ - [ - "88892b4.8a61bd8" - ] - ] + "wires": [["88892b4.8a61bd8"]] }, { "id": "62cafcb0.8ade9c", @@ -1504,11 +1327,7 @@ "payloadType": "json", "x": 550, "y": 860, - "wires": [ - [ - "88892b4.8a61bd8" - ] - ] + "wires": [["88892b4.8a61bd8"]] }, { "id": "a0171cdb.f209b", @@ -1525,11 +1344,7 @@ "payloadType": "json", "x": 550, "y": 900, - "wires": [ - [ - "88892b4.8a61bd8" - ] - ] + "wires": [["88892b4.8a61bd8"]] }, { "id": "6f7de764.a6a688", @@ -1546,11 +1361,7 @@ "payloadType": "json", "x": 520, "y": 940, - "wires": [ - [ - "88892b4.8a61bd8" - ] - ] + "wires": [["88892b4.8a61bd8"]] }, { "id": "8758b463.afb0f", @@ -1572,11 +1383,7 @@ "payloadType": "num", "x": 190, "y": 820, - "wires": [ - [ - "3611c654.8a42f2" - ] - ] + "wires": [["3611c654.8a42f2"]] }, { "id": "69e8161b.74b7a", @@ -1598,11 +1405,7 @@ "payloadType": "str", "x": 200, "y": 860, - "wires": [ - [ - "3611c654.8a42f2" - ] - ] + "wires": [["3611c654.8a42f2"]] }, { "id": "40010b09.c73cdc", @@ -1624,11 +1427,7 @@ "payloadType": "str", "x": 220, "y": 900, - "wires": [ - [ - "3611c654.8a42f2" - ] - ] + "wires": [["3611c654.8a42f2"]] }, { "id": "b3b5156e.cdf988", @@ -1703,10 +1502,7 @@ "outputs": 2, "x": 750, "y": 280, - "wires": [ - [], - [] - ] + "wires": [[], []] }, { "id": "a70b3192.dfb4f", @@ -1728,11 +1524,7 @@ "payloadType": "json", "x": 230, "y": 280, - "wires": [ - [ - "560fc866.6de558" - ] - ] + "wires": [["560fc866.6de558"]] }, { "id": "d5708f5.036c87", @@ -1754,11 +1546,7 @@ "payloadType": "date", "x": 220, "y": 380, - "wires": [ - [ - "90b692e4.b9f6c" - ] - ] + "wires": [["90b692e4.b9f6c"]] }, { "id": "90b692e4.b9f6c", @@ -1773,11 +1561,7 @@ "finalize": "", "x": 470, "y": 380, - "wires": [ - [ - "5cd5342a.cfd72c" - ] - ] + "wires": [["5cd5342a.cfd72c"]] }, { "id": "54bfafbc.396898", @@ -1799,11 +1583,7 @@ "payloadType": "json", "x": 500, "y": 320, - "wires": [ - [ - "8088a797.e1a7c" - ] - ] + "wires": [["8088a797.e1a7c"]] }, { "id": "560fc866.6de558", @@ -1818,11 +1598,7 @@ "finalize": "", "x": 500, "y": 280, - "wires": [ - [ - "8088a797.e1a7c" - ] - ] + "wires": [["8088a797.e1a7c"]] }, { "id": "61e113b2.dbb714", @@ -1835,9 +1611,7 @@ "fill": "#bfdbef", "label": true }, - "nodes": [ - "5cd5342a.cfd72c" - ], + "nodes": ["5cd5342a.cfd72c"], "x": 654, "y": 339, "w": 172, @@ -1888,10 +1662,7 @@ "outputs": 2, "x": 740, "y": 380, - "wires": [ - [], - [] - ] + "wires": [[], []] }, { "id": "c869b0a5.e4def8", @@ -1981,12 +1752,7 @@ "outputs": 2, "x": 510, "y": 1800, - "wires": [ - [ - "dadd634c.ae2258" - ], - [] - ] + "wires": [["dadd634c.ae2258"], []] }, { "id": "992f4930.012aa", @@ -2012,11 +1778,7 @@ "payloadType": "json", "x": 460, "y": 1880, - "wires": [ - [ - "753e3777.49a1d" - ] - ] + "wires": [["753e3777.49a1d"]] }, { "id": "2497a466.aa0e84", @@ -2042,11 +1804,7 @@ "payloadType": "json", "x": 190, "y": 1800, - "wires": [ - [ - "753e3777.49a1d" - ] - ] + "wires": [["753e3777.49a1d"]] }, { "id": "c53b76fb.7a3cc8", @@ -2072,11 +1830,7 @@ "payloadType": "json", "x": 190, "y": 1840, - "wires": [ - [ - "753e3777.49a1d" - ] - ] + "wires": [["753e3777.49a1d"]] }, { "id": "6c9646ee.1f3a18", @@ -2102,11 +1856,7 @@ "payloadType": "json", "x": 200, "y": 1880, - "wires": [ - [ - "753e3777.49a1d" - ] - ] + "wires": [["753e3777.49a1d"]] }, { "id": "1e42a8f3.cf008f", @@ -2132,10 +1882,6 @@ "payloadType": "json", "x": 190, "y": 1920, - "wires": [ - [ - "753e3777.49a1d" - ] - ] + "wires": [["753e3777.49a1d"]] } ] diff --git a/examples/demo/02 - Air Purifier.json b/examples/demo/02 - Air Purifier.json index b1e44f20..647e7eaa 100644 --- a/examples/demo/02 - Air Purifier.json +++ b/examples/demo/02 - Air Purifier.json @@ -1,331 +1,282 @@ [ - { - "id": "60e44fde.c914f8", - "type": "group", - "z": "60b06629.a2ebd", - "name": "Air Purifier: input power state, output commands device", - "style": { - "stroke": "#999999", - "fill": "none", - "label": true, - "label-position": "nw", - "color": "#a4a4a4" - }, - "nodes": [ - "8dea49.4a770db8", - "5302e4aa.1b466c", - "bfe1c73d.c165a8", - "9739d842.a402f", - "87048a6e.df64e8", - "db412cea.4a62f8", - "46418e19.aa6d6", - "664dadf9.85d0d4", - "d7cd8a56.628178", - "3de34c4c.1871a4", - "ee8894e4.f1855" - ], - "x": 14, - "y": 119, - "w": 822, - "h": 162, - "info": "Turning the device on or off will send:\n`{\"Active\":[0, 1]}`\n\nAfter changing power state, the device will be \"Turning on\" or \"Turning off\" until a current state is sent of:\n`{\"CurrentAirPurifierState\":[0, 1, 2]}`\n0: off
\n1: idle
\n2: on
\n\nThere will be a slider in the home app for sending `RotationSpeed`\n\nThere will be a switch on Home app for \"Oscillate\" which sends:\n`{\"SwingMode\":[0,1]}`\n\nChanging mode to manual to auto will send payload:\n`{\"TargetAirPurifierState\":[0, 1]}`\n\nChild lock will send \n`{\"LockPhysicalControls\": [0, 1]}`\n\n" + { + "id": "60e44fde.c914f8", + "type": "group", + "z": "60b06629.a2ebd", + "name": "Air Purifier: input power state, output commands device", + "style": { + "stroke": "#999999", + "fill": "none", + "label": true, + "label-position": "nw", + "color": "#a4a4a4" }, - { - "id": "8dea49.4a770db8", - "type": "inject", - "z": "60b06629.a2ebd", - "g": "60e44fde.c914f8", - "name": "off", - "props": [ - { - "p": "payload" - } - ], - "repeat": "", - "crontab": "", - "once": false, - "onceDelay": 0.1, - "topic": "", - "payload": "{\"CurrentAirPurifierState\":0}", - "payloadType": "json", - "x": 110, - "y": 160, - "wires": [ - [ - "5302e4aa.1b466c" - ] - ] - }, - { - "id": "5302e4aa.1b466c", - "type": "homekit-service", - "z": "60b06629.a2ebd", - "g": "60e44fde.c914f8", - "isParent": true, - "bridge": "409001a1.3e7a78", - "parentService": "", - "name": "Air purifier", - "serviceName": "AirPurifier", - "topic": "", - "filter": false, - "manufacturer": "Purity", - "model": "Air", - "serialNo": "23", - "firmwareRev": "1.0.0", - "hardwareRev": "1.0.0", - "softwareRev": "1.0.0", - "cameraConfigVideoProcessor": "ffmpeg", - "cameraConfigSource": "", - "cameraConfigStillImageSource": "", - "cameraConfigMaxStreams": 2, - "cameraConfigMaxWidth": 1280, - "cameraConfigMaxHeight": 720, - "cameraConfigMaxFPS": 10, - "cameraConfigMaxBitrate": 300, - "cameraConfigVideoCodec": "libx264", - "cameraConfigAudioCodec": "libfdk_aac", - "cameraConfigAudio": false, - "cameraConfigPacketSize": 1316, - "cameraConfigVerticalFlip": false, - "cameraConfigHorizontalFlip": false, - "cameraConfigMapVideo": "0:0", - "cameraConfigMapAudio": "0:1", - "cameraConfigVideoFilter": "scale=1280:720", - "cameraConfigAdditionalCommandLine": "-tune zerolatency", - "cameraConfigDebug": false, - "cameraConfigSnapshotOutput": "disabled", - "cameraConfigInterfaceName": "", - "characteristicProperties": "{\n \"SwingMode\":true,\n \"RotationSpeed\":true,\n \"LockPhysicalControls\":true\n}", - "outputs": 2, - "x": 290, - "y": 160, - "wires": [ - [ - "bfe1c73d.c165a8", - "9739d842.a402f" - ], - [] - ] - }, - { - "id": "bfe1c73d.c165a8", - "type": "debug", - "z": "60b06629.a2ebd", - "g": "60e44fde.c914f8", - "name": "Purifier output", - "active": true, - "tosidebar": true, - "console": false, - "tostatus": false, - "complete": "true", - "targetType": "full", - "x": 420, - "y": 240, - "wires": [] - }, - { - "id": "9739d842.a402f", - "type": "function", - "z": "60b06629.a2ebd", - "g": "60e44fde.c914f8", - "name": "on/off", - "func": "if (msg.hap !== undefined && msg.hap.context !== undefined){\n if (msg.payload.Active === 1){\n return [msg,null];\n }\n if (msg.payload.Active === 0){\n return [null,msg];\n }\n}\nreturn;", - "outputs": 2, - "noerr": 0, - "initialize": "", - "finalize": "", - "x": 450, - "y": 160, - "wires": [ - [ - "664dadf9.85d0d4", - "d7cd8a56.628178" - ], - [ - "3de34c4c.1871a4" - ] - ], - "outputLabels": [ - "On", - "Off" - ] - }, - { - "id": "87048a6e.df64e8", - "type": "inject", - "z": "60b06629.a2ebd", - "g": "60e44fde.c914f8", - "name": "idle", - "props": [ - { - "p": "payload" - } - ], - "repeat": "", - "crontab": "", - "once": false, - "onceDelay": 0.1, - "topic": "", - "payload": "{\"CurrentAirPurifierState\":1}", - "payloadType": "json", - "x": 110, - "y": 200, - "wires": [ - [ - "5302e4aa.1b466c" - ] - ] - }, - { - "id": "db412cea.4a62f8", - "type": "inject", - "z": "60b06629.a2ebd", - "g": "60e44fde.c914f8", - "name": "on", - "props": [ - { - "p": "payload" - } - ], - "repeat": "", - "crontab": "", - "once": false, - "onceDelay": 0.1, - "topic": "", - "payload": "{\"CurrentAirPurifierState\":2}", - "payloadType": "json", - "x": 110, - "y": 240, - "wires": [ - [ - "5302e4aa.1b466c" - ] - ] - }, - { - "id": "46418e19.aa6d6", - "type": "link in", - "z": "60b06629.a2ebd", - "g": "60e44fde.c914f8", - "name": "", - "links": [ - "ee8894e4.f1855" - ], - "x": 235, - "y": 240, - "wires": [ - [ - "5302e4aa.1b466c" - ] - ] - }, - { - "id": "664dadf9.85d0d4", - "type": "trigger", - "z": "60b06629.a2ebd", - "g": "60e44fde.c914f8", - "name": "5 sec to idle", - "op1": "", - "op2": "{\"CurrentAirPurifierState\":1}", - "op1type": "nul", - "op2type": "json", - "duration": "5", - "extend": false, - "units": "s", - "reset": "", - "bytopic": "all", - "topic": "topic", - "outputs": 1, - "x": 650, - "y": 160, - "wires": [ - [ - "ee8894e4.f1855" - ] - ] - }, - { - "id": "d7cd8a56.628178", - "type": "trigger", - "z": "60b06629.a2ebd", - "g": "60e44fde.c914f8", - "name": "10 sec to on", - "op1": "", - "op2": "{\"CurrentAirPurifierState\":2}", - "op1type": "nul", - "op2type": "json", - "duration": "10", - "extend": false, - "units": "s", - "reset": "", - "bytopic": "all", - "topic": "topic", - "outputs": 1, - "x": 650, - "y": 200, - "wires": [ - [ - "ee8894e4.f1855" - ] - ] - }, - { - "id": "3de34c4c.1871a4", - "type": "trigger", - "z": "60b06629.a2ebd", - "g": "60e44fde.c914f8", - "name": "5 sec to off", - "op1": "", - "op2": "{\"CurrentAirPurifierState\":0}", - "op1type": "nul", - "op2type": "json", - "duration": "5", - "extend": false, - "units": "s", - "reset": "", - "bytopic": "all", - "topic": "topic", - "outputs": 1, - "x": 650, - "y": 240, - "wires": [ - [ - "ee8894e4.f1855" - ] - ] - }, - { - "id": "ee8894e4.f1855", - "type": "link out", - "z": "60b06629.a2ebd", - "g": "60e44fde.c914f8", - "name": "", - "links": [ - "46418e19.aa6d6" - ], - "x": 795, - "y": 200, - "wires": [] - }, - { - "id": "409001a1.3e7a78", - "type": "homekit-bridge", - "z": "", - "bridgeName": "Demo 1", - "pinCode": "153-10-538", - "port": "", - "allowInsecureRequest": false, - "manufacturer": "NRCHKB", - "model": "Demo", - "serialNo": "1.1.2", - "customMdnsConfig": false, - "mdnsMulticast": true, - "mdnsInterface": "", - "mdnsPort": "", - "mdnsIp": "", - "mdnsTtl": "", - "mdnsLoopback": true, - "mdnsReuseAddr": true, - "allowMessagePassthrough": true - } + "nodes": [ + "8dea49.4a770db8", + "5302e4aa.1b466c", + "bfe1c73d.c165a8", + "9739d842.a402f", + "87048a6e.df64e8", + "db412cea.4a62f8", + "46418e19.aa6d6", + "664dadf9.85d0d4", + "d7cd8a56.628178", + "3de34c4c.1871a4", + "ee8894e4.f1855" + ], + "x": 14, + "y": 119, + "w": 822, + "h": 162, + "info": "Turning the device on or off will send:\n`{\"Active\":[0, 1]}`\n\nAfter changing power state, the device will be \"Turning on\" or \"Turning off\" until a current state is sent of:\n`{\"CurrentAirPurifierState\":[0, 1, 2]}`\n0: off
\n1: idle
\n2: on
\n\nThere will be a slider in the home app for sending `RotationSpeed`\n\nThere will be a switch on Home app for \"Oscillate\" which sends:\n`{\"SwingMode\":[0,1]}`\n\nChanging mode to manual to auto will send payload:\n`{\"TargetAirPurifierState\":[0, 1]}`\n\nChild lock will send \n`{\"LockPhysicalControls\": [0, 1]}`\n\n" + }, + { + "id": "8dea49.4a770db8", + "type": "inject", + "z": "60b06629.a2ebd", + "g": "60e44fde.c914f8", + "name": "off", + "props": [ + { + "p": "payload" + } + ], + "repeat": "", + "crontab": "", + "once": false, + "onceDelay": 0.1, + "topic": "", + "payload": "{\"CurrentAirPurifierState\":0}", + "payloadType": "json", + "x": 110, + "y": 160, + "wires": [["5302e4aa.1b466c"]] + }, + { + "id": "5302e4aa.1b466c", + "type": "homekit-service", + "z": "60b06629.a2ebd", + "g": "60e44fde.c914f8", + "isParent": true, + "bridge": "409001a1.3e7a78", + "parentService": "", + "name": "Air purifier", + "serviceName": "AirPurifier", + "topic": "", + "filter": false, + "manufacturer": "Purity", + "model": "Air", + "serialNo": "23", + "firmwareRev": "1.0.0", + "hardwareRev": "1.0.0", + "softwareRev": "1.0.0", + "cameraConfigVideoProcessor": "ffmpeg", + "cameraConfigSource": "", + "cameraConfigStillImageSource": "", + "cameraConfigMaxStreams": 2, + "cameraConfigMaxWidth": 1280, + "cameraConfigMaxHeight": 720, + "cameraConfigMaxFPS": 10, + "cameraConfigMaxBitrate": 300, + "cameraConfigVideoCodec": "libx264", + "cameraConfigAudioCodec": "libfdk_aac", + "cameraConfigAudio": false, + "cameraConfigPacketSize": 1316, + "cameraConfigVerticalFlip": false, + "cameraConfigHorizontalFlip": false, + "cameraConfigMapVideo": "0:0", + "cameraConfigMapAudio": "0:1", + "cameraConfigVideoFilter": "scale=1280:720", + "cameraConfigAdditionalCommandLine": "-tune zerolatency", + "cameraConfigDebug": false, + "cameraConfigSnapshotOutput": "disabled", + "cameraConfigInterfaceName": "", + "characteristicProperties": "{\n \"SwingMode\":true,\n \"RotationSpeed\":true,\n \"LockPhysicalControls\":true\n}", + "outputs": 2, + "x": 290, + "y": 160, + "wires": [["bfe1c73d.c165a8", "9739d842.a402f"], []] + }, + { + "id": "bfe1c73d.c165a8", + "type": "debug", + "z": "60b06629.a2ebd", + "g": "60e44fde.c914f8", + "name": "Purifier output", + "active": true, + "tosidebar": true, + "console": false, + "tostatus": false, + "complete": "true", + "targetType": "full", + "x": 420, + "y": 240, + "wires": [] + }, + { + "id": "9739d842.a402f", + "type": "function", + "z": "60b06629.a2ebd", + "g": "60e44fde.c914f8", + "name": "on/off", + "func": "if (msg.hap !== undefined && msg.hap.context !== undefined){\n if (msg.payload.Active === 1){\n return [msg,null];\n }\n if (msg.payload.Active === 0){\n return [null,msg];\n }\n}\nreturn;", + "outputs": 2, + "noerr": 0, + "initialize": "", + "finalize": "", + "x": 450, + "y": 160, + "wires": [["664dadf9.85d0d4", "d7cd8a56.628178"], ["3de34c4c.1871a4"]], + "outputLabels": ["On", "Off"] + }, + { + "id": "87048a6e.df64e8", + "type": "inject", + "z": "60b06629.a2ebd", + "g": "60e44fde.c914f8", + "name": "idle", + "props": [ + { + "p": "payload" + } + ], + "repeat": "", + "crontab": "", + "once": false, + "onceDelay": 0.1, + "topic": "", + "payload": "{\"CurrentAirPurifierState\":1}", + "payloadType": "json", + "x": 110, + "y": 200, + "wires": [["5302e4aa.1b466c"]] + }, + { + "id": "db412cea.4a62f8", + "type": "inject", + "z": "60b06629.a2ebd", + "g": "60e44fde.c914f8", + "name": "on", + "props": [ + { + "p": "payload" + } + ], + "repeat": "", + "crontab": "", + "once": false, + "onceDelay": 0.1, + "topic": "", + "payload": "{\"CurrentAirPurifierState\":2}", + "payloadType": "json", + "x": 110, + "y": 240, + "wires": [["5302e4aa.1b466c"]] + }, + { + "id": "46418e19.aa6d6", + "type": "link in", + "z": "60b06629.a2ebd", + "g": "60e44fde.c914f8", + "name": "", + "links": ["ee8894e4.f1855"], + "x": 235, + "y": 240, + "wires": [["5302e4aa.1b466c"]] + }, + { + "id": "664dadf9.85d0d4", + "type": "trigger", + "z": "60b06629.a2ebd", + "g": "60e44fde.c914f8", + "name": "5 sec to idle", + "op1": "", + "op2": "{\"CurrentAirPurifierState\":1}", + "op1type": "nul", + "op2type": "json", + "duration": "5", + "extend": false, + "units": "s", + "reset": "", + "bytopic": "all", + "topic": "topic", + "outputs": 1, + "x": 650, + "y": 160, + "wires": [["ee8894e4.f1855"]] + }, + { + "id": "d7cd8a56.628178", + "type": "trigger", + "z": "60b06629.a2ebd", + "g": "60e44fde.c914f8", + "name": "10 sec to on", + "op1": "", + "op2": "{\"CurrentAirPurifierState\":2}", + "op1type": "nul", + "op2type": "json", + "duration": "10", + "extend": false, + "units": "s", + "reset": "", + "bytopic": "all", + "topic": "topic", + "outputs": 1, + "x": 650, + "y": 200, + "wires": [["ee8894e4.f1855"]] + }, + { + "id": "3de34c4c.1871a4", + "type": "trigger", + "z": "60b06629.a2ebd", + "g": "60e44fde.c914f8", + "name": "5 sec to off", + "op1": "", + "op2": "{\"CurrentAirPurifierState\":0}", + "op1type": "nul", + "op2type": "json", + "duration": "5", + "extend": false, + "units": "s", + "reset": "", + "bytopic": "all", + "topic": "topic", + "outputs": 1, + "x": 650, + "y": 240, + "wires": [["ee8894e4.f1855"]] + }, + { + "id": "ee8894e4.f1855", + "type": "link out", + "z": "60b06629.a2ebd", + "g": "60e44fde.c914f8", + "name": "", + "links": ["46418e19.aa6d6"], + "x": 795, + "y": 200, + "wires": [] + }, + { + "id": "409001a1.3e7a78", + "type": "homekit-bridge", + "z": "", + "bridgeName": "Demo 1", + "pinCode": "153-10-538", + "port": "", + "allowInsecureRequest": false, + "manufacturer": "NRCHKB", + "model": "Demo", + "serialNo": "1.1.2", + "customMdnsConfig": false, + "mdnsMulticast": true, + "mdnsInterface": "", + "mdnsPort": "", + "mdnsIp": "", + "mdnsTtl": "", + "mdnsLoopback": true, + "mdnsReuseAddr": true, + "allowMessagePassthrough": true + } ] diff --git a/examples/demo/03 - Air Quality sensor with Battery.json b/examples/demo/03 - Air Quality sensor with Battery.json index 88cbee76..597488da 100644 --- a/examples/demo/03 - Air Quality sensor with Battery.json +++ b/examples/demo/03 - Air Quality sensor with Battery.json @@ -1,286 +1,258 @@ [ - { - "id": "b3b5156e.cdf988", - "type": "group", - "z": "eeb8b00c.2c18c", - "name": "Air Quality with Battery: input only sensor", - "style": { - "stroke": "#999999", - "fill": "none", - "label": true, - "label-position": "nw", - "color": "#a4a4a4" - }, - "nodes": [ - "8088a797.e1a7c", - "a70b3192.dfb4f", - "d5708f5.036c87", - "90b692e4.b9f6c", - "54bfafbc.396898", - "560fc866.6de558", - "61e113b2.dbb714" - ], - "x": 94, - "y": 239, - "w": 758, - "h": 208, - "info": "# Air Quality Sensor\n\nThis sensor will inject random values for all of the air quality metrics available in the HomeKit spec. It will also inject random values for a linked battery service.\n\nWatch the input and Home app to learn how to see how things are working." + { + "id": "b3b5156e.cdf988", + "type": "group", + "z": "eeb8b00c.2c18c", + "name": "Air Quality with Battery: input only sensor", + "style": { + "stroke": "#999999", + "fill": "none", + "label": true, + "label-position": "nw", + "color": "#a4a4a4" }, - { - "id": "8088a797.e1a7c", - "type": "homekit-service", - "z": "eeb8b00c.2c18c", - "g": "b3b5156e.cdf988", - "isParent": true, - "hostType": "0", - "bridge": "409001a1.3e7a78", - "accessoryId": "", - "parentService": "", - "name": "Air Quality", - "serviceName": "AirQualitySensor", - "topic": "", - "filter": false, - "manufacturer": "Quality", - "model": "Battery", - "serialNo": "777", - "firmwareRev": "8.3", - "hardwareRev": "2.1", - "softwareRev": "1.0.0", - "cameraConfigVideoProcessor": "ffmpeg", - "cameraConfigSource": "", - "cameraConfigStillImageSource": "", - "cameraConfigMaxStreams": 2, - "cameraConfigMaxWidth": 1280, - "cameraConfigMaxHeight": 720, - "cameraConfigMaxFPS": 10, - "cameraConfigMaxBitrate": 300, - "cameraConfigVideoCodec": "libx264", - "cameraConfigAudioCodec": "libfdk_aac", - "cameraConfigAudio": false, - "cameraConfigPacketSize": 1316, - "cameraConfigVerticalFlip": false, - "cameraConfigHorizontalFlip": false, - "cameraConfigMapVideo": "0:0", - "cameraConfigMapAudio": "0:1", - "cameraConfigVideoFilter": "scale=1280:720", - "cameraConfigAdditionalCommandLine": "-tune zerolatency", - "cameraConfigDebug": false, - "cameraConfigSnapshotOutput": "disabled", - "cameraConfigInterfaceName": "", - "characteristicProperties": "{ \"AirQuality\":true, \"PM2_5Density\":true, \"PM10Density\":true}", - "waitForSetupMsg": false, - "outputs": 2, - "x": 750, - "y": 280, - "wires": [ - [], - [] - ] + "nodes": [ + "8088a797.e1a7c", + "a70b3192.dfb4f", + "d5708f5.036c87", + "90b692e4.b9f6c", + "54bfafbc.396898", + "560fc866.6de558", + "61e113b2.dbb714" + ], + "x": 94, + "y": 239, + "w": 758, + "h": 208, + "info": "# Air Quality Sensor\n\nThis sensor will inject random values for all of the air quality metrics available in the HomeKit spec. It will also inject random values for a linked battery service.\n\nWatch the input and Home app to learn how to see how things are working." + }, + { + "id": "8088a797.e1a7c", + "type": "homekit-service", + "z": "eeb8b00c.2c18c", + "g": "b3b5156e.cdf988", + "isParent": true, + "hostType": "0", + "bridge": "409001a1.3e7a78", + "accessoryId": "", + "parentService": "", + "name": "Air Quality", + "serviceName": "AirQualitySensor", + "topic": "", + "filter": false, + "manufacturer": "Quality", + "model": "Battery", + "serialNo": "777", + "firmwareRev": "8.3", + "hardwareRev": "2.1", + "softwareRev": "1.0.0", + "cameraConfigVideoProcessor": "ffmpeg", + "cameraConfigSource": "", + "cameraConfigStillImageSource": "", + "cameraConfigMaxStreams": 2, + "cameraConfigMaxWidth": 1280, + "cameraConfigMaxHeight": 720, + "cameraConfigMaxFPS": 10, + "cameraConfigMaxBitrate": 300, + "cameraConfigVideoCodec": "libx264", + "cameraConfigAudioCodec": "libfdk_aac", + "cameraConfigAudio": false, + "cameraConfigPacketSize": 1316, + "cameraConfigVerticalFlip": false, + "cameraConfigHorizontalFlip": false, + "cameraConfigMapVideo": "0:0", + "cameraConfigMapAudio": "0:1", + "cameraConfigVideoFilter": "scale=1280:720", + "cameraConfigAdditionalCommandLine": "-tune zerolatency", + "cameraConfigDebug": false, + "cameraConfigSnapshotOutput": "disabled", + "cameraConfigInterfaceName": "", + "characteristicProperties": "{ \"AirQuality\":true, \"PM2_5Density\":true, \"PM10Density\":true}", + "waitForSetupMsg": false, + "outputs": 2, + "x": 750, + "y": 280, + "wires": [[], []] + }, + { + "id": "a70b3192.dfb4f", + "type": "inject", + "z": "eeb8b00c.2c18c", + "g": "b3b5156e.cdf988", + "name": "Air quality random", + "props": [ + { + "p": "payload" + } + ], + "repeat": "15", + "crontab": "", + "once": true, + "onceDelay": "5", + "topic": "", + "payload": "{}", + "payloadType": "json", + "x": 230, + "y": 280, + "wires": [["560fc866.6de558"]] + }, + { + "id": "d5708f5.036c87", + "type": "inject", + "z": "eeb8b00c.2c18c", + "g": "b3b5156e.cdf988", + "name": "Battery random", + "props": [ + { + "p": "payload" + } + ], + "repeat": "30", + "crontab": "", + "once": true, + "onceDelay": "5", + "topic": "", + "payload": "", + "payloadType": "date", + "x": 220, + "y": 380, + "wires": [["90b692e4.b9f6c"]] + }, + { + "id": "90b692e4.b9f6c", + "type": "function", + "z": "eeb8b00c.2c18c", + "g": "b3b5156e.cdf988", + "name": "Batt", + "func": "// Define random battery level\nconst level = Math.floor(Math.random() * Math.floor(100))\nvar newMsg = {\n payload: {\n \"BatteryLevel\": level\n }\n};\n\n// Show \"Low Battery\" if less than 10%\nif (level < 10)newMsg.payload.StatusLowBattery = 1;\nelse newMsg.payload.StatusLowBattery = 0;\n\n// Show \"Charging\" if greater than 60%\nif (level > 60) newMsg.payload.ChargingState = 1;\nelse newMsg.payload.ChargingState = 0;\n\nreturn newMsg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "x": 470, + "y": 380, + "wires": [["5cd5342a.cfd72c"]] + }, + { + "id": "54bfafbc.396898", + "type": "inject", + "z": "eeb8b00c.2c18c", + "g": "b3b5156e.cdf988", + "name": "NO RESPONSE", + "props": [ + { + "p": "payload" + } + ], + "repeat": "", + "crontab": "", + "once": false, + "onceDelay": 0.1, + "topic": "", + "payload": "{\"AirQuality\":\"NO_RESPONSE\"}", + "payloadType": "json", + "x": 500, + "y": 320, + "wires": [["8088a797.e1a7c"]] + }, + { + "id": "560fc866.6de558", + "type": "function", + "z": "eeb8b00c.2c18c", + "g": "b3b5156e.cdf988", + "name": "Random values", + "func": "var newMsg = {\n \"payload\":{\n \"AirQuality\":Math.floor(Math.random() * Math.floor(5)),\n \"PM2_5Density\":Math.floor(Math.random() * Math.floor(1000)),\n \"PM10Density\":Math.floor(Math.random() * Math.floor(1000)),\n \"OzoneDensity\":Math.floor(Math.random() * Math.floor(1000)),\n \"NitrogenDioxideDensity\":Math.floor(Math.random() * Math.floor(1000)),\n \"SulphurDioxideDensity\": Math.floor(Math.random() * Math.floor(1000))\n }\n}\n\n\n\nreturn newMsg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "x": 500, + "y": 280, + "wires": [["8088a797.e1a7c"]] + }, + { + "id": "61e113b2.dbb714", + "type": "group", + "z": "eeb8b00c.2c18c", + "g": "b3b5156e.cdf988", + "name": "LINKED", + "style": { + "stroke": "#0070c0", + "fill": "#bfdbef", + "label": true }, - { - "id": "a70b3192.dfb4f", - "type": "inject", - "z": "eeb8b00c.2c18c", - "g": "b3b5156e.cdf988", - "name": "Air quality random", - "props": [ - { - "p": "payload" - } - ], - "repeat": "15", - "crontab": "", - "once": true, - "onceDelay": "5", - "topic": "", - "payload": "{}", - "payloadType": "json", - "x": 230, - "y": 280, - "wires": [ - [ - "560fc866.6de558" - ] - ] - }, - { - "id": "d5708f5.036c87", - "type": "inject", - "z": "eeb8b00c.2c18c", - "g": "b3b5156e.cdf988", - "name": "Battery random", - "props": [ - { - "p": "payload" - } - ], - "repeat": "30", - "crontab": "", - "once": true, - "onceDelay": "5", - "topic": "", - "payload": "", - "payloadType": "date", - "x": 220, - "y": 380, - "wires": [ - [ - "90b692e4.b9f6c" - ] - ] - }, - { - "id": "90b692e4.b9f6c", - "type": "function", - "z": "eeb8b00c.2c18c", - "g": "b3b5156e.cdf988", - "name": "Batt", - "func": "// Define random battery level\nconst level = Math.floor(Math.random() * Math.floor(100))\nvar newMsg = {\n payload: {\n \"BatteryLevel\": level\n }\n};\n\n// Show \"Low Battery\" if less than 10%\nif (level < 10)newMsg.payload.StatusLowBattery = 1;\nelse newMsg.payload.StatusLowBattery = 0;\n\n// Show \"Charging\" if greater than 60%\nif (level > 60) newMsg.payload.ChargingState = 1;\nelse newMsg.payload.ChargingState = 0;\n\nreturn newMsg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "x": 470, - "y": 380, - "wires": [ - [ - "5cd5342a.cfd72c" - ] - ] - }, - { - "id": "54bfafbc.396898", - "type": "inject", - "z": "eeb8b00c.2c18c", - "g": "b3b5156e.cdf988", - "name": "NO RESPONSE", - "props": [ - { - "p": "payload" - } - ], - "repeat": "", - "crontab": "", - "once": false, - "onceDelay": 0.1, - "topic": "", - "payload": "{\"AirQuality\":\"NO_RESPONSE\"}", - "payloadType": "json", - "x": 500, - "y": 320, - "wires": [ - [ - "8088a797.e1a7c" - ] - ] - }, - { - "id": "560fc866.6de558", - "type": "function", - "z": "eeb8b00c.2c18c", - "g": "b3b5156e.cdf988", - "name": "Random values", - "func": "var newMsg = {\n \"payload\":{\n \"AirQuality\":Math.floor(Math.random() * Math.floor(5)),\n \"PM2_5Density\":Math.floor(Math.random() * Math.floor(1000)),\n \"PM10Density\":Math.floor(Math.random() * Math.floor(1000)),\n \"OzoneDensity\":Math.floor(Math.random() * Math.floor(1000)),\n \"NitrogenDioxideDensity\":Math.floor(Math.random() * Math.floor(1000)),\n \"SulphurDioxideDensity\": Math.floor(Math.random() * Math.floor(1000))\n }\n}\n\n\n\nreturn newMsg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "x": 500, - "y": 280, - "wires": [ - [ - "8088a797.e1a7c" - ] - ] - }, - { - "id": "61e113b2.dbb714", - "type": "group", - "z": "eeb8b00c.2c18c", - "g": "b3b5156e.cdf988", - "name": "LINKED", - "style": { - "stroke": "#0070c0", - "fill": "#bfdbef", - "label": true - }, - "nodes": [ - "5cd5342a.cfd72c" - ], - "x": 654, - "y": 339, - "w": 172, - "h": 82 - }, - { - "id": "5cd5342a.cfd72c", - "type": "homekit-service", - "z": "eeb8b00c.2c18c", - "g": "61e113b2.dbb714", - "isParent": false, - "hostType": "0", - "bridge": "", - "accessoryId": "", - "parentService": "8088a797.e1a7c", - "name": "Battery", - "serviceName": "Battery", - "topic": "Air Quality", - "filter": false, - "manufacturer": "Default Manufacturer", - "model": "Default Model", - "serialNo": "Default Serial Number", - "firmwareRev": "1.0.0", - "hardwareRev": "1.0.0", - "softwareRev": "1.0.0", - "cameraConfigVideoProcessor": "ffmpeg", - "cameraConfigSource": "", - "cameraConfigStillImageSource": "", - "cameraConfigMaxStreams": 2, - "cameraConfigMaxWidth": 1280, - "cameraConfigMaxHeight": 720, - "cameraConfigMaxFPS": 10, - "cameraConfigMaxBitrate": 300, - "cameraConfigVideoCodec": "libx264", - "cameraConfigAudioCodec": "libfdk_aac", - "cameraConfigAudio": false, - "cameraConfigPacketSize": 1316, - "cameraConfigVerticalFlip": false, - "cameraConfigHorizontalFlip": false, - "cameraConfigMapVideo": "0:0", - "cameraConfigMapAudio": "0:1", - "cameraConfigVideoFilter": "scale=1280:720", - "cameraConfigAdditionalCommandLine": "-tune zerolatency", - "cameraConfigDebug": false, - "cameraConfigSnapshotOutput": "disabled", - "cameraConfigInterfaceName": "", - "characteristicProperties": "{}", - "waitForSetupMsg": false, - "outputs": 2, - "x": 740, - "y": 380, - "wires": [ - [], - [] - ] - }, - { - "id": "409001a1.3e7a78", - "type": "homekit-bridge", - "bridgeName": "Demo 1", - "pinCode": "153-10-538", - "port": "", - "allowInsecureRequest": false, - "manufacturer": "NRCHKB", - "model": "Demo", - "serialNo": "1.1.2", - "customMdnsConfig": false, - "mdnsMulticast": true, - "mdnsInterface": "", - "mdnsPort": "", - "mdnsIp": "", - "mdnsTtl": "", - "mdnsLoopback": true, - "mdnsReuseAddr": true, - "allowMessagePassthrough": true - } + "nodes": ["5cd5342a.cfd72c"], + "x": 654, + "y": 339, + "w": 172, + "h": 82 + }, + { + "id": "5cd5342a.cfd72c", + "type": "homekit-service", + "z": "eeb8b00c.2c18c", + "g": "61e113b2.dbb714", + "isParent": false, + "hostType": "0", + "bridge": "", + "accessoryId": "", + "parentService": "8088a797.e1a7c", + "name": "Battery", + "serviceName": "Battery", + "topic": "Air Quality", + "filter": false, + "manufacturer": "Default Manufacturer", + "model": "Default Model", + "serialNo": "Default Serial Number", + "firmwareRev": "1.0.0", + "hardwareRev": "1.0.0", + "softwareRev": "1.0.0", + "cameraConfigVideoProcessor": "ffmpeg", + "cameraConfigSource": "", + "cameraConfigStillImageSource": "", + "cameraConfigMaxStreams": 2, + "cameraConfigMaxWidth": 1280, + "cameraConfigMaxHeight": 720, + "cameraConfigMaxFPS": 10, + "cameraConfigMaxBitrate": 300, + "cameraConfigVideoCodec": "libx264", + "cameraConfigAudioCodec": "libfdk_aac", + "cameraConfigAudio": false, + "cameraConfigPacketSize": 1316, + "cameraConfigVerticalFlip": false, + "cameraConfigHorizontalFlip": false, + "cameraConfigMapVideo": "0:0", + "cameraConfigMapAudio": "0:1", + "cameraConfigVideoFilter": "scale=1280:720", + "cameraConfigAdditionalCommandLine": "-tune zerolatency", + "cameraConfigDebug": false, + "cameraConfigSnapshotOutput": "disabled", + "cameraConfigInterfaceName": "", + "characteristicProperties": "{}", + "waitForSetupMsg": false, + "outputs": 2, + "x": 740, + "y": 380, + "wires": [[], []] + }, + { + "id": "409001a1.3e7a78", + "type": "homekit-bridge", + "bridgeName": "Demo 1", + "pinCode": "153-10-538", + "port": "", + "allowInsecureRequest": false, + "manufacturer": "NRCHKB", + "model": "Demo", + "serialNo": "1.1.2", + "customMdnsConfig": false, + "mdnsMulticast": true, + "mdnsInterface": "", + "mdnsPort": "", + "mdnsIp": "", + "mdnsTtl": "", + "mdnsLoopback": true, + "mdnsReuseAddr": true, + "allowMessagePassthrough": true + } ] diff --git a/examples/demo/04 - Dimmable Bulb.json b/examples/demo/04 - Dimmable Bulb.json index 587c4be0..d181b54f 100644 --- a/examples/demo/04 - Dimmable Bulb.json +++ b/examples/demo/04 - Dimmable Bulb.json @@ -1,192 +1,175 @@ [ - { - "id": "3a57bebe.a3b222", - "type": "group", - "z": "60b06629.a2ebd", - "name": "Dimmable Bulb: input from device, output to device", - "style": { - "stroke": "#999999", - "fill": "none", - "label": true, - "label-position": "nw", - "color": "#a4a4a4" - }, - "nodes": [ - "459254fe.49c72c", - "379657db.a99df8", - "52a07047.03ce7", - "253b3550.729caa", - "b9bc7f3d.51acf" - ], - "x": 14, - "y": 519, - "w": 752, - "h": 122, - "info": "# Dimmable Bulb\n\nThis is a dimmable bulb. The Characteristic Properties enable brightness. It is a white bulb which can be adjusted from 0 to 100% brightness." + { + "id": "3a57bebe.a3b222", + "type": "group", + "z": "60b06629.a2ebd", + "name": "Dimmable Bulb: input from device, output to device", + "style": { + "stroke": "#999999", + "fill": "none", + "label": true, + "label-position": "nw", + "color": "#a4a4a4" }, - { - "id": "459254fe.49c72c", - "type": "homekit-service", - "z": "60b06629.a2ebd", - "g": "3a57bebe.a3b222", - "isParent": true, - "bridge": "409001a1.3e7a78", - "parentService": "", - "name": "Dimmable", - "serviceName": "Lightbulb", - "topic": "", - "filter": false, - "manufacturer": "Garrett", - "model": "Dummy", - "serialNo": "Default Serial Number", - "firmwareRev": "1.1.9", - "hardwareRev": "1.0.0", - "softwareRev": "1.0.0", - "cameraConfigVideoProcessor": "ffmpeg", - "cameraConfigSource": "", - "cameraConfigStillImageSource": "", - "cameraConfigMaxStreams": 2, - "cameraConfigMaxWidth": 1280, - "cameraConfigMaxHeight": 720, - "cameraConfigMaxFPS": 10, - "cameraConfigMaxBitrate": 300, - "cameraConfigVideoCodec": "libx264", - "cameraConfigAudioCodec": "libfdk_aac", - "cameraConfigAudio": false, - "cameraConfigPacketSize": 1316, - "cameraConfigVerticalFlip": false, - "cameraConfigHorizontalFlip": false, - "cameraConfigMapVideo": "0:0", - "cameraConfigMapAudio": "0:1", - "cameraConfigVideoFilter": "scale=1280:720", - "cameraConfigAdditionalCommandLine": "-tune zerolatency", - "cameraConfigDebug": false, - "cameraConfigSnapshotOutput": "disabled", - "cameraConfigInterfaceName": "", - "characteristicProperties": "{\n \"Brightness\":true\n}", - "outputs": 2, - "x": 380, - "y": 600, - "wires": [ - [ - "379657db.a99df8" - ], - [] - ] - }, - { - "id": "379657db.a99df8", - "type": "debug", - "z": "60b06629.a2ebd", - "g": "3a57bebe.a3b222", - "name": "Dimmable light output", - "active": true, - "tosidebar": true, - "console": false, - "tostatus": false, - "complete": "payload", - "targetType": "msg", - "x": 620, - "y": 600, - "wires": [] - }, - { - "id": "52a07047.03ce7", - "type": "inject", - "z": "60b06629.a2ebd", - "g": "3a57bebe.a3b222", - "name": "NO RESPONSE", - "props": [ - { - "p": "payload" - } - ], - "repeat": "", - "crontab": "", - "once": false, - "onceDelay": 0.1, - "topic": "", - "payload": "{\"On\":\"NO_RESPONSE\"}", - "payloadType": "json", - "x": 320, - "y": 560, - "wires": [ - [ - "459254fe.49c72c" - ] - ] - }, - { - "id": "253b3550.729caa", - "type": "inject", - "z": "60b06629.a2ebd", - "g": "3a57bebe.a3b222", - "name": "ON", - "props": [ - { - "p": "payload" - } - ], - "repeat": "", - "crontab": "", - "once": false, - "onceDelay": 0.1, - "topic": "", - "payload": "{\"On\":true}", - "payloadType": "json", - "x": 110, - "y": 560, - "wires": [ - [ - "459254fe.49c72c" - ] - ] - }, - { - "id": "b9bc7f3d.51acf", - "type": "inject", - "z": "60b06629.a2ebd", - "g": "3a57bebe.a3b222", - "name": "OFF", - "props": [ - { - "p": "payload" - } - ], - "repeat": "", - "crontab": "", - "once": false, - "onceDelay": 0.1, - "topic": "", - "payload": "{\"On\":false}", - "payloadType": "json", - "x": 110, - "y": 600, - "wires": [ - [ - "459254fe.49c72c" - ] - ] - }, - { - "id": "409001a1.3e7a78", - "type": "homekit-bridge", - "z": "", - "bridgeName": "Demo 1", - "pinCode": "153-10-538", - "port": "", - "allowInsecureRequest": false, - "manufacturer": "NRCHKB", - "model": "Demo", - "serialNo": "1.1.2", - "customMdnsConfig": false, - "mdnsMulticast": true, - "mdnsInterface": "", - "mdnsPort": "", - "mdnsIp": "", - "mdnsTtl": "", - "mdnsLoopback": true, - "mdnsReuseAddr": true, - "allowMessagePassthrough": true - } + "nodes": [ + "459254fe.49c72c", + "379657db.a99df8", + "52a07047.03ce7", + "253b3550.729caa", + "b9bc7f3d.51acf" + ], + "x": 14, + "y": 519, + "w": 752, + "h": 122, + "info": "# Dimmable Bulb\n\nThis is a dimmable bulb. The Characteristic Properties enable brightness. It is a white bulb which can be adjusted from 0 to 100% brightness." + }, + { + "id": "459254fe.49c72c", + "type": "homekit-service", + "z": "60b06629.a2ebd", + "g": "3a57bebe.a3b222", + "isParent": true, + "bridge": "409001a1.3e7a78", + "parentService": "", + "name": "Dimmable", + "serviceName": "Lightbulb", + "topic": "", + "filter": false, + "manufacturer": "Garrett", + "model": "Dummy", + "serialNo": "Default Serial Number", + "firmwareRev": "1.1.9", + "hardwareRev": "1.0.0", + "softwareRev": "1.0.0", + "cameraConfigVideoProcessor": "ffmpeg", + "cameraConfigSource": "", + "cameraConfigStillImageSource": "", + "cameraConfigMaxStreams": 2, + "cameraConfigMaxWidth": 1280, + "cameraConfigMaxHeight": 720, + "cameraConfigMaxFPS": 10, + "cameraConfigMaxBitrate": 300, + "cameraConfigVideoCodec": "libx264", + "cameraConfigAudioCodec": "libfdk_aac", + "cameraConfigAudio": false, + "cameraConfigPacketSize": 1316, + "cameraConfigVerticalFlip": false, + "cameraConfigHorizontalFlip": false, + "cameraConfigMapVideo": "0:0", + "cameraConfigMapAudio": "0:1", + "cameraConfigVideoFilter": "scale=1280:720", + "cameraConfigAdditionalCommandLine": "-tune zerolatency", + "cameraConfigDebug": false, + "cameraConfigSnapshotOutput": "disabled", + "cameraConfigInterfaceName": "", + "characteristicProperties": "{\n \"Brightness\":true\n}", + "outputs": 2, + "x": 380, + "y": 600, + "wires": [["379657db.a99df8"], []] + }, + { + "id": "379657db.a99df8", + "type": "debug", + "z": "60b06629.a2ebd", + "g": "3a57bebe.a3b222", + "name": "Dimmable light output", + "active": true, + "tosidebar": true, + "console": false, + "tostatus": false, + "complete": "payload", + "targetType": "msg", + "x": 620, + "y": 600, + "wires": [] + }, + { + "id": "52a07047.03ce7", + "type": "inject", + "z": "60b06629.a2ebd", + "g": "3a57bebe.a3b222", + "name": "NO RESPONSE", + "props": [ + { + "p": "payload" + } + ], + "repeat": "", + "crontab": "", + "once": false, + "onceDelay": 0.1, + "topic": "", + "payload": "{\"On\":\"NO_RESPONSE\"}", + "payloadType": "json", + "x": 320, + "y": 560, + "wires": [["459254fe.49c72c"]] + }, + { + "id": "253b3550.729caa", + "type": "inject", + "z": "60b06629.a2ebd", + "g": "3a57bebe.a3b222", + "name": "ON", + "props": [ + { + "p": "payload" + } + ], + "repeat": "", + "crontab": "", + "once": false, + "onceDelay": 0.1, + "topic": "", + "payload": "{\"On\":true}", + "payloadType": "json", + "x": 110, + "y": 560, + "wires": [["459254fe.49c72c"]] + }, + { + "id": "b9bc7f3d.51acf", + "type": "inject", + "z": "60b06629.a2ebd", + "g": "3a57bebe.a3b222", + "name": "OFF", + "props": [ + { + "p": "payload" + } + ], + "repeat": "", + "crontab": "", + "once": false, + "onceDelay": 0.1, + "topic": "", + "payload": "{\"On\":false}", + "payloadType": "json", + "x": 110, + "y": 600, + "wires": [["459254fe.49c72c"]] + }, + { + "id": "409001a1.3e7a78", + "type": "homekit-bridge", + "z": "", + "bridgeName": "Demo 1", + "pinCode": "153-10-538", + "port": "", + "allowInsecureRequest": false, + "manufacturer": "NRCHKB", + "model": "Demo", + "serialNo": "1.1.2", + "customMdnsConfig": false, + "mdnsMulticast": true, + "mdnsInterface": "", + "mdnsPort": "", + "mdnsIp": "", + "mdnsTtl": "", + "mdnsLoopback": true, + "mdnsReuseAddr": true, + "allowMessagePassthrough": true + } ] diff --git a/examples/demo/05 - Color Bulb (HSV).json b/examples/demo/05 - Color Bulb (HSV).json index 1b55fac1..e5604c39 100644 --- a/examples/demo/05 - Color Bulb (HSV).json +++ b/examples/demo/05 - Color Bulb (HSV).json @@ -1,219 +1,198 @@ [ - { - "id": "384e0889.1fdae", - "type": "group", - "z": "60b06629.a2ebd", - "name": "Color Bulb: input from device, output to device", - "style": { - "stroke": "#999999", - "fill": "none", - "label": true, - "label-position": "nw", - "color": "#a4a4a4" - }, - "nodes": [ - "d838176b.dbaf7", - "7bf880d4.3cd4d", - "ee1452a5.08edd", - "c6ed2a2a.90a01", - "8cdfae2b.2f2ce8", - "1758401b.6c62e8" - ], - "x": 14, - "y": 659, - "w": 752, - "h": 162, - "info": "# Color Bulb\n\nThis is a color bulb. It accepts and sends out Hue, Saturation, Value, and On/off state.\n\nHue is the color\n\nSaturation is how deep the color is\n\nValue is brightness\n\nOn is power state" + { + "id": "384e0889.1fdae", + "type": "group", + "z": "60b06629.a2ebd", + "name": "Color Bulb: input from device, output to device", + "style": { + "stroke": "#999999", + "fill": "none", + "label": true, + "label-position": "nw", + "color": "#a4a4a4" }, - { - "id": "d838176b.dbaf7", - "type": "debug", - "z": "60b06629.a2ebd", - "g": "384e0889.1fdae", - "name": "Color light output", - "active": true, - "tosidebar": true, - "console": false, - "tostatus": false, - "complete": "payload", - "targetType": "msg", - "x": 630, - "y": 780, - "wires": [] - }, - { - "id": "7bf880d4.3cd4d", - "type": "homekit-service", - "z": "60b06629.a2ebd", - "g": "384e0889.1fdae", - "isParent": true, - "bridge": "409001a1.3e7a78", - "parentService": "", - "name": "Color", - "serviceName": "Lightbulb", - "topic": "", - "filter": false, - "manufacturer": "Garrett", - "model": "Color", - "serialNo": "42", - "firmwareRev": "1.2", - "hardwareRev": "1.0.0", - "softwareRev": "1.0.0", - "cameraConfigVideoProcessor": "ffmpeg", - "cameraConfigSource": "", - "cameraConfigStillImageSource": "", - "cameraConfigMaxStreams": 2, - "cameraConfigMaxWidth": 1280, - "cameraConfigMaxHeight": 720, - "cameraConfigMaxFPS": 10, - "cameraConfigMaxBitrate": 300, - "cameraConfigVideoCodec": "libx264", - "cameraConfigAudioCodec": "libfdk_aac", - "cameraConfigAudio": false, - "cameraConfigPacketSize": 1316, - "cameraConfigVerticalFlip": false, - "cameraConfigHorizontalFlip": false, - "cameraConfigMapVideo": "0:0", - "cameraConfigMapAudio": "0:1", - "cameraConfigVideoFilter": "scale=1280:720", - "cameraConfigAdditionalCommandLine": "-tune zerolatency", - "cameraConfigDebug": false, - "cameraConfigSnapshotOutput": "disabled", - "cameraConfigInterfaceName": "", - "characteristicProperties": "{\n \"Brightness\":true,\n \"Hue\":true,\n \"Saturation\":true\n}", - "outputs": 2, - "x": 410, - "y": 780, - "wires": [ - [ - "d838176b.dbaf7" - ], - [] - ] - }, - { - "id": "ee1452a5.08edd", - "type": "inject", - "z": "60b06629.a2ebd", - "g": "384e0889.1fdae", - "name": "NO RESPONSE", - "props": [ - { - "p": "payload" - } - ], - "repeat": "", - "crontab": "", - "once": false, - "onceDelay": 0.1, - "topic": "", - "payload": "{\"On\":\"NO_RESPONSE\"}", - "payloadType": "json", - "x": 340, - "y": 700, - "wires": [ - [ - "7bf880d4.3cd4d" - ] - ] - }, - { - "id": "c6ed2a2a.90a01", - "type": "inject", - "z": "60b06629.a2ebd", - "g": "384e0889.1fdae", - "name": "ON", - "props": [ - { - "p": "payload" - } - ], - "repeat": "", - "crontab": "", - "once": false, - "onceDelay": 0.1, - "topic": "", - "payload": "{\"On\":true}", - "payloadType": "json", - "x": 110, - "y": 700, - "wires": [ - [ - "7bf880d4.3cd4d" - ] - ] - }, - { - "id": "8cdfae2b.2f2ce8", - "type": "inject", - "z": "60b06629.a2ebd", - "g": "384e0889.1fdae", - "name": "Reset HSV", - "props": [ - { - "p": "payload" - } - ], - "repeat": "", - "crontab": "", - "once": false, - "onceDelay": 0.1, - "topic": "", - "payload": "{\"Brightness\":50,\"Hue\":50,\"Saturation\":50}", - "payloadType": "json", - "x": 120, - "y": 780, - "wires": [ - [ - "7bf880d4.3cd4d" - ] - ] - }, - { - "id": "1758401b.6c62e8", - "type": "inject", - "z": "60b06629.a2ebd", - "g": "384e0889.1fdae", - "name": "OFF", - "props": [ - { - "p": "payload" - } - ], - "repeat": "", - "crontab": "", - "once": false, - "onceDelay": 0.1, - "topic": "", - "payload": "{\"On\":false}", - "payloadType": "json", - "x": 110, - "y": 740, - "wires": [ - [ - "7bf880d4.3cd4d" - ] - ] - }, - { - "id": "409001a1.3e7a78", - "type": "homekit-bridge", - "z": "", - "bridgeName": "Demo 1", - "pinCode": "153-10-538", - "port": "", - "allowInsecureRequest": false, - "manufacturer": "NRCHKB", - "model": "Demo", - "serialNo": "1.1.2", - "customMdnsConfig": false, - "mdnsMulticast": true, - "mdnsInterface": "", - "mdnsPort": "", - "mdnsIp": "", - "mdnsTtl": "", - "mdnsLoopback": true, - "mdnsReuseAddr": true, - "allowMessagePassthrough": true - } + "nodes": [ + "d838176b.dbaf7", + "7bf880d4.3cd4d", + "ee1452a5.08edd", + "c6ed2a2a.90a01", + "8cdfae2b.2f2ce8", + "1758401b.6c62e8" + ], + "x": 14, + "y": 659, + "w": 752, + "h": 162, + "info": "# Color Bulb\n\nThis is a color bulb. It accepts and sends out Hue, Saturation, Value, and On/off state.\n\nHue is the color\n\nSaturation is how deep the color is\n\nValue is brightness\n\nOn is power state" + }, + { + "id": "d838176b.dbaf7", + "type": "debug", + "z": "60b06629.a2ebd", + "g": "384e0889.1fdae", + "name": "Color light output", + "active": true, + "tosidebar": true, + "console": false, + "tostatus": false, + "complete": "payload", + "targetType": "msg", + "x": 630, + "y": 780, + "wires": [] + }, + { + "id": "7bf880d4.3cd4d", + "type": "homekit-service", + "z": "60b06629.a2ebd", + "g": "384e0889.1fdae", + "isParent": true, + "bridge": "409001a1.3e7a78", + "parentService": "", + "name": "Color", + "serviceName": "Lightbulb", + "topic": "", + "filter": false, + "manufacturer": "Garrett", + "model": "Color", + "serialNo": "42", + "firmwareRev": "1.2", + "hardwareRev": "1.0.0", + "softwareRev": "1.0.0", + "cameraConfigVideoProcessor": "ffmpeg", + "cameraConfigSource": "", + "cameraConfigStillImageSource": "", + "cameraConfigMaxStreams": 2, + "cameraConfigMaxWidth": 1280, + "cameraConfigMaxHeight": 720, + "cameraConfigMaxFPS": 10, + "cameraConfigMaxBitrate": 300, + "cameraConfigVideoCodec": "libx264", + "cameraConfigAudioCodec": "libfdk_aac", + "cameraConfigAudio": false, + "cameraConfigPacketSize": 1316, + "cameraConfigVerticalFlip": false, + "cameraConfigHorizontalFlip": false, + "cameraConfigMapVideo": "0:0", + "cameraConfigMapAudio": "0:1", + "cameraConfigVideoFilter": "scale=1280:720", + "cameraConfigAdditionalCommandLine": "-tune zerolatency", + "cameraConfigDebug": false, + "cameraConfigSnapshotOutput": "disabled", + "cameraConfigInterfaceName": "", + "characteristicProperties": "{\n \"Brightness\":true,\n \"Hue\":true,\n \"Saturation\":true\n}", + "outputs": 2, + "x": 410, + "y": 780, + "wires": [["d838176b.dbaf7"], []] + }, + { + "id": "ee1452a5.08edd", + "type": "inject", + "z": "60b06629.a2ebd", + "g": "384e0889.1fdae", + "name": "NO RESPONSE", + "props": [ + { + "p": "payload" + } + ], + "repeat": "", + "crontab": "", + "once": false, + "onceDelay": 0.1, + "topic": "", + "payload": "{\"On\":\"NO_RESPONSE\"}", + "payloadType": "json", + "x": 340, + "y": 700, + "wires": [["7bf880d4.3cd4d"]] + }, + { + "id": "c6ed2a2a.90a01", + "type": "inject", + "z": "60b06629.a2ebd", + "g": "384e0889.1fdae", + "name": "ON", + "props": [ + { + "p": "payload" + } + ], + "repeat": "", + "crontab": "", + "once": false, + "onceDelay": 0.1, + "topic": "", + "payload": "{\"On\":true}", + "payloadType": "json", + "x": 110, + "y": 700, + "wires": [["7bf880d4.3cd4d"]] + }, + { + "id": "8cdfae2b.2f2ce8", + "type": "inject", + "z": "60b06629.a2ebd", + "g": "384e0889.1fdae", + "name": "Reset HSV", + "props": [ + { + "p": "payload" + } + ], + "repeat": "", + "crontab": "", + "once": false, + "onceDelay": 0.1, + "topic": "", + "payload": "{\"Brightness\":50,\"Hue\":50,\"Saturation\":50}", + "payloadType": "json", + "x": 120, + "y": 780, + "wires": [["7bf880d4.3cd4d"]] + }, + { + "id": "1758401b.6c62e8", + "type": "inject", + "z": "60b06629.a2ebd", + "g": "384e0889.1fdae", + "name": "OFF", + "props": [ + { + "p": "payload" + } + ], + "repeat": "", + "crontab": "", + "once": false, + "onceDelay": 0.1, + "topic": "", + "payload": "{\"On\":false}", + "payloadType": "json", + "x": 110, + "y": 740, + "wires": [["7bf880d4.3cd4d"]] + }, + { + "id": "409001a1.3e7a78", + "type": "homekit-bridge", + "z": "", + "bridgeName": "Demo 1", + "pinCode": "153-10-538", + "port": "", + "allowInsecureRequest": false, + "manufacturer": "NRCHKB", + "model": "Demo", + "serialNo": "1.1.2", + "customMdnsConfig": false, + "mdnsMulticast": true, + "mdnsInterface": "", + "mdnsPort": "", + "mdnsIp": "", + "mdnsTtl": "", + "mdnsLoopback": true, + "mdnsReuseAddr": true, + "allowMessagePassthrough": true + } ] diff --git a/examples/demo/06 - Fan (simple, 3 speeds).json b/examples/demo/06 - Fan (simple, 3 speeds).json index f38ccab7..17f9b7b8 100644 --- a/examples/demo/06 - Fan (simple, 3 speeds).json +++ b/examples/demo/06 - Fan (simple, 3 speeds).json @@ -1,268 +1,243 @@ [ - { - "id": "c869b0a5.e4def8", - "type": "group", - "z": "60b06629.a2ebd", - "name": "Fan Simplified: input from device, output to device", - "style": { - "stroke": "#999999", - "fill": "none", - "label": true, - "label-position": "nw", - "color": "#a4a4a4" - }, - "nodes": [ - "dadd634c.ae2258", - "753e3777.49a1d", - "992f4930.012aa", - "2497a466.aa0e84", - "c53b76fb.7a3cc8", - "6c9646ee.1f3a18", - "1e42a8f3.cf008f" - ], - "x": 14, - "y": 1819, - "w": 752, - "h": 202, - "info": "# Fan Simple\n\nThis example is for a 3-speed fan.\n\nSpeeds are:
\nLow = 33
\nMedium = 66
\nHigh = 99
\n\nValues outside of this are restricted and will not work. The home app will \"snap\" to these values. Siri will respond to \"set fan to low/medium/high\" with the corresponding value." + { + "id": "c869b0a5.e4def8", + "type": "group", + "z": "60b06629.a2ebd", + "name": "Fan Simplified: input from device, output to device", + "style": { + "stroke": "#999999", + "fill": "none", + "label": true, + "label-position": "nw", + "color": "#a4a4a4" }, - { - "id": "dadd634c.ae2258", - "type": "debug", - "z": "60b06629.a2ebd", - "g": "c869b0a5.e4def8", - "name": "Fan output", - "active": true, - "tosidebar": true, - "console": false, - "tostatus": false, - "complete": "payload", - "targetType": "msg", - "statusVal": "", - "statusType": "auto", - "x": 650, - "y": 1860, - "wires": [] - }, - { - "id": "753e3777.49a1d", - "type": "homekit-service", - "z": "60b06629.a2ebd", - "g": "c869b0a5.e4def8", - "isParent": true, - "bridge": "409001a1.3e7a78", - "parentService": "", - "name": "Fan Speeds", - "serviceName": "Fan", - "topic": "", - "filter": false, - "manufacturer": "Gman", - "model": "Default Model", - "serialNo": "CRX1", - "firmwareRev": "1.0.0", - "hardwareRev": "1.0.0", - "softwareRev": "1.0.0", - "cameraConfigVideoProcessor": "ffmpeg", - "cameraConfigSource": "", - "cameraConfigStillImageSource": "", - "cameraConfigMaxStreams": 2, - "cameraConfigMaxWidth": 1280, - "cameraConfigMaxHeight": 720, - "cameraConfigMaxFPS": 10, - "cameraConfigMaxBitrate": 300, - "cameraConfigVideoCodec": "libx264", - "cameraConfigAudioCodec": "libfdk_aac", - "cameraConfigAudio": false, - "cameraConfigPacketSize": 1316, - "cameraConfigVerticalFlip": false, - "cameraConfigHorizontalFlip": false, - "cameraConfigMapVideo": "0:0", - "cameraConfigMapAudio": "0:1", - "cameraConfigVideoFilter": "scale=1280:720", - "cameraConfigAdditionalCommandLine": "-tune zerolatency", - "cameraConfigDebug": false, - "cameraConfigSnapshotOutput": "disabled", - "cameraConfigInterfaceName": "", - "characteristicProperties": "{\n \"RotationSpeed\": {\n \"minValue\":0,\n \"maxValue\":99,\n \"minStep\":33\n }\n}", - "outputs": 2, - "x": 430, - "y": 1860, - "wires": [ - [ - "dadd634c.ae2258" - ], - [] - ] - }, - { - "id": "992f4930.012aa", - "type": "inject", - "z": "60b06629.a2ebd", - "g": "c869b0a5.e4def8", - "name": "NO RESPONSE", - "props": [ - { - "p": "payload" - }, - { - "p": "topic", - "vt": "str" - } - ], - "repeat": "", - "crontab": "", - "once": false, - "onceDelay": 0.1, - "topic": "", - "payload": "{\"On\":\"NO_RESPONSE\"}", - "payloadType": "json", - "x": 380, - "y": 1940, - "wires": [ - [ - "753e3777.49a1d" - ] - ] - }, - { - "id": "2497a466.aa0e84", - "type": "inject", - "z": "60b06629.a2ebd", - "g": "c869b0a5.e4def8", - "name": "OFF", - "props": [ - { - "p": "payload" - }, - { - "p": "topic", - "vt": "str" - } - ], - "repeat": "", - "crontab": "", - "once": false, - "onceDelay": 0.1, - "topic": "", - "payload": "{\"On\":false}", - "payloadType": "json", - "x": 110, - "y": 1860, - "wires": [ - [ - "753e3777.49a1d" - ] - ] - }, - { - "id": "c53b76fb.7a3cc8", - "type": "inject", - "z": "60b06629.a2ebd", - "g": "c869b0a5.e4def8", - "name": "Low", - "props": [ - { - "p": "payload" - }, - { - "p": "topic", - "vt": "str" - } - ], - "repeat": "", - "crontab": "", - "once": false, - "onceDelay": 0.1, - "topic": "", - "payload": "{\"On\":true,\"RotationSpeed\":33}", - "payloadType": "json", - "x": 110, - "y": 1900, - "wires": [ - [ - "753e3777.49a1d" - ] - ] - }, - { - "id": "6c9646ee.1f3a18", - "type": "inject", - "z": "60b06629.a2ebd", - "g": "c869b0a5.e4def8", - "name": "Medium", - "props": [ - { - "p": "payload" - }, - { - "p": "topic", - "vt": "str" - } - ], - "repeat": "", - "crontab": "", - "once": false, - "onceDelay": 0.1, - "topic": "", - "payload": "{\"On\":true,\"RotationSpeed\":66}", - "payloadType": "json", - "x": 120, - "y": 1940, - "wires": [ - [ - "753e3777.49a1d" - ] - ] - }, - { - "id": "1e42a8f3.cf008f", - "type": "inject", - "z": "60b06629.a2ebd", - "g": "c869b0a5.e4def8", - "name": "High", - "props": [ - { - "p": "payload" - }, - { - "p": "topic", - "vt": "str" - } - ], - "repeat": "", - "crontab": "", - "once": false, - "onceDelay": 0.1, - "topic": "", - "payload": "{\"On\":true,\"RotationSpeed\":99}", - "payloadType": "json", - "x": 110, - "y": 1980, - "wires": [ - [ - "753e3777.49a1d" - ] - ] - }, - { - "id": "409001a1.3e7a78", - "type": "homekit-bridge", - "z": "", - "bridgeName": "Demo 1", - "pinCode": "153-10-538", - "port": "", - "allowInsecureRequest": false, - "manufacturer": "NRCHKB", - "model": "Demo", - "serialNo": "1.1.2", - "customMdnsConfig": false, - "mdnsMulticast": true, - "mdnsInterface": "", - "mdnsPort": "", - "mdnsIp": "", - "mdnsTtl": "", - "mdnsLoopback": true, - "mdnsReuseAddr": true, - "allowMessagePassthrough": true - } + "nodes": [ + "dadd634c.ae2258", + "753e3777.49a1d", + "992f4930.012aa", + "2497a466.aa0e84", + "c53b76fb.7a3cc8", + "6c9646ee.1f3a18", + "1e42a8f3.cf008f" + ], + "x": 14, + "y": 1819, + "w": 752, + "h": 202, + "info": "# Fan Simple\n\nThis example is for a 3-speed fan.\n\nSpeeds are:
\nLow = 33
\nMedium = 66
\nHigh = 99
\n\nValues outside of this are restricted and will not work. The home app will \"snap\" to these values. Siri will respond to \"set fan to low/medium/high\" with the corresponding value." + }, + { + "id": "dadd634c.ae2258", + "type": "debug", + "z": "60b06629.a2ebd", + "g": "c869b0a5.e4def8", + "name": "Fan output", + "active": true, + "tosidebar": true, + "console": false, + "tostatus": false, + "complete": "payload", + "targetType": "msg", + "statusVal": "", + "statusType": "auto", + "x": 650, + "y": 1860, + "wires": [] + }, + { + "id": "753e3777.49a1d", + "type": "homekit-service", + "z": "60b06629.a2ebd", + "g": "c869b0a5.e4def8", + "isParent": true, + "bridge": "409001a1.3e7a78", + "parentService": "", + "name": "Fan Speeds", + "serviceName": "Fan", + "topic": "", + "filter": false, + "manufacturer": "Gman", + "model": "Default Model", + "serialNo": "CRX1", + "firmwareRev": "1.0.0", + "hardwareRev": "1.0.0", + "softwareRev": "1.0.0", + "cameraConfigVideoProcessor": "ffmpeg", + "cameraConfigSource": "", + "cameraConfigStillImageSource": "", + "cameraConfigMaxStreams": 2, + "cameraConfigMaxWidth": 1280, + "cameraConfigMaxHeight": 720, + "cameraConfigMaxFPS": 10, + "cameraConfigMaxBitrate": 300, + "cameraConfigVideoCodec": "libx264", + "cameraConfigAudioCodec": "libfdk_aac", + "cameraConfigAudio": false, + "cameraConfigPacketSize": 1316, + "cameraConfigVerticalFlip": false, + "cameraConfigHorizontalFlip": false, + "cameraConfigMapVideo": "0:0", + "cameraConfigMapAudio": "0:1", + "cameraConfigVideoFilter": "scale=1280:720", + "cameraConfigAdditionalCommandLine": "-tune zerolatency", + "cameraConfigDebug": false, + "cameraConfigSnapshotOutput": "disabled", + "cameraConfigInterfaceName": "", + "characteristicProperties": "{\n \"RotationSpeed\": {\n \"minValue\":0,\n \"maxValue\":99,\n \"minStep\":33\n }\n}", + "outputs": 2, + "x": 430, + "y": 1860, + "wires": [["dadd634c.ae2258"], []] + }, + { + "id": "992f4930.012aa", + "type": "inject", + "z": "60b06629.a2ebd", + "g": "c869b0a5.e4def8", + "name": "NO RESPONSE", + "props": [ + { + "p": "payload" + }, + { + "p": "topic", + "vt": "str" + } + ], + "repeat": "", + "crontab": "", + "once": false, + "onceDelay": 0.1, + "topic": "", + "payload": "{\"On\":\"NO_RESPONSE\"}", + "payloadType": "json", + "x": 380, + "y": 1940, + "wires": [["753e3777.49a1d"]] + }, + { + "id": "2497a466.aa0e84", + "type": "inject", + "z": "60b06629.a2ebd", + "g": "c869b0a5.e4def8", + "name": "OFF", + "props": [ + { + "p": "payload" + }, + { + "p": "topic", + "vt": "str" + } + ], + "repeat": "", + "crontab": "", + "once": false, + "onceDelay": 0.1, + "topic": "", + "payload": "{\"On\":false}", + "payloadType": "json", + "x": 110, + "y": 1860, + "wires": [["753e3777.49a1d"]] + }, + { + "id": "c53b76fb.7a3cc8", + "type": "inject", + "z": "60b06629.a2ebd", + "g": "c869b0a5.e4def8", + "name": "Low", + "props": [ + { + "p": "payload" + }, + { + "p": "topic", + "vt": "str" + } + ], + "repeat": "", + "crontab": "", + "once": false, + "onceDelay": 0.1, + "topic": "", + "payload": "{\"On\":true,\"RotationSpeed\":33}", + "payloadType": "json", + "x": 110, + "y": 1900, + "wires": [["753e3777.49a1d"]] + }, + { + "id": "6c9646ee.1f3a18", + "type": "inject", + "z": "60b06629.a2ebd", + "g": "c869b0a5.e4def8", + "name": "Medium", + "props": [ + { + "p": "payload" + }, + { + "p": "topic", + "vt": "str" + } + ], + "repeat": "", + "crontab": "", + "once": false, + "onceDelay": 0.1, + "topic": "", + "payload": "{\"On\":true,\"RotationSpeed\":66}", + "payloadType": "json", + "x": 120, + "y": 1940, + "wires": [["753e3777.49a1d"]] + }, + { + "id": "1e42a8f3.cf008f", + "type": "inject", + "z": "60b06629.a2ebd", + "g": "c869b0a5.e4def8", + "name": "High", + "props": [ + { + "p": "payload" + }, + { + "p": "topic", + "vt": "str" + } + ], + "repeat": "", + "crontab": "", + "once": false, + "onceDelay": 0.1, + "topic": "", + "payload": "{\"On\":true,\"RotationSpeed\":99}", + "payloadType": "json", + "x": 110, + "y": 1980, + "wires": [["753e3777.49a1d"]] + }, + { + "id": "409001a1.3e7a78", + "type": "homekit-bridge", + "z": "", + "bridgeName": "Demo 1", + "pinCode": "153-10-538", + "port": "", + "allowInsecureRequest": false, + "manufacturer": "NRCHKB", + "model": "Demo", + "serialNo": "1.1.2", + "customMdnsConfig": false, + "mdnsMulticast": true, + "mdnsInterface": "", + "mdnsPort": "", + "mdnsIp": "", + "mdnsTtl": "", + "mdnsLoopback": true, + "mdnsReuseAddr": true, + "allowMessagePassthrough": true + } ] diff --git a/examples/demo/07 - Fan (with speed, oscillate, rotation direction).json b/examples/demo/07 - Fan (with speed, oscillate, rotation direction).json index 7d4542a6..0b2df4c1 100644 --- a/examples/demo/07 - Fan (with speed, oscillate, rotation direction).json +++ b/examples/demo/07 - Fan (with speed, oscillate, rotation direction).json @@ -1,195 +1,178 @@ [ - { - "id": "2c464315.51c50c", - "type": "group", - "z": "60b06629.a2ebd", - "name": "Fan Full Example: input from device, output to device", - "style": { - "stroke": "#999999", - "fill": "none", - "label": true, - "label-position": "nw", - "color": "#a4a4a4" - }, - "nodes": [ - "b7778e52.220a5", - "fd8aff55.91d41", - "c717b796.0735b8", - "f56a2f96.509c1", - "d945ba75.897998" - ], - "x": 14, - "y": 1619, - "w": 752, - "h": 182, - "info": "# Fan V2\n\nThis example shows a fan. The inputs from node red are to turn the fan on, off, or set \"No Response\".\n\nThe outputs going to \"Fan output\" will show:\n\nOn / off state
\nRotation speed
\nSwing mode on / off (oscillate)
\nRotation direction (clockwise/counterclockwise)" + { + "id": "2c464315.51c50c", + "type": "group", + "z": "60b06629.a2ebd", + "name": "Fan Full Example: input from device, output to device", + "style": { + "stroke": "#999999", + "fill": "none", + "label": true, + "label-position": "nw", + "color": "#a4a4a4" }, - { - "id": "b7778e52.220a5", - "type": "debug", - "z": "60b06629.a2ebd", - "g": "2c464315.51c50c", - "name": "Fan output", - "active": true, - "tosidebar": true, - "console": false, - "tostatus": false, - "complete": "payload", - "targetType": "msg", - "x": 650, - "y": 1660, - "wires": [] - }, - { - "id": "fd8aff55.91d41", - "type": "homekit-service", - "z": "60b06629.a2ebd", - "g": "2c464315.51c50c", - "isParent": true, - "bridge": "409001a1.3e7a78", - "parentService": "", - "name": "Fan V2", - "serviceName": "Fanv2", - "topic": "", - "filter": false, - "manufacturer": "Default Manufacturer", - "model": "Default Model", - "serialNo": "Default Serial Number", - "firmwareRev": "1.0.0", - "hardwareRev": "1.0.0", - "softwareRev": "1.0.0", - "cameraConfigVideoProcessor": "ffmpeg", - "cameraConfigSource": "", - "cameraConfigStillImageSource": "", - "cameraConfigMaxStreams": 2, - "cameraConfigMaxWidth": 1280, - "cameraConfigMaxHeight": 720, - "cameraConfigMaxFPS": 10, - "cameraConfigMaxBitrate": 300, - "cameraConfigVideoCodec": "libx264", - "cameraConfigAudioCodec": "libfdk_aac", - "cameraConfigAudio": false, - "cameraConfigPacketSize": 1316, - "cameraConfigVerticalFlip": false, - "cameraConfigHorizontalFlip": false, - "cameraConfigMapVideo": "0:0", - "cameraConfigMapAudio": "0:1", - "cameraConfigVideoFilter": "scale=1280:720", - "cameraConfigAdditionalCommandLine": "-tune zerolatency", - "cameraConfigDebug": false, - "cameraConfigSnapshotOutput": "disabled", - "cameraConfigInterfaceName": "", - "characteristicProperties": "{\n \"RotationSpeed\":true,\n \"RotationDirection\":true,\n \"SwingMode\":true\n}", - "outputs": 2, - "x": 420, - "y": 1660, - "wires": [ - [ - "b7778e52.220a5" - ], - [] - ] - }, - { - "id": "c717b796.0735b8", - "type": "inject", - "z": "60b06629.a2ebd", - "g": "2c464315.51c50c", - "name": "NO RESPONSE", - "repeat": "", - "crontab": "", - "once": false, - "onceDelay": 0.1, - "topic": "", - "payload": "{\"Active\":\"NO_RESPONSE\"}", - "payloadType": "json", - "x": 140, - "y": 1760, - "wires": [ - [ - "fd8aff55.91d41" - ] - ] - }, - { - "id": "f56a2f96.509c1", - "type": "inject", - "z": "60b06629.a2ebd", - "g": "2c464315.51c50c", - "name": "ON", - "props": [ - { - "p": "payload" - }, - { - "p": "topic", - "vt": "str" - } - ], - "repeat": "", - "crontab": "", - "once": false, - "onceDelay": 0.1, - "topic": "", - "payload": "{\"Active\":true}", - "payloadType": "json", - "x": 120, - "y": 1660, - "wires": [ - [ - "fd8aff55.91d41" - ] - ] - }, - { - "id": "d945ba75.897998", - "type": "inject", - "z": "60b06629.a2ebd", - "g": "2c464315.51c50c", - "name": "OFF", - "props": [ - { - "p": "payload" - }, - { - "p": "topic", - "vt": "str" - } - ], - "repeat": "", - "crontab": "", - "once": false, - "onceDelay": 0.1, - "topic": "", - "payload": "{\"Active\":false}", - "payloadType": "json", - "x": 120, - "y": 1700, - "wires": [ - [ - "fd8aff55.91d41" - ] - ] - }, - { - "id": "409001a1.3e7a78", - "type": "homekit-bridge", - "z": "", - "bridgeName": "Demo 1", - "pinCode": "153-10-538", - "port": "", - "allowInsecureRequest": false, - "manufacturer": "NRCHKB", - "model": "Demo", - "serialNo": "1.1.2", - "customMdnsConfig": false, - "mdnsMulticast": true, - "mdnsInterface": "", - "mdnsPort": "", - "mdnsIp": "", - "mdnsTtl": "", - "mdnsLoopback": true, - "mdnsReuseAddr": true, - "allowMessagePassthrough": true - } + "nodes": [ + "b7778e52.220a5", + "fd8aff55.91d41", + "c717b796.0735b8", + "f56a2f96.509c1", + "d945ba75.897998" + ], + "x": 14, + "y": 1619, + "w": 752, + "h": 182, + "info": "# Fan V2\n\nThis example shows a fan. The inputs from node red are to turn the fan on, off, or set \"No Response\".\n\nThe outputs going to \"Fan output\" will show:\n\nOn / off state
\nRotation speed
\nSwing mode on / off (oscillate)
\nRotation direction (clockwise/counterclockwise)" + }, + { + "id": "b7778e52.220a5", + "type": "debug", + "z": "60b06629.a2ebd", + "g": "2c464315.51c50c", + "name": "Fan output", + "active": true, + "tosidebar": true, + "console": false, + "tostatus": false, + "complete": "payload", + "targetType": "msg", + "x": 650, + "y": 1660, + "wires": [] + }, + { + "id": "fd8aff55.91d41", + "type": "homekit-service", + "z": "60b06629.a2ebd", + "g": "2c464315.51c50c", + "isParent": true, + "bridge": "409001a1.3e7a78", + "parentService": "", + "name": "Fan V2", + "serviceName": "Fanv2", + "topic": "", + "filter": false, + "manufacturer": "Default Manufacturer", + "model": "Default Model", + "serialNo": "Default Serial Number", + "firmwareRev": "1.0.0", + "hardwareRev": "1.0.0", + "softwareRev": "1.0.0", + "cameraConfigVideoProcessor": "ffmpeg", + "cameraConfigSource": "", + "cameraConfigStillImageSource": "", + "cameraConfigMaxStreams": 2, + "cameraConfigMaxWidth": 1280, + "cameraConfigMaxHeight": 720, + "cameraConfigMaxFPS": 10, + "cameraConfigMaxBitrate": 300, + "cameraConfigVideoCodec": "libx264", + "cameraConfigAudioCodec": "libfdk_aac", + "cameraConfigAudio": false, + "cameraConfigPacketSize": 1316, + "cameraConfigVerticalFlip": false, + "cameraConfigHorizontalFlip": false, + "cameraConfigMapVideo": "0:0", + "cameraConfigMapAudio": "0:1", + "cameraConfigVideoFilter": "scale=1280:720", + "cameraConfigAdditionalCommandLine": "-tune zerolatency", + "cameraConfigDebug": false, + "cameraConfigSnapshotOutput": "disabled", + "cameraConfigInterfaceName": "", + "characteristicProperties": "{\n \"RotationSpeed\":true,\n \"RotationDirection\":true,\n \"SwingMode\":true\n}", + "outputs": 2, + "x": 420, + "y": 1660, + "wires": [["b7778e52.220a5"], []] + }, + { + "id": "c717b796.0735b8", + "type": "inject", + "z": "60b06629.a2ebd", + "g": "2c464315.51c50c", + "name": "NO RESPONSE", + "repeat": "", + "crontab": "", + "once": false, + "onceDelay": 0.1, + "topic": "", + "payload": "{\"Active\":\"NO_RESPONSE\"}", + "payloadType": "json", + "x": 140, + "y": 1760, + "wires": [["fd8aff55.91d41"]] + }, + { + "id": "f56a2f96.509c1", + "type": "inject", + "z": "60b06629.a2ebd", + "g": "2c464315.51c50c", + "name": "ON", + "props": [ + { + "p": "payload" + }, + { + "p": "topic", + "vt": "str" + } + ], + "repeat": "", + "crontab": "", + "once": false, + "onceDelay": 0.1, + "topic": "", + "payload": "{\"Active\":true}", + "payloadType": "json", + "x": 120, + "y": 1660, + "wires": [["fd8aff55.91d41"]] + }, + { + "id": "d945ba75.897998", + "type": "inject", + "z": "60b06629.a2ebd", + "g": "2c464315.51c50c", + "name": "OFF", + "props": [ + { + "p": "payload" + }, + { + "p": "topic", + "vt": "str" + } + ], + "repeat": "", + "crontab": "", + "once": false, + "onceDelay": 0.1, + "topic": "", + "payload": "{\"Active\":false}", + "payloadType": "json", + "x": 120, + "y": 1700, + "wires": [["fd8aff55.91d41"]] + }, + { + "id": "409001a1.3e7a78", + "type": "homekit-bridge", + "z": "", + "bridgeName": "Demo 1", + "pinCode": "153-10-538", + "port": "", + "allowInsecureRequest": false, + "manufacturer": "NRCHKB", + "model": "Demo", + "serialNo": "1.1.2", + "customMdnsConfig": false, + "mdnsMulticast": true, + "mdnsInterface": "", + "mdnsPort": "", + "mdnsIp": "", + "mdnsTtl": "", + "mdnsLoopback": true, + "mdnsReuseAddr": true, + "allowMessagePassthrough": true + } ] diff --git a/examples/demo/08 - CO2 detector.json b/examples/demo/08 - CO2 detector.json index cefad8e9..686cdfcf 100644 --- a/examples/demo/08 - CO2 detector.json +++ b/examples/demo/08 - CO2 detector.json @@ -1,258 +1,227 @@ [ - { - "id": "ab48426e.25466", - "type": "group", - "z": "60b06629.a2ebd", - "name": "CO2 Sensor: input only sensor", - "style": { - "stroke": "#999999", - "fill": "none", - "label": true, - "label-position": "nw", - "color": "#a4a4a4" - }, - "nodes": [ - "88892b4.8a61bd8", - "3611c654.8a42f2", - "62cafcb0.8ade9c", - "a0171cdb.f209b", - "6f7de764.a6a688", - "8758b463.afb0f", - "69e8161b.74b7a", - "40010b09.c73cdc" - ], - "x": 14, - "y": 839, - "w": 752, - "h": 202, - "info": "# CO2 Sensor\n\nThere are three inputs to this example, one for each level of Carbon Dioxide in the air. Options are:\n\n**0 ppm:** this will assume no CO2
\n**Safe level:** this will assume a level between 1 and 999 ppm, inclusive
\n**Dangerous level:** this will assume a level between 1,000 and 100,000, inclusive; this will also trigger an alert" + { + "id": "ab48426e.25466", + "type": "group", + "z": "60b06629.a2ebd", + "name": "CO2 Sensor: input only sensor", + "style": { + "stroke": "#999999", + "fill": "none", + "label": true, + "label-position": "nw", + "color": "#a4a4a4" }, - { - "id": "88892b4.8a61bd8", - "type": "homekit-service", - "z": "60b06629.a2ebd", - "g": "ab48426e.25466", - "isParent": true, - "bridge": "409001a1.3e7a78", - "parentService": "", - "name": "CO2 Sensor", - "serviceName": "CarbonDioxideSensor", - "topic": "", - "filter": false, - "manufacturer": "Default Manufacturer", - "model": "Carbon", - "serialNo": "Default Serial Number", - "firmwareRev": "22", - "hardwareRev": "11", - "cameraConfigVideoProcessor": "", - "cameraConfigSource": "", - "cameraConfigStillImageSource": "", - "cameraConfigMaxStreams": "", - "cameraConfigMaxWidth": "", - "cameraConfigMaxHeight": "", - "cameraConfigMaxFPS": "", - "cameraConfigMaxBitrate": "", - "cameraConfigVideoCodec": "", - "cameraConfigAudioCodec": "", - "cameraConfigAudio": false, - "cameraConfigPacketSize": "", - "cameraConfigVerticalFlip": false, - "cameraConfigHorizontalFlip": false, - "cameraConfigMapVideo": "", - "cameraConfigMapAudio": "", - "cameraConfigVideoFilter": "", - "cameraConfigAdditionalCommandLine": "", - "cameraConfigDebug": false, - "cameraConfigSnapshotOutput": "disabled", - "cameraConfigInterfaceName": "", - "characteristicProperties": "{\n \"CarbonDioxideLevel\" : true,\n \"CarbonDioxidePeakLevel\": true,\n \"StatusActive\" : true\n}", - "outputs": 2, - "x": 670, - "y": 880, - "wires": [ - [], - [] - ] - }, - { - "id": "3611c654.8a42f2", - "type": "function", - "z": "60b06629.a2ebd", - "g": "ab48426e.25466", - "name": "Random values, peak value", - "func": "// Reset all values to 0 if 0ppm input\nif(msg.payload === 0){\n context.set('lastPeak',0);\n newMsg = {\n payload: {\n \"CarbonDioxideLevel\":0,\n \"CarbonDioxidePeakLevel\":0,\n \"CarbonDioxideDetected\":0\n }\n };\n return newMsg;\n}\n\n// Initialize vars\nvar CurrentLevel = 0;\nvar lastPeak = context.get('lastPeak');\n\n// Set random safe or dangerous levels\nif(msg.payload === \"Safe\"){\n CurrentLevel = Math.floor(Math.random() * (999 - 1 + 1) + 1);\n}\nif(msg.payload === \"Danger\"){\n CurrentLevel = Math.floor(Math.random() * (100000 - 1000 + 1) + 1000);\n}\n\n// Formulate output message\nvar newMsg = {\n payload: {\n \"CarbonDioxideLevel\" : CurrentLevel,\n \"CarbonDioxideDetected\" : 0\n }\n};\n\n// Set new peak level\nif(CurrentLevel > lastPeak){\n lastPeak = CurrentLevel;\n context.set('lastPeak',CurrentLevel);\n newMsg.payload.CarbonDioxidePeakLevel = CurrentLevel;\n}\n\n// Set warning if dangerous\nif (CurrentLevel >= 1000) {\n newMsg.payload.CarbonDioxideDetected = 1;\n} \n\nreturn newMsg;", - "outputs": 1, - "noerr": 0, - "initialize": "// Code added here will be run once\n// whenever the node is deployed.\ncontext.set('lastPeak',0);\n", - "finalize": "", - "x": 400, - "y": 880, - "wires": [ - [ - "88892b4.8a61bd8" - ] - ] - }, - { - "id": "62cafcb0.8ade9c", - "type": "inject", - "z": "60b06629.a2ebd", - "g": "ab48426e.25466", - "name": "Active", - "repeat": "", - "crontab": "", - "once": false, - "onceDelay": 0.1, - "topic": "", - "payload": "{\"StatusActive\":true}", - "payloadType": "json", - "x": 470, - "y": 920, - "wires": [ - [ - "88892b4.8a61bd8" - ] - ] - }, - { - "id": "a0171cdb.f209b", - "type": "inject", - "z": "60b06629.a2ebd", - "g": "ab48426e.25466", - "name": "Inactive", - "repeat": "", - "crontab": "", - "once": false, - "onceDelay": 0.1, - "topic": "", - "payload": "{\"StatusActive\":false}", - "payloadType": "json", - "x": 470, - "y": 960, - "wires": [ - [ - "88892b4.8a61bd8" - ] - ] - }, - { - "id": "6f7de764.a6a688", - "type": "inject", - "z": "60b06629.a2ebd", - "g": "ab48426e.25466", - "name": "NO RESPONSE", - "repeat": "", - "crontab": "", - "once": false, - "onceDelay": 0.1, - "topic": "", - "payload": "{\"CarbonDioxideLevel\":\"NO_RESPONSE\"}", - "payloadType": "json", - "x": 440, - "y": 1000, - "wires": [ - [ - "88892b4.8a61bd8" - ] - ] - }, - { - "id": "8758b463.afb0f", - "type": "inject", - "z": "60b06629.a2ebd", - "g": "ab48426e.25466", - "name": "0 ppm", - "props": [ - { - "p": "payload" - } - ], - "repeat": "", - "crontab": "", - "once": false, - "onceDelay": 0.1, - "topic": "", - "payload": "0", - "payloadType": "num", - "x": 110, - "y": 880, - "wires": [ - [ - "3611c654.8a42f2" - ] - ] - }, - { - "id": "69e8161b.74b7a", - "type": "inject", - "z": "60b06629.a2ebd", - "g": "ab48426e.25466", - "name": "Safe Level", - "props": [ - { - "p": "payload" - } - ], - "repeat": "", - "crontab": "", - "once": false, - "onceDelay": 0.1, - "topic": "", - "payload": "Safe", - "payloadType": "str", - "x": 120, - "y": 920, - "wires": [ - [ - "3611c654.8a42f2" - ] - ] - }, - { - "id": "40010b09.c73cdc", - "type": "inject", - "z": "60b06629.a2ebd", - "g": "ab48426e.25466", - "name": "Dangerous level", - "props": [ - { - "p": "payload" - } - ], - "repeat": "", - "crontab": "", - "once": false, - "onceDelay": 0.1, - "topic": "", - "payload": "Danger", - "payloadType": "str", - "x": 140, - "y": 960, - "wires": [ - [ - "3611c654.8a42f2" - ] - ] - }, - { - "id": "409001a1.3e7a78", - "type": "homekit-bridge", - "z": "", - "bridgeName": "Demo 1", - "pinCode": "153-10-538", - "port": "", - "allowInsecureRequest": false, - "manufacturer": "NRCHKB", - "model": "Demo", - "serialNo": "1.1.2", - "customMdnsConfig": false, - "mdnsMulticast": true, - "mdnsInterface": "", - "mdnsPort": "", - "mdnsIp": "", - "mdnsTtl": "", - "mdnsLoopback": true, - "mdnsReuseAddr": true, - "allowMessagePassthrough": true - } + "nodes": [ + "88892b4.8a61bd8", + "3611c654.8a42f2", + "62cafcb0.8ade9c", + "a0171cdb.f209b", + "6f7de764.a6a688", + "8758b463.afb0f", + "69e8161b.74b7a", + "40010b09.c73cdc" + ], + "x": 14, + "y": 839, + "w": 752, + "h": 202, + "info": "# CO2 Sensor\n\nThere are three inputs to this example, one for each level of Carbon Dioxide in the air. Options are:\n\n**0 ppm:** this will assume no CO2
\n**Safe level:** this will assume a level between 1 and 999 ppm, inclusive
\n**Dangerous level:** this will assume a level between 1,000 and 100,000, inclusive; this will also trigger an alert" + }, + { + "id": "88892b4.8a61bd8", + "type": "homekit-service", + "z": "60b06629.a2ebd", + "g": "ab48426e.25466", + "isParent": true, + "bridge": "409001a1.3e7a78", + "parentService": "", + "name": "CO2 Sensor", + "serviceName": "CarbonDioxideSensor", + "topic": "", + "filter": false, + "manufacturer": "Default Manufacturer", + "model": "Carbon", + "serialNo": "Default Serial Number", + "firmwareRev": "22", + "hardwareRev": "11", + "cameraConfigVideoProcessor": "", + "cameraConfigSource": "", + "cameraConfigStillImageSource": "", + "cameraConfigMaxStreams": "", + "cameraConfigMaxWidth": "", + "cameraConfigMaxHeight": "", + "cameraConfigMaxFPS": "", + "cameraConfigMaxBitrate": "", + "cameraConfigVideoCodec": "", + "cameraConfigAudioCodec": "", + "cameraConfigAudio": false, + "cameraConfigPacketSize": "", + "cameraConfigVerticalFlip": false, + "cameraConfigHorizontalFlip": false, + "cameraConfigMapVideo": "", + "cameraConfigMapAudio": "", + "cameraConfigVideoFilter": "", + "cameraConfigAdditionalCommandLine": "", + "cameraConfigDebug": false, + "cameraConfigSnapshotOutput": "disabled", + "cameraConfigInterfaceName": "", + "characteristicProperties": "{\n \"CarbonDioxideLevel\" : true,\n \"CarbonDioxidePeakLevel\": true,\n \"StatusActive\" : true\n}", + "outputs": 2, + "x": 670, + "y": 880, + "wires": [[], []] + }, + { + "id": "3611c654.8a42f2", + "type": "function", + "z": "60b06629.a2ebd", + "g": "ab48426e.25466", + "name": "Random values, peak value", + "func": "// Reset all values to 0 if 0ppm input\nif(msg.payload === 0){\n context.set('lastPeak',0);\n newMsg = {\n payload: {\n \"CarbonDioxideLevel\":0,\n \"CarbonDioxidePeakLevel\":0,\n \"CarbonDioxideDetected\":0\n }\n };\n return newMsg;\n}\n\n// Initialize vars\nvar CurrentLevel = 0;\nvar lastPeak = context.get('lastPeak');\n\n// Set random safe or dangerous levels\nif(msg.payload === \"Safe\"){\n CurrentLevel = Math.floor(Math.random() * (999 - 1 + 1) + 1);\n}\nif(msg.payload === \"Danger\"){\n CurrentLevel = Math.floor(Math.random() * (100000 - 1000 + 1) + 1000);\n}\n\n// Formulate output message\nvar newMsg = {\n payload: {\n \"CarbonDioxideLevel\" : CurrentLevel,\n \"CarbonDioxideDetected\" : 0\n }\n};\n\n// Set new peak level\nif(CurrentLevel > lastPeak){\n lastPeak = CurrentLevel;\n context.set('lastPeak',CurrentLevel);\n newMsg.payload.CarbonDioxidePeakLevel = CurrentLevel;\n}\n\n// Set warning if dangerous\nif (CurrentLevel >= 1000) {\n newMsg.payload.CarbonDioxideDetected = 1;\n} \n\nreturn newMsg;", + "outputs": 1, + "noerr": 0, + "initialize": "// Code added here will be run once\n// whenever the node is deployed.\ncontext.set('lastPeak',0);\n", + "finalize": "", + "x": 400, + "y": 880, + "wires": [["88892b4.8a61bd8"]] + }, + { + "id": "62cafcb0.8ade9c", + "type": "inject", + "z": "60b06629.a2ebd", + "g": "ab48426e.25466", + "name": "Active", + "repeat": "", + "crontab": "", + "once": false, + "onceDelay": 0.1, + "topic": "", + "payload": "{\"StatusActive\":true}", + "payloadType": "json", + "x": 470, + "y": 920, + "wires": [["88892b4.8a61bd8"]] + }, + { + "id": "a0171cdb.f209b", + "type": "inject", + "z": "60b06629.a2ebd", + "g": "ab48426e.25466", + "name": "Inactive", + "repeat": "", + "crontab": "", + "once": false, + "onceDelay": 0.1, + "topic": "", + "payload": "{\"StatusActive\":false}", + "payloadType": "json", + "x": 470, + "y": 960, + "wires": [["88892b4.8a61bd8"]] + }, + { + "id": "6f7de764.a6a688", + "type": "inject", + "z": "60b06629.a2ebd", + "g": "ab48426e.25466", + "name": "NO RESPONSE", + "repeat": "", + "crontab": "", + "once": false, + "onceDelay": 0.1, + "topic": "", + "payload": "{\"CarbonDioxideLevel\":\"NO_RESPONSE\"}", + "payloadType": "json", + "x": 440, + "y": 1000, + "wires": [["88892b4.8a61bd8"]] + }, + { + "id": "8758b463.afb0f", + "type": "inject", + "z": "60b06629.a2ebd", + "g": "ab48426e.25466", + "name": "0 ppm", + "props": [ + { + "p": "payload" + } + ], + "repeat": "", + "crontab": "", + "once": false, + "onceDelay": 0.1, + "topic": "", + "payload": "0", + "payloadType": "num", + "x": 110, + "y": 880, + "wires": [["3611c654.8a42f2"]] + }, + { + "id": "69e8161b.74b7a", + "type": "inject", + "z": "60b06629.a2ebd", + "g": "ab48426e.25466", + "name": "Safe Level", + "props": [ + { + "p": "payload" + } + ], + "repeat": "", + "crontab": "", + "once": false, + "onceDelay": 0.1, + "topic": "", + "payload": "Safe", + "payloadType": "str", + "x": 120, + "y": 920, + "wires": [["3611c654.8a42f2"]] + }, + { + "id": "40010b09.c73cdc", + "type": "inject", + "z": "60b06629.a2ebd", + "g": "ab48426e.25466", + "name": "Dangerous level", + "props": [ + { + "p": "payload" + } + ], + "repeat": "", + "crontab": "", + "once": false, + "onceDelay": 0.1, + "topic": "", + "payload": "Danger", + "payloadType": "str", + "x": 140, + "y": 960, + "wires": [["3611c654.8a42f2"]] + }, + { + "id": "409001a1.3e7a78", + "type": "homekit-bridge", + "z": "", + "bridgeName": "Demo 1", + "pinCode": "153-10-538", + "port": "", + "allowInsecureRequest": false, + "manufacturer": "NRCHKB", + "model": "Demo", + "serialNo": "1.1.2", + "customMdnsConfig": false, + "mdnsMulticast": true, + "mdnsInterface": "", + "mdnsPort": "", + "mdnsIp": "", + "mdnsTtl": "", + "mdnsLoopback": true, + "mdnsReuseAddr": true, + "allowMessagePassthrough": true + } ] diff --git a/examples/demo/09 - CO (carbon monoxide) example.json b/examples/demo/09 - CO (carbon monoxide) example.json index 983c94fb..5bf71f6e 100644 --- a/examples/demo/09 - CO (carbon monoxide) example.json +++ b/examples/demo/09 - CO (carbon monoxide) example.json @@ -1,293 +1,258 @@ [ - { - "id": "6eaa9b9e.282734", - "type": "group", - "z": "60b06629.a2ebd", - "name": "CO plus CO2 Sensor: input only sensor", - "style": { - "stroke": "#999999", - "fill": "none", - "label": true, - "label-position": "nw", - "color": "#a4a4a4" - }, - "nodes": [ - "2e6738a6.ef5dd8", - "79889759.8219c", - "7f53465b.356a68", - "97aff586.786ff8", - "659ff3da.236404", - "e6105066.f8911", - "b433a780.665a7", - "d4b30334.a19e58", - "b0eeeb34.2dde8" - ], - "x": 14, - "y": 1059, - "w": 752, - "h": 282, - "info": "# Combined Sensor\nThis is a sensor which will display both Carbon Monoxide (poisonous, deadly gas) and Carbon Dioxide (what humans exhale) levels.\n\n# CO Sensor\n\nThere are three inputs to this example, one for each level of Carbon Monoxide in the air. Options are:\n\n**0 ppm:** this will assume no CO in the air
\n**Low level:** this will assume a level between 1 and 35 ppm, inclusive. This level is generally assumed to not cause problems in healthy adults
\n**Dangerous level:** this will assume a level between 35 and 5000, inclusive; this will also trigger an alert in Home app\n\n## IF YOU HAVE A CARBON MONOXIDE DETECTOR EVER READING ABOVE 35 PPM, PLEASE EVACUATE THE AREA AND SEEK FRESH AIR IMMEDIATELY TO AVOID RISK OF DEATH ##\n\n# CO2 Sensor\n\nThere are three inputs to this example, one for each level of Carbon Dioxide in the air. Options are:\n\n**0 ppm:** this will assume no CO2 in the air
\n**CO2 Level:** this will assume a level between 1 and 100,000 ppm, inclusive
\n**Dangerous level:** this will assume a level between 1,000 and 100,000, inclusive\n\n" + { + "id": "6eaa9b9e.282734", + "type": "group", + "z": "60b06629.a2ebd", + "name": "CO plus CO2 Sensor: input only sensor", + "style": { + "stroke": "#999999", + "fill": "none", + "label": true, + "label-position": "nw", + "color": "#a4a4a4" }, - { - "id": "2e6738a6.ef5dd8", - "type": "homekit-service", - "z": "60b06629.a2ebd", - "g": "6eaa9b9e.282734", - "isParent": true, - "bridge": "409001a1.3e7a78", - "parentService": "", - "name": "CO detector", - "serviceName": "CarbonMonoxideSensor", - "topic": "", - "filter": false, - "manufacturer": "MONOxide", - "model": "1", - "serialNo": "2", - "firmwareRev": "2", - "hardwareRev": "2", - "softwareRev": "1.0.0", - "cameraConfigVideoProcessor": "ffmpeg", - "cameraConfigSource": "", - "cameraConfigStillImageSource": "", - "cameraConfigMaxStreams": 2, - "cameraConfigMaxWidth": 1280, - "cameraConfigMaxHeight": 720, - "cameraConfigMaxFPS": 10, - "cameraConfigMaxBitrate": 300, - "cameraConfigVideoCodec": "libx264", - "cameraConfigAudioCodec": "libfdk_aac", - "cameraConfigAudio": false, - "cameraConfigPacketSize": 1316, - "cameraConfigVerticalFlip": false, - "cameraConfigHorizontalFlip": false, - "cameraConfigMapVideo": "0:0", - "cameraConfigMapAudio": "0:1", - "cameraConfigVideoFilter": "scale=1280:720", - "cameraConfigAdditionalCommandLine": "-tune zerolatency", - "cameraConfigDebug": false, - "cameraConfigSnapshotOutput": "disabled", - "cameraConfigInterfaceName": "", - "characteristicProperties": "{\n \"CarbonMonoxideLevel\":{\n \"maxValue\":5000\n },\n \"CarbonMonoxidePeakLevel\":{\n \"maxValue\":5000\n },\n \"CarbonDioxideLevel\":true,\n \"CarbonDioxidePeakLevel\":true\n}", - "outputs": 2, - "x": 670, - "y": 1100, - "wires": [ - [], - [] - ] - }, - { - "id": "79889759.8219c", - "type": "function", - "z": "60b06629.a2ebd", - "g": "6eaa9b9e.282734", - "name": "Carbon DIoxide", - "func": "if(msg.payload === 0){\n context.set('lastPeak',0);\n newMsg = {\n payload: {\n \"CarbonDioxideLevel\":0\n }\n }\n return newMsg;\n}\n\n// Initialize vars\nvar CurrentLevel = 0;\nvar lastPeak = context.get('lastPeak');\n\n// Set random level\nif(msg.payload === \"CO2\"){\n CurrentLevel = Math.floor(Math.random() * (100000 - 1 + 1) + 1);\n}\n\n\n// Formulate output message\nvar newMsg = {\n payload: {\n \"CarbonDioxideLevel\" : CurrentLevel\n }\n};\n\n// Set new peak level\nif(CurrentLevel > lastPeak){\n lastPeak = CurrentLevel;\n context.set('lastPeak',CurrentLevel);\n newMsg.payload.CarbonDioxidePeakLevel = CurrentLevel;\n}\n\nreturn newMsg;", - "outputs": 1, - "noerr": 0, - "initialize": "// Code added here will be run once\n// whenever the node is deployed.\ncontext.set('lastPeak',0);", - "finalize": "", - "x": 380, - "y": 1260, - "wires": [ - [ - "2e6738a6.ef5dd8" - ] - ] - }, - { - "id": "7f53465b.356a68", - "type": "function", - "z": "60b06629.a2ebd", - "g": "6eaa9b9e.282734", - "name": "Carbon MONoxide", - "func": "// Reset all values to 0 if 0ppm input\nif(msg.payload === 0){\n context.set('lastPeak',0);\n newMsg = {\n payload: {\n \"CarbonMonoxideLevel\":0,\n \"CarbonMonoxidePeakLevel\":0,\n \"CarbonMonoxideDetected\":0\n }\n };\n return newMsg;\n}\n\n// Initialize vars\nvar CurrentLevel = 0;\nvar lastPeak = context.get('lastPeak');\n\n// Set random Low or Dangerous levels\nif(msg.payload === \"Low\"){\n CurrentLevel = Math.floor(Math.random() * (35 - 1 + 1) + 1);\n}\nif(msg.payload === \"Danger\"){\n CurrentLevel = Math.floor(Math.random() * (5000 - 35 + 1) + 35);\n}\n\n// Formulate output message\nvar newMsg = {\n payload: {\n \"CarbonMonoxideLevel\" : CurrentLevel,\n \"CarbonMonoxideDetected\" : 0\n }\n};\n\n// Set new peak level\nif(CurrentLevel > lastPeak){\n lastPeak = CurrentLevel;\n context.set('lastPeak',CurrentLevel);\n newMsg.payload.CarbonMonoxidePeakLevel = CurrentLevel;\n}\n\n// Set warning if dangerous\nif (CurrentLevel >= 35) {\n newMsg.payload.CarbonMonoxideDetected = 1;\n} \n\nreturn newMsg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "x": 390, - "y": 1140, - "wires": [ - [ - "2e6738a6.ef5dd8" - ] - ] - }, - { - "id": "97aff586.786ff8", - "type": "inject", - "z": "60b06629.a2ebd", - "g": "6eaa9b9e.282734", - "name": "NO RESPONSE", - "props": [ - { - "p": "payload" - }, - { - "p": "topic", - "vt": "str" - } - ], - "repeat": "", - "crontab": "", - "once": false, - "onceDelay": 0.1, - "topic": "", - "payload": "{\"CarbonMonoxideLevel\":\"NO_RESPONSE\"}", - "payloadType": "json", - "x": 400, - "y": 1100, - "wires": [ - [ - "2e6738a6.ef5dd8" - ] - ] - }, - { - "id": "659ff3da.236404", - "type": "inject", - "z": "60b06629.a2ebd", - "g": "6eaa9b9e.282734", - "name": "Clear CO2 Peak", - "props": [ - { - "p": "payload" - } - ], - "repeat": "", - "crontab": "", - "once": false, - "onceDelay": 0.1, - "topic": "", - "payload": "0", - "payloadType": "num", - "x": 140, - "y": 1260, - "wires": [ - [ - "79889759.8219c" - ] - ] - }, - { - "id": "e6105066.f8911", - "type": "inject", - "z": "60b06629.a2ebd", - "g": "6eaa9b9e.282734", - "name": "0 ppm", - "repeat": "", - "crontab": "", - "once": false, - "onceDelay": 0.1, - "topic": "", - "payload": "0", - "payloadType": "num", - "x": 130, - "y": 1100, - "wires": [ - [ - "7f53465b.356a68" - ] - ] - }, - { - "id": "b433a780.665a7", - "type": "inject", - "z": "60b06629.a2ebd", - "g": "6eaa9b9e.282734", - "name": "CO2 Level", - "props": [ - { - "p": "payload" - } - ], - "repeat": "", - "crontab": "", - "once": false, - "onceDelay": 0.1, - "topic": "", - "payload": "CO2", - "payloadType": "str", - "x": 120, - "y": 1300, - "wires": [ - [ - "79889759.8219c" - ] - ] - }, - { - "id": "d4b30334.a19e58", - "type": "inject", - "z": "60b06629.a2ebd", - "g": "6eaa9b9e.282734", - "name": "Low level", - "props": [ - { - "p": "payload" - } - ], - "repeat": "", - "crontab": "", - "once": false, - "onceDelay": 0.1, - "topic": "", - "payload": "Low", - "payloadType": "str", - "x": 140, - "y": 1140, - "wires": [ - [ - "7f53465b.356a68" - ] - ] - }, - { - "id": "b0eeeb34.2dde8", - "type": "inject", - "z": "60b06629.a2ebd", - "g": "6eaa9b9e.282734", - "name": "Danger level", - "props": [ - { - "p": "payload" - } - ], - "repeat": "", - "crontab": "", - "once": false, - "onceDelay": 0.1, - "topic": "", - "payload": "Danger", - "payloadType": "str", - "x": 150, - "y": 1180, - "wires": [ - [ - "7f53465b.356a68" - ] - ] - }, - { - "id": "409001a1.3e7a78", - "type": "homekit-bridge", - "z": "", - "bridgeName": "Demo 1", - "pinCode": "153-10-538", - "port": "", - "allowInsecureRequest": false, - "manufacturer": "NRCHKB", - "model": "Demo", - "serialNo": "1.1.2", - "customMdnsConfig": false, - "mdnsMulticast": true, - "mdnsInterface": "", - "mdnsPort": "", - "mdnsIp": "", - "mdnsTtl": "", - "mdnsLoopback": true, - "mdnsReuseAddr": true, - "allowMessagePassthrough": true - } + "nodes": [ + "2e6738a6.ef5dd8", + "79889759.8219c", + "7f53465b.356a68", + "97aff586.786ff8", + "659ff3da.236404", + "e6105066.f8911", + "b433a780.665a7", + "d4b30334.a19e58", + "b0eeeb34.2dde8" + ], + "x": 14, + "y": 1059, + "w": 752, + "h": 282, + "info": "# Combined Sensor\nThis is a sensor which will display both Carbon Monoxide (poisonous, deadly gas) and Carbon Dioxide (what humans exhale) levels.\n\n# CO Sensor\n\nThere are three inputs to this example, one for each level of Carbon Monoxide in the air. Options are:\n\n**0 ppm:** this will assume no CO in the air
\n**Low level:** this will assume a level between 1 and 35 ppm, inclusive. This level is generally assumed to not cause problems in healthy adults
\n**Dangerous level:** this will assume a level between 35 and 5000, inclusive; this will also trigger an alert in Home app\n\n## IF YOU HAVE A CARBON MONOXIDE DETECTOR EVER READING ABOVE 35 PPM, PLEASE EVACUATE THE AREA AND SEEK FRESH AIR IMMEDIATELY TO AVOID RISK OF DEATH ##\n\n# CO2 Sensor\n\nThere are three inputs to this example, one for each level of Carbon Dioxide in the air. Options are:\n\n**0 ppm:** this will assume no CO2 in the air
\n**CO2 Level:** this will assume a level between 1 and 100,000 ppm, inclusive
\n**Dangerous level:** this will assume a level between 1,000 and 100,000, inclusive\n\n" + }, + { + "id": "2e6738a6.ef5dd8", + "type": "homekit-service", + "z": "60b06629.a2ebd", + "g": "6eaa9b9e.282734", + "isParent": true, + "bridge": "409001a1.3e7a78", + "parentService": "", + "name": "CO detector", + "serviceName": "CarbonMonoxideSensor", + "topic": "", + "filter": false, + "manufacturer": "MONOxide", + "model": "1", + "serialNo": "2", + "firmwareRev": "2", + "hardwareRev": "2", + "softwareRev": "1.0.0", + "cameraConfigVideoProcessor": "ffmpeg", + "cameraConfigSource": "", + "cameraConfigStillImageSource": "", + "cameraConfigMaxStreams": 2, + "cameraConfigMaxWidth": 1280, + "cameraConfigMaxHeight": 720, + "cameraConfigMaxFPS": 10, + "cameraConfigMaxBitrate": 300, + "cameraConfigVideoCodec": "libx264", + "cameraConfigAudioCodec": "libfdk_aac", + "cameraConfigAudio": false, + "cameraConfigPacketSize": 1316, + "cameraConfigVerticalFlip": false, + "cameraConfigHorizontalFlip": false, + "cameraConfigMapVideo": "0:0", + "cameraConfigMapAudio": "0:1", + "cameraConfigVideoFilter": "scale=1280:720", + "cameraConfigAdditionalCommandLine": "-tune zerolatency", + "cameraConfigDebug": false, + "cameraConfigSnapshotOutput": "disabled", + "cameraConfigInterfaceName": "", + "characteristicProperties": "{\n \"CarbonMonoxideLevel\":{\n \"maxValue\":5000\n },\n \"CarbonMonoxidePeakLevel\":{\n \"maxValue\":5000\n },\n \"CarbonDioxideLevel\":true,\n \"CarbonDioxidePeakLevel\":true\n}", + "outputs": 2, + "x": 670, + "y": 1100, + "wires": [[], []] + }, + { + "id": "79889759.8219c", + "type": "function", + "z": "60b06629.a2ebd", + "g": "6eaa9b9e.282734", + "name": "Carbon DIoxide", + "func": "if(msg.payload === 0){\n context.set('lastPeak',0);\n newMsg = {\n payload: {\n \"CarbonDioxideLevel\":0\n }\n }\n return newMsg;\n}\n\n// Initialize vars\nvar CurrentLevel = 0;\nvar lastPeak = context.get('lastPeak');\n\n// Set random level\nif(msg.payload === \"CO2\"){\n CurrentLevel = Math.floor(Math.random() * (100000 - 1 + 1) + 1);\n}\n\n\n// Formulate output message\nvar newMsg = {\n payload: {\n \"CarbonDioxideLevel\" : CurrentLevel\n }\n};\n\n// Set new peak level\nif(CurrentLevel > lastPeak){\n lastPeak = CurrentLevel;\n context.set('lastPeak',CurrentLevel);\n newMsg.payload.CarbonDioxidePeakLevel = CurrentLevel;\n}\n\nreturn newMsg;", + "outputs": 1, + "noerr": 0, + "initialize": "// Code added here will be run once\n// whenever the node is deployed.\ncontext.set('lastPeak',0);", + "finalize": "", + "x": 380, + "y": 1260, + "wires": [["2e6738a6.ef5dd8"]] + }, + { + "id": "7f53465b.356a68", + "type": "function", + "z": "60b06629.a2ebd", + "g": "6eaa9b9e.282734", + "name": "Carbon MONoxide", + "func": "// Reset all values to 0 if 0ppm input\nif(msg.payload === 0){\n context.set('lastPeak',0);\n newMsg = {\n payload: {\n \"CarbonMonoxideLevel\":0,\n \"CarbonMonoxidePeakLevel\":0,\n \"CarbonMonoxideDetected\":0\n }\n };\n return newMsg;\n}\n\n// Initialize vars\nvar CurrentLevel = 0;\nvar lastPeak = context.get('lastPeak');\n\n// Set random Low or Dangerous levels\nif(msg.payload === \"Low\"){\n CurrentLevel = Math.floor(Math.random() * (35 - 1 + 1) + 1);\n}\nif(msg.payload === \"Danger\"){\n CurrentLevel = Math.floor(Math.random() * (5000 - 35 + 1) + 35);\n}\n\n// Formulate output message\nvar newMsg = {\n payload: {\n \"CarbonMonoxideLevel\" : CurrentLevel,\n \"CarbonMonoxideDetected\" : 0\n }\n};\n\n// Set new peak level\nif(CurrentLevel > lastPeak){\n lastPeak = CurrentLevel;\n context.set('lastPeak',CurrentLevel);\n newMsg.payload.CarbonMonoxidePeakLevel = CurrentLevel;\n}\n\n// Set warning if dangerous\nif (CurrentLevel >= 35) {\n newMsg.payload.CarbonMonoxideDetected = 1;\n} \n\nreturn newMsg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "x": 390, + "y": 1140, + "wires": [["2e6738a6.ef5dd8"]] + }, + { + "id": "97aff586.786ff8", + "type": "inject", + "z": "60b06629.a2ebd", + "g": "6eaa9b9e.282734", + "name": "NO RESPONSE", + "props": [ + { + "p": "payload" + }, + { + "p": "topic", + "vt": "str" + } + ], + "repeat": "", + "crontab": "", + "once": false, + "onceDelay": 0.1, + "topic": "", + "payload": "{\"CarbonMonoxideLevel\":\"NO_RESPONSE\"}", + "payloadType": "json", + "x": 400, + "y": 1100, + "wires": [["2e6738a6.ef5dd8"]] + }, + { + "id": "659ff3da.236404", + "type": "inject", + "z": "60b06629.a2ebd", + "g": "6eaa9b9e.282734", + "name": "Clear CO2 Peak", + "props": [ + { + "p": "payload" + } + ], + "repeat": "", + "crontab": "", + "once": false, + "onceDelay": 0.1, + "topic": "", + "payload": "0", + "payloadType": "num", + "x": 140, + "y": 1260, + "wires": [["79889759.8219c"]] + }, + { + "id": "e6105066.f8911", + "type": "inject", + "z": "60b06629.a2ebd", + "g": "6eaa9b9e.282734", + "name": "0 ppm", + "repeat": "", + "crontab": "", + "once": false, + "onceDelay": 0.1, + "topic": "", + "payload": "0", + "payloadType": "num", + "x": 130, + "y": 1100, + "wires": [["7f53465b.356a68"]] + }, + { + "id": "b433a780.665a7", + "type": "inject", + "z": "60b06629.a2ebd", + "g": "6eaa9b9e.282734", + "name": "CO2 Level", + "props": [ + { + "p": "payload" + } + ], + "repeat": "", + "crontab": "", + "once": false, + "onceDelay": 0.1, + "topic": "", + "payload": "CO2", + "payloadType": "str", + "x": 120, + "y": 1300, + "wires": [["79889759.8219c"]] + }, + { + "id": "d4b30334.a19e58", + "type": "inject", + "z": "60b06629.a2ebd", + "g": "6eaa9b9e.282734", + "name": "Low level", + "props": [ + { + "p": "payload" + } + ], + "repeat": "", + "crontab": "", + "once": false, + "onceDelay": 0.1, + "topic": "", + "payload": "Low", + "payloadType": "str", + "x": 140, + "y": 1140, + "wires": [["7f53465b.356a68"]] + }, + { + "id": "b0eeeb34.2dde8", + "type": "inject", + "z": "60b06629.a2ebd", + "g": "6eaa9b9e.282734", + "name": "Danger level", + "props": [ + { + "p": "payload" + } + ], + "repeat": "", + "crontab": "", + "once": false, + "onceDelay": 0.1, + "topic": "", + "payload": "Danger", + "payloadType": "str", + "x": 150, + "y": 1180, + "wires": [["7f53465b.356a68"]] + }, + { + "id": "409001a1.3e7a78", + "type": "homekit-bridge", + "z": "", + "bridgeName": "Demo 1", + "pinCode": "153-10-538", + "port": "", + "allowInsecureRequest": false, + "manufacturer": "NRCHKB", + "model": "Demo", + "serialNo": "1.1.2", + "customMdnsConfig": false, + "mdnsMulticast": true, + "mdnsInterface": "", + "mdnsPort": "", + "mdnsIp": "", + "mdnsTtl": "", + "mdnsLoopback": true, + "mdnsReuseAddr": true, + "allowMessagePassthrough": true + } ] diff --git a/examples/demo/10 - Door window contact sensor.json b/examples/demo/10 - Door window contact sensor.json index 10de5934..32fd056b 100644 --- a/examples/demo/10 - Door window contact sensor.json +++ b/examples/demo/10 - Door window contact sensor.json @@ -1,268 +1,237 @@ [ - { - "id": "a875cc7.a4c42b", - "type": "group", - "z": "60b06629.a2ebd", - "name": "Contact Sensor: input only sensor", - "style": { - "stroke": "#999999", - "fill": "none", - "label": true, - "label-position": "nw", - "color": "#a4a4a4" - }, - "nodes": [ - "a5194c26.18c628", - "2f9bc0d.42a73c", - "dfca0b2d.8b8e8", - "d74a610c.09a36", - "c15b6468.ae2eb8", - "6f7bc7fa.7f4f6", - "99b55eb3.e31bf8", - "508d9ccf.29e404" - ], - "x": 14, - "y": 1359, - "w": 752, - "h": 242, - "info": "# Contact Sensor\n\nThe contact sensor has one inject node to Open the sensor (door, window, etc). Once open, a ten second timer will run then set it back to closed.\n\nAdditional inputs are for \"No Response\", \"Tampered\", and \"Battery\". Note that this battery will not show a battery level but only a good/low battery status." + { + "id": "a875cc7.a4c42b", + "type": "group", + "z": "60b06629.a2ebd", + "name": "Contact Sensor: input only sensor", + "style": { + "stroke": "#999999", + "fill": "none", + "label": true, + "label-position": "nw", + "color": "#a4a4a4" }, - { - "id": "a5194c26.18c628", - "type": "homekit-service", - "z": "60b06629.a2ebd", - "g": "a875cc7.a4c42b", - "isParent": true, - "bridge": "409001a1.3e7a78", - "parentService": "", - "name": "Contact Sensor", - "serviceName": "ContactSensor", - "topic": "", - "filter": false, - "manufacturer": "Full Contact", - "model": "Door", - "serialNo": "Sensor", - "firmwareRev": "1.0.0", - "hardwareRev": "1.0.0", - "softwareRev": "1.0.0", - "cameraConfigVideoProcessor": "ffmpeg", - "cameraConfigSource": "", - "cameraConfigStillImageSource": "", - "cameraConfigMaxStreams": 2, - "cameraConfigMaxWidth": 1280, - "cameraConfigMaxHeight": 720, - "cameraConfigMaxFPS": 10, - "cameraConfigMaxBitrate": 300, - "cameraConfigVideoCodec": "libx264", - "cameraConfigAudioCodec": "libfdk_aac", - "cameraConfigAudio": false, - "cameraConfigPacketSize": 1316, - "cameraConfigVerticalFlip": false, - "cameraConfigHorizontalFlip": false, - "cameraConfigMapVideo": "0:0", - "cameraConfigMapAudio": "0:1", - "cameraConfigVideoFilter": "scale=1280:720", - "cameraConfigAdditionalCommandLine": "-tune zerolatency", - "cameraConfigDebug": false, - "cameraConfigSnapshotOutput": "disabled", - "cameraConfigInterfaceName": "", - "characteristicProperties": "{\n \"StatusTampered\":true,\n \"StatusLowBattery\":true\n}", - "outputs": 2, - "x": 660, - "y": 1400, - "wires": [ - [], - [] - ] - }, - { - "id": "2f9bc0d.42a73c", - "type": "inject", - "z": "60b06629.a2ebd", - "g": "a875cc7.a4c42b", - "name": "Tampered", - "repeat": "", - "crontab": "", - "once": false, - "onceDelay": 0.1, - "topic": "", - "payload": "{\"StatusTampered\":1}", - "payloadType": "json", - "x": 120, - "y": 1520, - "wires": [ - [ - "a5194c26.18c628" - ] - ] - }, - { - "id": "dfca0b2d.8b8e8", - "type": "inject", - "z": "60b06629.a2ebd", - "g": "a875cc7.a4c42b", - "name": "Clear tampered", - "repeat": "", - "crontab": "", - "once": false, - "onceDelay": 0.1, - "topic": "", - "payload": "{\"StatusTampered\":0}", - "payloadType": "json", - "x": 140, - "y": 1560, - "wires": [ - [ - "a5194c26.18c628" - ] - ] - }, - { - "id": "d74a610c.09a36", - "type": "inject", - "z": "60b06629.a2ebd", - "g": "a875cc7.a4c42b", - "name": "Low batt", - "repeat": "", - "crontab": "", - "once": false, - "onceDelay": 0.1, - "topic": "", - "payload": "{\"StatusLowBattery\":1}", - "payloadType": "json", - "x": 480, - "y": 1520, - "wires": [ - [ - "a5194c26.18c628" - ] - ] - }, - { - "id": "c15b6468.ae2eb8", - "type": "inject", - "z": "60b06629.a2ebd", - "g": "a875cc7.a4c42b", - "name": "Good batt", - "repeat": "", - "crontab": "", - "once": false, - "onceDelay": 0.1, - "topic": "", - "payload": "{\"StatusLowBattery\":0}", - "payloadType": "json", - "x": 480, - "y": 1560, - "wires": [ - [ - "a5194c26.18c628" - ] - ] - }, - { - "id": "6f7bc7fa.7f4f6", - "type": "inject", - "z": "60b06629.a2ebd", - "g": "a875cc7.a4c42b", - "name": "NO RESPONSE", - "props": [ - { - "p": "payload" - }, - { - "p": "topic", - "vt": "str" - } - ], - "repeat": "", - "crontab": "", - "once": false, - "onceDelay": 0.1, - "topic": "", - "payload": "{\"ContactSensorState\":\"NO_RESPONSE\"}", - "payloadType": "json", - "x": 140, - "y": 1460, - "wires": [ - [ - "a5194c26.18c628" - ] - ] - }, - { - "id": "99b55eb3.e31bf8", - "type": "trigger", - "z": "60b06629.a2ebd", - "g": "a875cc7.a4c42b", - "name": "10 Sec open", - "op1": "", - "op2": "{\"ContactSensorState\":0}", - "op1type": "pay", - "op2type": "json", - "duration": "10", - "extend": false, - "units": "s", - "reset": "", - "bytopic": "all", - "topic": "topic", - "outputs": 1, - "x": 350, - "y": 1400, - "wires": [ - [ - "a5194c26.18c628" - ] - ] - }, - { - "id": "508d9ccf.29e404", - "type": "inject", - "z": "60b06629.a2ebd", - "g": "a875cc7.a4c42b", - "name": "Open", - "props": [ - { - "p": "payload" - }, - { - "p": "topic", - "vt": "str" - } - ], - "repeat": "", - "crontab": "", - "once": false, - "onceDelay": "1", - "topic": "", - "payload": "{\"ContactSensorState\":1}", - "payloadType": "json", - "x": 110, - "y": 1400, - "wires": [ - [ - "99b55eb3.e31bf8" - ] - ] - }, - { - "id": "409001a1.3e7a78", - "type": "homekit-bridge", - "z": "", - "bridgeName": "Demo 1", - "pinCode": "153-10-538", - "port": "", - "allowInsecureRequest": false, - "manufacturer": "NRCHKB", - "model": "Demo", - "serialNo": "1.1.2", - "customMdnsConfig": false, - "mdnsMulticast": true, - "mdnsInterface": "", - "mdnsPort": "", - "mdnsIp": "", - "mdnsTtl": "", - "mdnsLoopback": true, - "mdnsReuseAddr": true, - "allowMessagePassthrough": true - } + "nodes": [ + "a5194c26.18c628", + "2f9bc0d.42a73c", + "dfca0b2d.8b8e8", + "d74a610c.09a36", + "c15b6468.ae2eb8", + "6f7bc7fa.7f4f6", + "99b55eb3.e31bf8", + "508d9ccf.29e404" + ], + "x": 14, + "y": 1359, + "w": 752, + "h": 242, + "info": "# Contact Sensor\n\nThe contact sensor has one inject node to Open the sensor (door, window, etc). Once open, a ten second timer will run then set it back to closed.\n\nAdditional inputs are for \"No Response\", \"Tampered\", and \"Battery\". Note that this battery will not show a battery level but only a good/low battery status." + }, + { + "id": "a5194c26.18c628", + "type": "homekit-service", + "z": "60b06629.a2ebd", + "g": "a875cc7.a4c42b", + "isParent": true, + "bridge": "409001a1.3e7a78", + "parentService": "", + "name": "Contact Sensor", + "serviceName": "ContactSensor", + "topic": "", + "filter": false, + "manufacturer": "Full Contact", + "model": "Door", + "serialNo": "Sensor", + "firmwareRev": "1.0.0", + "hardwareRev": "1.0.0", + "softwareRev": "1.0.0", + "cameraConfigVideoProcessor": "ffmpeg", + "cameraConfigSource": "", + "cameraConfigStillImageSource": "", + "cameraConfigMaxStreams": 2, + "cameraConfigMaxWidth": 1280, + "cameraConfigMaxHeight": 720, + "cameraConfigMaxFPS": 10, + "cameraConfigMaxBitrate": 300, + "cameraConfigVideoCodec": "libx264", + "cameraConfigAudioCodec": "libfdk_aac", + "cameraConfigAudio": false, + "cameraConfigPacketSize": 1316, + "cameraConfigVerticalFlip": false, + "cameraConfigHorizontalFlip": false, + "cameraConfigMapVideo": "0:0", + "cameraConfigMapAudio": "0:1", + "cameraConfigVideoFilter": "scale=1280:720", + "cameraConfigAdditionalCommandLine": "-tune zerolatency", + "cameraConfigDebug": false, + "cameraConfigSnapshotOutput": "disabled", + "cameraConfigInterfaceName": "", + "characteristicProperties": "{\n \"StatusTampered\":true,\n \"StatusLowBattery\":true\n}", + "outputs": 2, + "x": 660, + "y": 1400, + "wires": [[], []] + }, + { + "id": "2f9bc0d.42a73c", + "type": "inject", + "z": "60b06629.a2ebd", + "g": "a875cc7.a4c42b", + "name": "Tampered", + "repeat": "", + "crontab": "", + "once": false, + "onceDelay": 0.1, + "topic": "", + "payload": "{\"StatusTampered\":1}", + "payloadType": "json", + "x": 120, + "y": 1520, + "wires": [["a5194c26.18c628"]] + }, + { + "id": "dfca0b2d.8b8e8", + "type": "inject", + "z": "60b06629.a2ebd", + "g": "a875cc7.a4c42b", + "name": "Clear tampered", + "repeat": "", + "crontab": "", + "once": false, + "onceDelay": 0.1, + "topic": "", + "payload": "{\"StatusTampered\":0}", + "payloadType": "json", + "x": 140, + "y": 1560, + "wires": [["a5194c26.18c628"]] + }, + { + "id": "d74a610c.09a36", + "type": "inject", + "z": "60b06629.a2ebd", + "g": "a875cc7.a4c42b", + "name": "Low batt", + "repeat": "", + "crontab": "", + "once": false, + "onceDelay": 0.1, + "topic": "", + "payload": "{\"StatusLowBattery\":1}", + "payloadType": "json", + "x": 480, + "y": 1520, + "wires": [["a5194c26.18c628"]] + }, + { + "id": "c15b6468.ae2eb8", + "type": "inject", + "z": "60b06629.a2ebd", + "g": "a875cc7.a4c42b", + "name": "Good batt", + "repeat": "", + "crontab": "", + "once": false, + "onceDelay": 0.1, + "topic": "", + "payload": "{\"StatusLowBattery\":0}", + "payloadType": "json", + "x": 480, + "y": 1560, + "wires": [["a5194c26.18c628"]] + }, + { + "id": "6f7bc7fa.7f4f6", + "type": "inject", + "z": "60b06629.a2ebd", + "g": "a875cc7.a4c42b", + "name": "NO RESPONSE", + "props": [ + { + "p": "payload" + }, + { + "p": "topic", + "vt": "str" + } + ], + "repeat": "", + "crontab": "", + "once": false, + "onceDelay": 0.1, + "topic": "", + "payload": "{\"ContactSensorState\":\"NO_RESPONSE\"}", + "payloadType": "json", + "x": 140, + "y": 1460, + "wires": [["a5194c26.18c628"]] + }, + { + "id": "99b55eb3.e31bf8", + "type": "trigger", + "z": "60b06629.a2ebd", + "g": "a875cc7.a4c42b", + "name": "10 Sec open", + "op1": "", + "op2": "{\"ContactSensorState\":0}", + "op1type": "pay", + "op2type": "json", + "duration": "10", + "extend": false, + "units": "s", + "reset": "", + "bytopic": "all", + "topic": "topic", + "outputs": 1, + "x": 350, + "y": 1400, + "wires": [["a5194c26.18c628"]] + }, + { + "id": "508d9ccf.29e404", + "type": "inject", + "z": "60b06629.a2ebd", + "g": "a875cc7.a4c42b", + "name": "Open", + "props": [ + { + "p": "payload" + }, + { + "p": "topic", + "vt": "str" + } + ], + "repeat": "", + "crontab": "", + "once": false, + "onceDelay": "1", + "topic": "", + "payload": "{\"ContactSensorState\":1}", + "payloadType": "json", + "x": 110, + "y": 1400, + "wires": [["99b55eb3.e31bf8"]] + }, + { + "id": "409001a1.3e7a78", + "type": "homekit-bridge", + "z": "", + "bridgeName": "Demo 1", + "pinCode": "153-10-538", + "port": "", + "allowInsecureRequest": false, + "manufacturer": "NRCHKB", + "model": "Demo", + "serialNo": "1.1.2", + "customMdnsConfig": false, + "mdnsMulticast": true, + "mdnsInterface": "", + "mdnsPort": "", + "mdnsIp": "", + "mdnsTtl": "", + "mdnsLoopback": true, + "mdnsReuseAddr": true, + "allowMessagePassthrough": true + } ] diff --git a/examples/demos (advanced)/01 - Television with inputs and speaker.json b/examples/demos (advanced)/01 - Television with inputs and speaker.json index a2d0238c..ed6d432e 100644 --- a/examples/demos (advanced)/01 - Television with inputs and speaker.json +++ b/examples/demos (advanced)/01 - Television with inputs and speaker.json @@ -1,611 +1,545 @@ [ - { - "id": "a98abda4.5784d", - "type": "group", - "z": "21f36bce.02d864", - "name": "Television: input from device, output to device", - "style": { - "stroke": "#999999", - "fill": "none", - "label": true, - "label-position": "nw", - "color": "#a4a4a4" - }, - "nodes": [ - "894d3458.2f07d", - "87183aa8.418ec", - "519fe2f2.b4870c", - "5de4624c.b2aeac", - "d5812842.bebac", - "ac7b78f3.2b9328", - "1d662593.e8434a", - "405055ca.02f2dc", - "f164c3c9.de75e8", - "d35fba0b.560e68", - "da9f0bd6.b2bbf", - "b4c4b8b.fc331c8", - "56282414.102184", - "f83a84cb.08b19" - ], - "x": 14, - "y": 59, - "w": 932, - "h": 488, - "info": "## Example With Speaker and 4 inputs\n\nThis example will show a television service with 4 inputs and a speaker (volume control). There are two functions that should be used to name your specific devices. These functions are `Setup TV` and `Setup Inputs`.\n\n**Setup TV:**\nThis function will be run 5 seconds after startup or whenever the `TV Setup` inject node is triggered. Change the name on line 1 of the function. The output message is sent to the Television Service to initialize the name and set the TV to `{\"Active\":0}` (TV off).\n\n**Setup Inputs:**\nThis function will be run 6 seconds after startup or whenever the `Source Setup` inject node is triggered. The following variables are available:\n* Lines 5 through 8 will name your sources\n* Lines 24 through 27 will set the input type according to the values in lines 11 through 21\n\n## Setting the HomeKit item based on TV state\n\nThere are various `inject` nodes which can be used to send information from your television ([Vizio API](https://github.com/exiva/Vizio_SmartCast_API), [Onkyo device](https://github.com/estbeetoo/node-red-contrib-eiscp), [Samsung TV](https://github.com/Toxblh/node-red-contrib-samsung-tv-control), [LG TV](https://github.com/hobbyquaker/node-red-contrib-lgtv), etc). It is up to you as the user to set this up according to your hardware. Use the provided `inject` nodes as a template to begin understanding the payloads expected by the Television Service.\n\nPlease note that the Television Speaker and Input Source service items **DO NOT** receive any input after initial configuration.\n\n## Setting TV state based on HomeKit output\n\nThere are two debug nodes provided. These can be used as examples of the output coming from HomeKit nodes to set up your system accordingly.\n\nThe `State and source output` debug node will output the following payloads:\n* `{\"Active\":0/1}` for TV state off/on\n* `{\"Input\":0-3}` for changing inputs from HomeKit\n* `{\"RemoteKey\":various}` for various integers when using the control center remote\n\n\nThe `Volume output` debug node will output the following payloads:\n* `{\"VolumeSelector\":0}` when control center remote press is \"Increase Volume\"\n* `{\"VolumeSelector\":1}` when control center remote press is \"Decrease Volume\"\n\nThe Input Source services will output payloads like `{\"ConfiguredName\":\"Name\"}` if the name is changed from HomeKit. If you would like to change your input names from within HomeKit rather than the `Set up inputs` function, it can be done but is beyond the scope of this example.\n" + { + "id": "a98abda4.5784d", + "type": "group", + "z": "21f36bce.02d864", + "name": "Television: input from device, output to device", + "style": { + "stroke": "#999999", + "fill": "none", + "label": true, + "label-position": "nw", + "color": "#a4a4a4" }, - { - "id": "894d3458.2f07d", - "type": "inject", - "z": "21f36bce.02d864", - "g": "a98abda4.5784d", - "name": "TV on", - "repeat": "", - "crontab": "", - "once": false, - "onceDelay": 0.1, - "topic": "", - "payload": "{\"Active\":1}", - "payloadType": "json", - "x": 110, - "y": 160, - "wires": [ - [ - "56282414.102184" - ] - ] + "nodes": [ + "894d3458.2f07d", + "87183aa8.418ec", + "519fe2f2.b4870c", + "5de4624c.b2aeac", + "d5812842.bebac", + "ac7b78f3.2b9328", + "1d662593.e8434a", + "405055ca.02f2dc", + "f164c3c9.de75e8", + "d35fba0b.560e68", + "da9f0bd6.b2bbf", + "b4c4b8b.fc331c8", + "56282414.102184", + "f83a84cb.08b19" + ], + "x": 14, + "y": 59, + "w": 932, + "h": 488, + "info": "## Example With Speaker and 4 inputs\n\nThis example will show a television service with 4 inputs and a speaker (volume control). There are two functions that should be used to name your specific devices. These functions are `Setup TV` and `Setup Inputs`.\n\n**Setup TV:**\nThis function will be run 5 seconds after startup or whenever the `TV Setup` inject node is triggered. Change the name on line 1 of the function. The output message is sent to the Television Service to initialize the name and set the TV to `{\"Active\":0}` (TV off).\n\n**Setup Inputs:**\nThis function will be run 6 seconds after startup or whenever the `Source Setup` inject node is triggered. The following variables are available:\n* Lines 5 through 8 will name your sources\n* Lines 24 through 27 will set the input type according to the values in lines 11 through 21\n\n## Setting the HomeKit item based on TV state\n\nThere are various `inject` nodes which can be used to send information from your television ([Vizio API](https://github.com/exiva/Vizio_SmartCast_API), [Onkyo device](https://github.com/estbeetoo/node-red-contrib-eiscp), [Samsung TV](https://github.com/Toxblh/node-red-contrib-samsung-tv-control), [LG TV](https://github.com/hobbyquaker/node-red-contrib-lgtv), etc). It is up to you as the user to set this up according to your hardware. Use the provided `inject` nodes as a template to begin understanding the payloads expected by the Television Service.\n\nPlease note that the Television Speaker and Input Source service items **DO NOT** receive any input after initial configuration.\n\n## Setting TV state based on HomeKit output\n\nThere are two debug nodes provided. These can be used as examples of the output coming from HomeKit nodes to set up your system accordingly.\n\nThe `State and source output` debug node will output the following payloads:\n* `{\"Active\":0/1}` for TV state off/on\n* `{\"Input\":0-3}` for changing inputs from HomeKit\n* `{\"RemoteKey\":various}` for various integers when using the control center remote\n\n\nThe `Volume output` debug node will output the following payloads:\n* `{\"VolumeSelector\":0}` when control center remote press is \"Increase Volume\"\n* `{\"VolumeSelector\":1}` when control center remote press is \"Decrease Volume\"\n\nThe Input Source services will output payloads like `{\"ConfiguredName\":\"Name\"}` if the name is changed from HomeKit. If you would like to change your input names from within HomeKit rather than the `Set up inputs` function, it can be done but is beyond the scope of this example.\n" + }, + { + "id": "894d3458.2f07d", + "type": "inject", + "z": "21f36bce.02d864", + "g": "a98abda4.5784d", + "name": "TV on", + "repeat": "", + "crontab": "", + "once": false, + "onceDelay": 0.1, + "topic": "", + "payload": "{\"Active\":1}", + "payloadType": "json", + "x": 110, + "y": 160, + "wires": [["56282414.102184"]] + }, + { + "id": "87183aa8.418ec", + "type": "inject", + "z": "21f36bce.02d864", + "g": "a98abda4.5784d", + "name": "TV off", + "repeat": "", + "crontab": "", + "once": false, + "onceDelay": 0.1, + "topic": "", + "payload": "{\"Active\":0}", + "payloadType": "json", + "x": 110, + "y": 200, + "wires": [["56282414.102184"]] + }, + { + "id": "519fe2f2.b4870c", + "type": "debug", + "z": "21f36bce.02d864", + "g": "a98abda4.5784d", + "name": "State and source output", + "active": true, + "tosidebar": true, + "console": false, + "tostatus": false, + "complete": "payload", + "targetType": "msg", + "x": 790, + "y": 140, + "wires": [] + }, + { + "id": "5de4624c.b2aeac", + "type": "debug", + "z": "21f36bce.02d864", + "g": "a98abda4.5784d", + "name": "Volume output", + "active": true, + "tosidebar": true, + "console": false, + "tostatus": false, + "complete": "payload", + "targetType": "msg", + "statusVal": "", + "statusType": "auto", + "x": 800, + "y": 220, + "wires": [] + }, + { + "id": "d5812842.bebac", + "type": "inject", + "z": "21f36bce.02d864", + "g": "a98abda4.5784d", + "name": "TV Setup", + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": "5", + "topic": "", + "payload": "", + "payloadType": "date", + "x": 120, + "y": 100, + "wires": [["1d662593.e8434a"]] + }, + { + "id": "ac7b78f3.2b9328", + "type": "inject", + "z": "21f36bce.02d864", + "g": "a98abda4.5784d", + "name": "Source Setup", + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": "6", + "topic": "", + "payload": "", + "payloadType": "date", + "x": 140, + "y": 480, + "wires": [["b4c4b8b.fc331c8"]] + }, + { + "id": "1d662593.e8434a", + "type": "function", + "z": "21f36bce.02d864", + "g": "a98abda4.5784d", + "name": "Setup TV", + "func": "var name = \"Television\";\n\nmsg.payload = {\n \"ConfiguredName\": name,\n \"ActiveIdentifier\" : 0,\n \"SleepDiscoveryMode\" : 0,\n \"Active\" : 0\n};\nreturn msg;", + "outputs": 1, + "noerr": 0, + "x": 300, + "y": 100, + "wires": [["56282414.102184"]] + }, + { + "id": "405055ca.02f2dc", + "type": "inject", + "z": "21f36bce.02d864", + "g": "a98abda4.5784d", + "name": "Input 1", + "repeat": "", + "crontab": "", + "once": false, + "onceDelay": 0.1, + "topic": "", + "payload": "{\"ActiveIdentifier\":1}", + "payloadType": "json", + "x": 110, + "y": 320, + "wires": [["56282414.102184"]] + }, + { + "id": "f164c3c9.de75e8", + "type": "inject", + "z": "21f36bce.02d864", + "g": "a98abda4.5784d", + "name": "Input 0", + "repeat": "", + "crontab": "", + "once": false, + "onceDelay": 0.1, + "topic": "", + "payload": "{\"ActiveIdentifier\":0}", + "payloadType": "json", + "x": 110, + "y": 280, + "wires": [["56282414.102184"]] + }, + { + "id": "d35fba0b.560e68", + "type": "inject", + "z": "21f36bce.02d864", + "g": "a98abda4.5784d", + "name": "Input 2", + "repeat": "", + "crontab": "", + "once": false, + "onceDelay": 0.1, + "topic": "", + "payload": "{\"ActiveIdentifier\":2}", + "payloadType": "json", + "x": 110, + "y": 360, + "wires": [["56282414.102184"]] + }, + { + "id": "da9f0bd6.b2bbf", + "type": "inject", + "z": "21f36bce.02d864", + "g": "a98abda4.5784d", + "name": "Input 3", + "repeat": "", + "crontab": "", + "once": false, + "onceDelay": 0.1, + "topic": "", + "payload": "{\"ActiveIdentifier\":3}", + "payloadType": "json", + "x": 110, + "y": 400, + "wires": [["56282414.102184"]] + }, + { + "id": "b4c4b8b.fc331c8", + "type": "function", + "z": "21f36bce.02d864", + "g": "a98abda4.5784d", + "name": "Set up inputs", + "func": "// This function will initialize and name inputs\n// it is set to work with 4 inputs\n\n// INPUT SOURCE NAMES\nvar input0 = \"HDMI 1\";\nvar input1 = \"HDMI 2\";\nvar input2 = \"Apple TV\";\nvar input3 = \"Wii U\";\n\n// INPUT SOURCE TYPES\nvar OTHER = 0;\nvar HOME_SCREEN = 1;\nvar TUNER = 2;\nvar HDMI = 3;\nvar COMPOSITE_VIDEO = 4;\nvar S_VIDEO = 5;\nvar COMPONENT_VIDEO = 6;\nvar DVI = 7;\nvar AIRPLAY = 8;\nvar USB = 9;\nvar APPLICATION = 10;\n\n// Configure your input types based on options above\nvar input0type = HDMI;\nvar input1type = HDMI;\nvar input2type = HDMI;\nvar input3type = COMPOSITE_VIDEO;\n\n\n// Duplicate or remove sets if you have more or fewer inputs\nvar msg0={};\nvar msg1={};\nvar msg2={};\nvar msg3={};\n\nmsg0.payload = {\n \"Identifier\": 0,\n \"IsConfigured\" : 1,\n \"ConfiguredName\": input0,\n \"InputSourceType\": input0type\n};\nmsg1.payload = {\n \"Identifier\": 1,\n \"IsConfigured\" : 1,\n \"ConfiguredName\": input1,\n \"InputSourceType\": input1type\n};\nmsg2.payload = {\n \"Identifier\": 2,\n \"IsConfigured\" : 1,\n \"ConfiguredName\": input2,\n \"InputSourceType\": input2type\n};\nmsg3.payload = {\n \"Identifier\": 3,\n \"IsConfigured\" : 1,\n \"ConfiguredName\" : input3,\n \"InputSourceType\" : input3type\n};\nreturn [msg0,msg1,msg2,msg3];", + "outputs": 4, + "noerr": 0, + "x": 330, + "y": 460, + "wires": [ + ["cb312294.a7f498"], + ["28645f7e.68e9b"], + ["3a8efd21.5d57c2"], + ["4c751d1f.e9a014"] + ] + }, + { + "id": "56282414.102184", + "type": "homekit-service", + "z": "21f36bce.02d864", + "g": "a98abda4.5784d", + "isParent": true, + "bridge": "5257174b.4307a8", + "parentService": "", + "name": "Television Example", + "serviceName": "Television", + "topic": "", + "filter": false, + "manufacturer": "Default Manufacturer", + "model": "Default Model", + "serialNo": "Default Serial Number", + "firmwareRev": "", + "hardwareRev": "", + "cameraConfigVideoProcessor": "ffmpeg", + "cameraConfigSource": "", + "cameraConfigStillImageSource": "", + "cameraConfigMaxStreams": 2, + "cameraConfigMaxWidth": 1280, + "cameraConfigMaxHeight": 720, + "cameraConfigMaxFPS": 10, + "cameraConfigMaxBitrate": 300, + "cameraConfigVideoCodec": "libx264", + "cameraConfigAudioCodec": "libfdk_aac", + "cameraConfigAudio": false, + "cameraConfigPacketSize": 1316, + "cameraConfigVerticalFlip": false, + "cameraConfigHorizontalFlip": false, + "cameraConfigMapVideo": "0:0", + "cameraConfigMapAudio": "0:1", + "cameraConfigVideoFilter": "scale=1280:720", + "cameraConfigAdditionalCommandLine": "-tune zerolatency", + "cameraConfigDebug": false, + "cameraConfigSnapshotOutput": "disabled", + "cameraConfigInterfaceName": "", + "characteristicProperties": "{\n \"RemoteKey\":null\n}", + "outputs": 2, + "x": 530, + "y": 140, + "wires": [[], ["519fe2f2.b4870c"]] + }, + { + "id": "f83a84cb.08b19", + "type": "group", + "z": "21f36bce.02d864", + "g": "a98abda4.5784d", + "name": "Linked services", + "style": { + "stroke": "#0070c0", + "fill": "#bfdbef", + "label": true }, - { - "id": "87183aa8.418ec", - "type": "inject", - "z": "21f36bce.02d864", - "g": "a98abda4.5784d", - "name": "TV off", - "repeat": "", - "crontab": "", - "once": false, - "onceDelay": 0.1, - "topic": "", - "payload": "{\"Active\":0}", - "payloadType": "json", - "x": 110, - "y": 200, - "wires": [ - [ - "56282414.102184" - ] - ] - }, - { - "id": "519fe2f2.b4870c", - "type": "debug", - "z": "21f36bce.02d864", - "g": "a98abda4.5784d", - "name": "State and source output", - "active": true, - "tosidebar": true, - "console": false, - "tostatus": false, - "complete": "payload", - "targetType": "msg", - "x": 790, - "y": 140, - "wires": [] - }, - { - "id": "5de4624c.b2aeac", - "type": "debug", - "z": "21f36bce.02d864", - "g": "a98abda4.5784d", - "name": "Volume output", - "active": true, - "tosidebar": true, - "console": false, - "tostatus": false, - "complete": "payload", - "targetType": "msg", - "statusVal": "", - "statusType": "auto", - "x": 800, - "y": 220, - "wires": [] - }, - { - "id": "d5812842.bebac", - "type": "inject", - "z": "21f36bce.02d864", - "g": "a98abda4.5784d", - "name": "TV Setup", - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": "5", - "topic": "", - "payload": "", - "payloadType": "date", - "x": 120, - "y": 100, - "wires": [ - [ - "1d662593.e8434a" - ] - ] - }, - { - "id": "ac7b78f3.2b9328", - "type": "inject", - "z": "21f36bce.02d864", - "g": "a98abda4.5784d", - "name": "Source Setup", - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": "6", - "topic": "", - "payload": "", - "payloadType": "date", - "x": 140, - "y": 480, - "wires": [ - [ - "b4c4b8b.fc331c8" - ] - ] - }, - { - "id": "1d662593.e8434a", - "type": "function", - "z": "21f36bce.02d864", - "g": "a98abda4.5784d", - "name": "Setup TV", - "func": "var name = \"Television\";\n\nmsg.payload = {\n \"ConfiguredName\": name,\n \"ActiveIdentifier\" : 0,\n \"SleepDiscoveryMode\" : 0,\n \"Active\" : 0\n};\nreturn msg;", - "outputs": 1, - "noerr": 0, - "x": 300, - "y": 100, - "wires": [ - [ - "56282414.102184" - ] - ] - }, - { - "id": "405055ca.02f2dc", - "type": "inject", - "z": "21f36bce.02d864", - "g": "a98abda4.5784d", - "name": "Input 1", - "repeat": "", - "crontab": "", - "once": false, - "onceDelay": 0.1, - "topic": "", - "payload": "{\"ActiveIdentifier\":1}", - "payloadType": "json", - "x": 110, - "y": 320, - "wires": [ - [ - "56282414.102184" - ] - ] - }, - { - "id": "f164c3c9.de75e8", - "type": "inject", - "z": "21f36bce.02d864", - "g": "a98abda4.5784d", - "name": "Input 0", - "repeat": "", - "crontab": "", - "once": false, - "onceDelay": 0.1, - "topic": "", - "payload": "{\"ActiveIdentifier\":0}", - "payloadType": "json", - "x": 110, - "y": 280, - "wires": [ - [ - "56282414.102184" - ] - ] - }, - { - "id": "d35fba0b.560e68", - "type": "inject", - "z": "21f36bce.02d864", - "g": "a98abda4.5784d", - "name": "Input 2", - "repeat": "", - "crontab": "", - "once": false, - "onceDelay": 0.1, - "topic": "", - "payload": "{\"ActiveIdentifier\":2}", - "payloadType": "json", - "x": 110, - "y": 360, - "wires": [ - [ - "56282414.102184" - ] - ] - }, - { - "id": "da9f0bd6.b2bbf", - "type": "inject", - "z": "21f36bce.02d864", - "g": "a98abda4.5784d", - "name": "Input 3", - "repeat": "", - "crontab": "", - "once": false, - "onceDelay": 0.1, - "topic": "", - "payload": "{\"ActiveIdentifier\":3}", - "payloadType": "json", - "x": 110, - "y": 400, - "wires": [ - [ - "56282414.102184" - ] - ] - }, - { - "id": "b4c4b8b.fc331c8", - "type": "function", - "z": "21f36bce.02d864", - "g": "a98abda4.5784d", - "name": "Set up inputs", - "func": "// This function will initialize and name inputs\n// it is set to work with 4 inputs\n\n// INPUT SOURCE NAMES\nvar input0 = \"HDMI 1\";\nvar input1 = \"HDMI 2\";\nvar input2 = \"Apple TV\";\nvar input3 = \"Wii U\";\n\n// INPUT SOURCE TYPES\nvar OTHER = 0;\nvar HOME_SCREEN = 1;\nvar TUNER = 2;\nvar HDMI = 3;\nvar COMPOSITE_VIDEO = 4;\nvar S_VIDEO = 5;\nvar COMPONENT_VIDEO = 6;\nvar DVI = 7;\nvar AIRPLAY = 8;\nvar USB = 9;\nvar APPLICATION = 10;\n\n// Configure your input types based on options above\nvar input0type = HDMI;\nvar input1type = HDMI;\nvar input2type = HDMI;\nvar input3type = COMPOSITE_VIDEO;\n\n\n// Duplicate or remove sets if you have more or fewer inputs\nvar msg0={};\nvar msg1={};\nvar msg2={};\nvar msg3={};\n\nmsg0.payload = {\n \"Identifier\": 0,\n \"IsConfigured\" : 1,\n \"ConfiguredName\": input0,\n \"InputSourceType\": input0type\n};\nmsg1.payload = {\n \"Identifier\": 1,\n \"IsConfigured\" : 1,\n \"ConfiguredName\": input1,\n \"InputSourceType\": input1type\n};\nmsg2.payload = {\n \"Identifier\": 2,\n \"IsConfigured\" : 1,\n \"ConfiguredName\": input2,\n \"InputSourceType\": input2type\n};\nmsg3.payload = {\n \"Identifier\": 3,\n \"IsConfigured\" : 1,\n \"ConfiguredName\" : input3,\n \"InputSourceType\" : input3type\n};\nreturn [msg0,msg1,msg2,msg3];", - "outputs": 4, - "noerr": 0, - "x": 330, - "y": 460, - "wires": [ - [ - "cb312294.a7f498" - ], - [ - "28645f7e.68e9b" - ], - [ - "3a8efd21.5d57c2" - ], - [ - "4c751d1f.e9a014" - ] - ] - }, - { - "id": "56282414.102184", - "type": "homekit-service", - "z": "21f36bce.02d864", - "g": "a98abda4.5784d", - "isParent": true, - "bridge": "5257174b.4307a8", - "parentService": "", - "name": "Television Example", - "serviceName": "Television", - "topic": "", - "filter": false, - "manufacturer": "Default Manufacturer", - "model": "Default Model", - "serialNo": "Default Serial Number", - "firmwareRev": "", - "hardwareRev": "", - "cameraConfigVideoProcessor": "ffmpeg", - "cameraConfigSource": "", - "cameraConfigStillImageSource": "", - "cameraConfigMaxStreams": 2, - "cameraConfigMaxWidth": 1280, - "cameraConfigMaxHeight": 720, - "cameraConfigMaxFPS": 10, - "cameraConfigMaxBitrate": 300, - "cameraConfigVideoCodec": "libx264", - "cameraConfigAudioCodec": "libfdk_aac", - "cameraConfigAudio": false, - "cameraConfigPacketSize": 1316, - "cameraConfigVerticalFlip": false, - "cameraConfigHorizontalFlip": false, - "cameraConfigMapVideo": "0:0", - "cameraConfigMapAudio": "0:1", - "cameraConfigVideoFilter": "scale=1280:720", - "cameraConfigAdditionalCommandLine": "-tune zerolatency", - "cameraConfigDebug": false, - "cameraConfigSnapshotOutput": "disabled", - "cameraConfigInterfaceName": "", - "characteristicProperties": "{\n \"RemoteKey\":null\n}", - "outputs": 2, - "x": 530, - "y": 140, - "wires": [ - [], - [ - "519fe2f2.b4870c" - ] - ] - }, - { - "id": "f83a84cb.08b19", - "type": "group", - "z": "21f36bce.02d864", - "g": "a98abda4.5784d", - "name": "Linked services", - "style": { - "stroke": "#0070c0", - "fill": "#bfdbef", - "label": true - }, - "nodes": [ - "1b32678b.2eedf", - "cb312294.a7f498", - "28645f7e.68e9b", - "3a8efd21.5d57c2", - "4c751d1f.e9a014" - ], - "x": 434, - "y": 179, - "w": 232, - "h": 342 - }, - { - "id": "1b32678b.2eedf", - "type": "homekit-service", - "z": "21f36bce.02d864", - "g": "f83a84cb.08b19", - "isParent": false, - "bridge": "5257174b.4307a8", - "parentService": "56282414.102184", - "name": "Television Speaker", - "serviceName": "TelevisionSpeaker", - "topic": "Television Example", - "filter": false, - "manufacturer": "Default Manufacturer", - "model": "Default Model", - "serialNo": "Default Serial Number", - "firmwareRev": "", - "hardwareRev": "", - "cameraConfigVideoProcessor": "ffmpeg", - "cameraConfigSource": "", - "cameraConfigStillImageSource": "", - "cameraConfigMaxStreams": 2, - "cameraConfigMaxWidth": 1280, - "cameraConfigMaxHeight": 720, - "cameraConfigMaxFPS": 10, - "cameraConfigMaxBitrate": 300, - "cameraConfigVideoCodec": "libx264", - "cameraConfigAudioCodec": "libfdk_aac", - "cameraConfigAudio": false, - "cameraConfigPacketSize": 1316, - "cameraConfigVerticalFlip": false, - "cameraConfigHorizontalFlip": false, - "cameraConfigMapVideo": "0:0", - "cameraConfigMapAudio": "0:1", - "cameraConfigVideoFilter": "scale=1280:720", - "cameraConfigAdditionalCommandLine": "-tune zerolatency", - "cameraConfigDebug": false, - "cameraConfigSnapshotOutput": "disabled", - "cameraConfigInterfaceName": "", - "characteristicProperties": "{\n \"VolumeControlType\":1,\n \"VolumeSelector\":true\n}", - "outputs": 2, - "x": 550, - "y": 220, - "wires": [ - [], - [ - "5de4624c.b2aeac" - ] - ] - }, - { - "id": "cb312294.a7f498", - "type": "homekit-service", - "z": "21f36bce.02d864", - "g": "f83a84cb.08b19", - "isParent": false, - "bridge": "", - "parentService": "56282414.102184", - "name": "Input 0", - "serviceName": "InputSource", - "topic": "Television Example", - "filter": false, - "manufacturer": "Default Manufacturer", - "model": "Default Model", - "serialNo": "Default Serial Number", - "firmwareRev": "", - "hardwareRev": "", - "cameraConfigVideoProcessor": "ffmpeg", - "cameraConfigSource": "", - "cameraConfigStillImageSource": "", - "cameraConfigMaxStreams": 2, - "cameraConfigMaxWidth": 1280, - "cameraConfigMaxHeight": 720, - "cameraConfigMaxFPS": 10, - "cameraConfigMaxBitrate": 300, - "cameraConfigVideoCodec": "libx264", - "cameraConfigAudioCodec": "libfdk_aac", - "cameraConfigAudio": false, - "cameraConfigPacketSize": 1316, - "cameraConfigVerticalFlip": false, - "cameraConfigHorizontalFlip": false, - "cameraConfigMapVideo": "0:0", - "cameraConfigMapAudio": "0:1", - "cameraConfigVideoFilter": "scale=1280:720", - "cameraConfigAdditionalCommandLine": "-tune zerolatency", - "cameraConfigDebug": false, - "cameraConfigSnapshotOutput": "disabled", - "cameraConfigInterfaceName": "", - "characteristicProperties": "{}", - "outputs": 2, - "x": 580, - "y": 300, - "wires": [ - [], - [] - ] - }, - { - "id": "28645f7e.68e9b", - "type": "homekit-service", - "z": "21f36bce.02d864", - "g": "f83a84cb.08b19", - "isParent": false, - "bridge": "", - "parentService": "56282414.102184", - "name": "Input 1", - "serviceName": "InputSource", - "topic": "Television Example", - "filter": false, - "manufacturer": "Default Manufacturer", - "model": "Default Model", - "serialNo": "Default Serial Number", - "firmwareRev": "", - "hardwareRev": "", - "cameraConfigVideoProcessor": "ffmpeg", - "cameraConfigSource": "", - "cameraConfigStillImageSource": "", - "cameraConfigMaxStreams": 2, - "cameraConfigMaxWidth": 1280, - "cameraConfigMaxHeight": 720, - "cameraConfigMaxFPS": 10, - "cameraConfigMaxBitrate": 300, - "cameraConfigVideoCodec": "libx264", - "cameraConfigAudioCodec": "libfdk_aac", - "cameraConfigAudio": false, - "cameraConfigPacketSize": 1316, - "cameraConfigVerticalFlip": false, - "cameraConfigHorizontalFlip": false, - "cameraConfigMapVideo": "0:0", - "cameraConfigMapAudio": "0:1", - "cameraConfigVideoFilter": "scale=1280:720", - "cameraConfigAdditionalCommandLine": "-tune zerolatency", - "cameraConfigDebug": false, - "cameraConfigSnapshotOutput": "disabled", - "cameraConfigInterfaceName": "", - "characteristicProperties": "{}", - "outputs": 2, - "x": 580, - "y": 360, - "wires": [ - [], - [] - ] - }, - { - "id": "3a8efd21.5d57c2", - "type": "homekit-service", - "z": "21f36bce.02d864", - "g": "f83a84cb.08b19", - "isParent": false, - "bridge": "", - "parentService": "56282414.102184", - "name": "Input 2", - "serviceName": "InputSource", - "topic": "Television Example", - "filter": false, - "manufacturer": "Default Manufacturer", - "model": "Default Model", - "serialNo": "Default Serial Number", - "firmwareRev": "", - "hardwareRev": "", - "cameraConfigVideoProcessor": "ffmpeg", - "cameraConfigSource": "", - "cameraConfigStillImageSource": "", - "cameraConfigMaxStreams": 2, - "cameraConfigMaxWidth": 1280, - "cameraConfigMaxHeight": 720, - "cameraConfigMaxFPS": 10, - "cameraConfigMaxBitrate": 300, - "cameraConfigVideoCodec": "libx264", - "cameraConfigAudioCodec": "libfdk_aac", - "cameraConfigAudio": false, - "cameraConfigPacketSize": 1316, - "cameraConfigVerticalFlip": false, - "cameraConfigHorizontalFlip": false, - "cameraConfigMapVideo": "0:0", - "cameraConfigMapAudio": "0:1", - "cameraConfigVideoFilter": "scale=1280:720", - "cameraConfigAdditionalCommandLine": "-tune zerolatency", - "cameraConfigDebug": false, - "cameraConfigSnapshotOutput": "disabled", - "cameraConfigInterfaceName": "", - "characteristicProperties": "{}", - "outputs": 2, - "x": 580, - "y": 420, - "wires": [ - [], - [] - ] - }, - { - "id": "4c751d1f.e9a014", - "type": "homekit-service", - "z": "21f36bce.02d864", - "g": "f83a84cb.08b19", - "isParent": false, - "bridge": "", - "parentService": "56282414.102184", - "name": "Input 3", - "serviceName": "InputSource", - "topic": "Television Example", - "filter": false, - "manufacturer": "Default Manufacturer", - "model": "Default Model", - "serialNo": "Default Serial Number", - "firmwareRev": "", - "hardwareRev": "", - "cameraConfigVideoProcessor": "ffmpeg", - "cameraConfigSource": "", - "cameraConfigStillImageSource": "", - "cameraConfigMaxStreams": 2, - "cameraConfigMaxWidth": 1280, - "cameraConfigMaxHeight": 720, - "cameraConfigMaxFPS": 10, - "cameraConfigMaxBitrate": 300, - "cameraConfigVideoCodec": "libx264", - "cameraConfigAudioCodec": "libfdk_aac", - "cameraConfigAudio": false, - "cameraConfigPacketSize": 1316, - "cameraConfigVerticalFlip": false, - "cameraConfigHorizontalFlip": false, - "cameraConfigMapVideo": "0:0", - "cameraConfigMapAudio": "0:1", - "cameraConfigVideoFilter": "scale=1280:720", - "cameraConfigAdditionalCommandLine": "-tune zerolatency", - "cameraConfigDebug": false, - "cameraConfigSnapshotOutput": "disabled", - "cameraConfigInterfaceName": "", - "characteristicProperties": "{}", - "outputs": 2, - "x": 580, - "y": 480, - "wires": [ - [], - [] - ] - }, - { - "id": "5257174b.4307a8", - "type": "homekit-bridge", - "z": "", - "bridgeName": "Demo TV", - "pinCode": "111-11-111", - "port": "", - "allowInsecureRequest": false, - "manufacturer": "NRCHKB", - "model": "Demo", - "serialNo": "1.1.2", - "customMdnsConfig": false, - "mdnsMulticast": true, - "mdnsInterface": "", - "mdnsPort": "", - "mdnsIp": "", - "mdnsTtl": "", - "mdnsLoopback": true, - "mdnsReuseAddr": true, - "allowMessagePassthrough": false - } + "nodes": [ + "1b32678b.2eedf", + "cb312294.a7f498", + "28645f7e.68e9b", + "3a8efd21.5d57c2", + "4c751d1f.e9a014" + ], + "x": 434, + "y": 179, + "w": 232, + "h": 342 + }, + { + "id": "1b32678b.2eedf", + "type": "homekit-service", + "z": "21f36bce.02d864", + "g": "f83a84cb.08b19", + "isParent": false, + "bridge": "5257174b.4307a8", + "parentService": "56282414.102184", + "name": "Television Speaker", + "serviceName": "TelevisionSpeaker", + "topic": "Television Example", + "filter": false, + "manufacturer": "Default Manufacturer", + "model": "Default Model", + "serialNo": "Default Serial Number", + "firmwareRev": "", + "hardwareRev": "", + "cameraConfigVideoProcessor": "ffmpeg", + "cameraConfigSource": "", + "cameraConfigStillImageSource": "", + "cameraConfigMaxStreams": 2, + "cameraConfigMaxWidth": 1280, + "cameraConfigMaxHeight": 720, + "cameraConfigMaxFPS": 10, + "cameraConfigMaxBitrate": 300, + "cameraConfigVideoCodec": "libx264", + "cameraConfigAudioCodec": "libfdk_aac", + "cameraConfigAudio": false, + "cameraConfigPacketSize": 1316, + "cameraConfigVerticalFlip": false, + "cameraConfigHorizontalFlip": false, + "cameraConfigMapVideo": "0:0", + "cameraConfigMapAudio": "0:1", + "cameraConfigVideoFilter": "scale=1280:720", + "cameraConfigAdditionalCommandLine": "-tune zerolatency", + "cameraConfigDebug": false, + "cameraConfigSnapshotOutput": "disabled", + "cameraConfigInterfaceName": "", + "characteristicProperties": "{\n \"VolumeControlType\":1,\n \"VolumeSelector\":true\n}", + "outputs": 2, + "x": 550, + "y": 220, + "wires": [[], ["5de4624c.b2aeac"]] + }, + { + "id": "cb312294.a7f498", + "type": "homekit-service", + "z": "21f36bce.02d864", + "g": "f83a84cb.08b19", + "isParent": false, + "bridge": "", + "parentService": "56282414.102184", + "name": "Input 0", + "serviceName": "InputSource", + "topic": "Television Example", + "filter": false, + "manufacturer": "Default Manufacturer", + "model": "Default Model", + "serialNo": "Default Serial Number", + "firmwareRev": "", + "hardwareRev": "", + "cameraConfigVideoProcessor": "ffmpeg", + "cameraConfigSource": "", + "cameraConfigStillImageSource": "", + "cameraConfigMaxStreams": 2, + "cameraConfigMaxWidth": 1280, + "cameraConfigMaxHeight": 720, + "cameraConfigMaxFPS": 10, + "cameraConfigMaxBitrate": 300, + "cameraConfigVideoCodec": "libx264", + "cameraConfigAudioCodec": "libfdk_aac", + "cameraConfigAudio": false, + "cameraConfigPacketSize": 1316, + "cameraConfigVerticalFlip": false, + "cameraConfigHorizontalFlip": false, + "cameraConfigMapVideo": "0:0", + "cameraConfigMapAudio": "0:1", + "cameraConfigVideoFilter": "scale=1280:720", + "cameraConfigAdditionalCommandLine": "-tune zerolatency", + "cameraConfigDebug": false, + "cameraConfigSnapshotOutput": "disabled", + "cameraConfigInterfaceName": "", + "characteristicProperties": "{}", + "outputs": 2, + "x": 580, + "y": 300, + "wires": [[], []] + }, + { + "id": "28645f7e.68e9b", + "type": "homekit-service", + "z": "21f36bce.02d864", + "g": "f83a84cb.08b19", + "isParent": false, + "bridge": "", + "parentService": "56282414.102184", + "name": "Input 1", + "serviceName": "InputSource", + "topic": "Television Example", + "filter": false, + "manufacturer": "Default Manufacturer", + "model": "Default Model", + "serialNo": "Default Serial Number", + "firmwareRev": "", + "hardwareRev": "", + "cameraConfigVideoProcessor": "ffmpeg", + "cameraConfigSource": "", + "cameraConfigStillImageSource": "", + "cameraConfigMaxStreams": 2, + "cameraConfigMaxWidth": 1280, + "cameraConfigMaxHeight": 720, + "cameraConfigMaxFPS": 10, + "cameraConfigMaxBitrate": 300, + "cameraConfigVideoCodec": "libx264", + "cameraConfigAudioCodec": "libfdk_aac", + "cameraConfigAudio": false, + "cameraConfigPacketSize": 1316, + "cameraConfigVerticalFlip": false, + "cameraConfigHorizontalFlip": false, + "cameraConfigMapVideo": "0:0", + "cameraConfigMapAudio": "0:1", + "cameraConfigVideoFilter": "scale=1280:720", + "cameraConfigAdditionalCommandLine": "-tune zerolatency", + "cameraConfigDebug": false, + "cameraConfigSnapshotOutput": "disabled", + "cameraConfigInterfaceName": "", + "characteristicProperties": "{}", + "outputs": 2, + "x": 580, + "y": 360, + "wires": [[], []] + }, + { + "id": "3a8efd21.5d57c2", + "type": "homekit-service", + "z": "21f36bce.02d864", + "g": "f83a84cb.08b19", + "isParent": false, + "bridge": "", + "parentService": "56282414.102184", + "name": "Input 2", + "serviceName": "InputSource", + "topic": "Television Example", + "filter": false, + "manufacturer": "Default Manufacturer", + "model": "Default Model", + "serialNo": "Default Serial Number", + "firmwareRev": "", + "hardwareRev": "", + "cameraConfigVideoProcessor": "ffmpeg", + "cameraConfigSource": "", + "cameraConfigStillImageSource": "", + "cameraConfigMaxStreams": 2, + "cameraConfigMaxWidth": 1280, + "cameraConfigMaxHeight": 720, + "cameraConfigMaxFPS": 10, + "cameraConfigMaxBitrate": 300, + "cameraConfigVideoCodec": "libx264", + "cameraConfigAudioCodec": "libfdk_aac", + "cameraConfigAudio": false, + "cameraConfigPacketSize": 1316, + "cameraConfigVerticalFlip": false, + "cameraConfigHorizontalFlip": false, + "cameraConfigMapVideo": "0:0", + "cameraConfigMapAudio": "0:1", + "cameraConfigVideoFilter": "scale=1280:720", + "cameraConfigAdditionalCommandLine": "-tune zerolatency", + "cameraConfigDebug": false, + "cameraConfigSnapshotOutput": "disabled", + "cameraConfigInterfaceName": "", + "characteristicProperties": "{}", + "outputs": 2, + "x": 580, + "y": 420, + "wires": [[], []] + }, + { + "id": "4c751d1f.e9a014", + "type": "homekit-service", + "z": "21f36bce.02d864", + "g": "f83a84cb.08b19", + "isParent": false, + "bridge": "", + "parentService": "56282414.102184", + "name": "Input 3", + "serviceName": "InputSource", + "topic": "Television Example", + "filter": false, + "manufacturer": "Default Manufacturer", + "model": "Default Model", + "serialNo": "Default Serial Number", + "firmwareRev": "", + "hardwareRev": "", + "cameraConfigVideoProcessor": "ffmpeg", + "cameraConfigSource": "", + "cameraConfigStillImageSource": "", + "cameraConfigMaxStreams": 2, + "cameraConfigMaxWidth": 1280, + "cameraConfigMaxHeight": 720, + "cameraConfigMaxFPS": 10, + "cameraConfigMaxBitrate": 300, + "cameraConfigVideoCodec": "libx264", + "cameraConfigAudioCodec": "libfdk_aac", + "cameraConfigAudio": false, + "cameraConfigPacketSize": 1316, + "cameraConfigVerticalFlip": false, + "cameraConfigHorizontalFlip": false, + "cameraConfigMapVideo": "0:0", + "cameraConfigMapAudio": "0:1", + "cameraConfigVideoFilter": "scale=1280:720", + "cameraConfigAdditionalCommandLine": "-tune zerolatency", + "cameraConfigDebug": false, + "cameraConfigSnapshotOutput": "disabled", + "cameraConfigInterfaceName": "", + "characteristicProperties": "{}", + "outputs": 2, + "x": 580, + "y": 480, + "wires": [[], []] + }, + { + "id": "5257174b.4307a8", + "type": "homekit-bridge", + "z": "", + "bridgeName": "Demo TV", + "pinCode": "111-11-111", + "port": "", + "allowInsecureRequest": false, + "manufacturer": "NRCHKB", + "model": "Demo", + "serialNo": "1.1.2", + "customMdnsConfig": false, + "mdnsMulticast": true, + "mdnsInterface": "", + "mdnsPort": "", + "mdnsIp": "", + "mdnsTtl": "", + "mdnsLoopback": true, + "mdnsReuseAddr": true, + "allowMessagePassthrough": false + } ] diff --git a/examples/switch/01 - Plain Switch.json b/examples/switch/01 - Plain Switch.json index 4f44841c..5d966284 100644 --- a/examples/switch/01 - Plain Switch.json +++ b/examples/switch/01 - Plain Switch.json @@ -14,9 +14,7 @@ "style": { "label": true }, - "nodes": [ - "d6f9e9ce.b3af8" - ], + "nodes": ["d6f9e9ce.b3af8"], "x": 434, "y": 79, "w": 212, @@ -31,9 +29,7 @@ "stroke": "#ffC000", "label": true }, - "nodes": [ - "4ea13695.19871" - ], + "nodes": ["4ea13695.19871"], "x": 234, "y": 79, "w": 192, @@ -47,10 +43,7 @@ "style": { "label": true }, - "nodes": [ - "e02112b7.b761d", - "e9073d2c.84e64" - ], + "nodes": ["e02112b7.b761d", "e9073d2c.84e64"], "x": 54, "y": 59, "w": 172, @@ -99,12 +92,7 @@ "outputs": 2, "x": 330, "y": 120, - "wires": [ - [ - "d6f9e9ce.b3af8" - ], - [] - ] + "wires": [["d6f9e9ce.b3af8"], []] }, { "id": "d6f9e9ce.b3af8", @@ -144,11 +132,7 @@ "payloadType": "json", "x": 150, "y": 100, - "wires": [ - [ - "4ea13695.19871" - ] - ] + "wires": [["4ea13695.19871"]] }, { "id": "e9073d2c.84e64", @@ -170,11 +154,7 @@ "payloadType": "json", "x": 150, "y": 140, - "wires": [ - [ - "4ea13695.19871" - ] - ] + "wires": [["4ea13695.19871"]] }, { "id": "3dcda60a.e5ff12", @@ -200,4 +180,4 @@ "mdnsReuseAddr": true, "allowMessagePassthrough": true } -] \ No newline at end of file +] diff --git a/package-lock.json b/package-lock.json index af71cf03..6160aeee 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,9318 +1,7637 @@ { - "name": "node-red-contrib-homekit-bridged", - "version": "2.0.0-dev.1", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "node-red-contrib-homekit-bridged", - "version": "2.0.0-dev.1", - "license": "Apache-2.0", - "dependencies": { - "@homebridge/hap-nodejs": "2.0.2", - "@nrchkb/logger": "~3.1.1", - "node-persist": "^3.1.3", - "semver": "~7.7.3", - "uuid": "~13.0.0" - }, - "devDependencies": { - "@homebridge/ciao": "~1.3.4", - "@node-red/registry": "^4.1.1", - "@types/node": "^20", - "@types/node-persist": "^3.1.8", - "@types/node-red": "^1.3.5", - "@types/node-red-node-test-helper": "^0.3.5", - "@types/semver": "^7.7.1", - "@types/uuid": "^10.0.0", - "@typescript-eslint/eslint-plugin": "^7.16.0", - "@typescript-eslint/parser": "^7.16.0", - "babel-eslint": "^10.1.0", - "del-cli": "^7.0.0", - "eslint": "^8", - "eslint-config-prettier": "^9.1.0", - "eslint-plugin-prettier": "^5.5.4", - "eslint-plugin-simple-import-sort": "^12.1.1", - "husky": "^9.1.7", - "node-red": "^4.1.1", - "node-red-node-test-helper": "^0.3.5", - "prettier": "^3.6.2", - "ts-node": "^10.9.2", - "typescript": "^5.9.3", - "vitest": "^4.0.13" - }, - "engines": { - "node": "^20 || ^22 || ^24" - } - }, - "node_modules/@aashutoshrathi/word-wrap": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", - "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@babel/code-frame": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", - "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", - "dev": true, - "dependencies": { - "@babel/highlight": "^7.23.4", - "chalk": "^2.4.2" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/generator": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.6.tgz", - "integrity": "sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==", - "dev": true, - "dependencies": { - "@babel/types": "^7.23.6", - "@jridgewell/gen-mapping": "^0.3.2", - "@jridgewell/trace-mapping": "^0.3.17", - "jsesc": "^2.5.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-environment-visitor": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", - "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-function-name": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", - "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", - "dev": true, - "dependencies": { - "@babel/template": "^7.22.15", - "@babel/types": "^7.23.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-hoist-variables": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", - "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", - "dev": true, - "dependencies": { - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-split-export-declaration": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", - "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", - "dev": true, - "dependencies": { - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-string-parser": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz", - "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", - "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", - "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", - "dev": true, - "dependencies": { - "@babel/helper-validator-identifier": "^7.22.20", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/parser": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.6.tgz", - "integrity": "sha512-Z2uID7YJ7oNvAI20O9X0bblw7Qqs8Q2hFy0R9tAfnfLkp5MW0UH9eUvnDSnFwKZ0AvgS1ucqR4KzvVHgnke1VQ==", - "dev": true, - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/runtime": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.4.tgz", - "integrity": "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/template": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", - "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.22.13", - "@babel/parser": "^7.22.15", - "@babel/types": "^7.22.15" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse": { - "version": "7.23.7", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.7.tgz", - "integrity": "sha512-tY3mM8rH9jM0YHFGyfC0/xf+SB5eKUu7HPj7/k3fpi9dAlsMc5YbQvDi0Sh2QTPXqMhyaAtzAr807TIyfQrmyg==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.23.5", - "@babel/generator": "^7.23.6", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.23.6", - "@babel/types": "^7.23.6", - "debug": "^4.3.1", - "globals": "^11.1.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/types": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.6.tgz", - "integrity": "sha512-+uarb83brBzPKN38NX1MkB6vb6+mwvR6amUulqAE7ccQw1pEl+bCia9TbdG1lsnFP7lZySvUn37CHyXQdfTwzg==", - "dev": true, - "dependencies": { - "@babel/helper-string-parser": "^7.23.4", - "@babel/helper-validator-identifier": "^7.22.20", - "to-fast-properties": "^2.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@cspotcode/source-map-support": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", - "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", - "dev": true, - "dependencies": { - "@jridgewell/trace-mapping": "0.3.9" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", - "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", - "dev": true, - "dependencies": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" - } - }, - "node_modules/@emnapi/core": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.7.1.tgz", - "integrity": "sha512-o1uhUASyo921r2XtHYOHy7gdkGLge8ghBEQHMWmyJFoXlpU58kIrhhN3w26lpQb6dspetweapMn2CSNwQ8I4wg==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@emnapi/wasi-threads": "1.1.0", - "tslib": "^2.4.0" - } - }, - "node_modules/@emnapi/runtime": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.7.1.tgz", - "integrity": "sha512-PVtJr5CmLwYAU9PZDMITZoR5iAOShYREoR45EyyLrbntV50mdePTgUn4AmOw90Ifcj+x2kRjdzr1HP3RrNiHGA==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@emnapi/wasi-threads": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.1.0.tgz", - "integrity": "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", - "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz", - "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz", - "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz", - "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz", - "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz", - "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz", - "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz", - "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz", - "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz", - "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz", - "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz", - "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz", - "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz", - "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz", - "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz", - "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz", - "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz", - "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz", - "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz", - "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz", - "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openharmony-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz", - "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz", - "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz", - "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz", - "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz", - "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" - } - }, - "node_modules/@eslint-community/regexpp": { - "version": "4.10.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.1.tgz", - "integrity": "sha512-Zm2NGpWELsQAD1xsJzGQpYfvICSsFkEpU0jxBjfdC6uNEWXcHnfs9hScFWtXVDVl+rBQJGrl4g1vcKIejpH9dA==", - "dev": true, - "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" - } - }, - "node_modules/@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", - "dev": true, - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", - "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@eslint/eslintrc/node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@eslint/js": { - "version": "8.56.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.56.0.tgz", - "integrity": "sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/@homebridge/ciao": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/@homebridge/ciao/-/ciao-1.3.4.tgz", - "integrity": "sha512-qK6ZgGx0wwOubq/MY6eTbhApQHBUQCvCOsTYpQE01uLvfA2/Prm6egySHlZouKaina1RPuDwfLhCmsRCxwHj3Q==", - "license": "MIT", - "dependencies": { - "debug": "^4.4.1", - "fast-deep-equal": "^3.1.3", - "source-map-support": "^0.5.21", - "tslib": "^2.8.1" - }, - "bin": { - "ciao-bcs": "lib/bonjour-conformance-testing.js" - } - }, - "node_modules/@homebridge/hap-nodejs": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@homebridge/hap-nodejs/-/hap-nodejs-2.0.2.tgz", - "integrity": "sha512-HqlMqVQ8bzh7uFqL0vNI6a5PJHAmCyPzHuPbBxf6XcPVKn02ELwCMDQ8ud5oS1fPO5z20lvV7rIfAqTbSlZ7Uw==", - "license": "Apache-2.0", - "dependencies": { - "@homebridge/ciao": "^1.3.4", - "@homebridge/dbus-native": "^0.7.2", - "bonjour-hap": "^3.9.1", - "debug": "^4.4.3", - "fast-srp-hap": "^2.0.4", - "futoin-hkdf": "^1.5.3", - "node-persist": "^0.0.12", - "source-map-support": "^0.5.21", - "tslib": "^2.8.1", - "tweetnacl": "^1.0.3" - }, - "engines": { - "node": "^20 || ^22 || ^24" - } - }, - "node_modules/@homebridge/hap-nodejs/node_modules/@homebridge/dbus-native": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/@homebridge/dbus-native/-/dbus-native-0.7.2.tgz", - "integrity": "sha512-BNVe6YNxiy5x/E5/ZXDIWMD6Njv9cjW59PM/1CMpYe0jLAJ8pJN+Tq/JhVs3gXwmTavz2S86/sspmHquChet8A==", - "license": "MIT", - "dependencies": { - "event-stream": "^4.0.1", - "hexy": "^0.3.5", - "long": "^5.3.2", - "minimist": "^1.2.8", - "safe-buffer": "^5.1.2", - "xml2js": "^0.6.2" - }, - "bin": { - "dbus2js": "bin/dbus2js.js" - } - }, - "node_modules/@homebridge/hap-nodejs/node_modules/node-persist": { - "version": "0.0.12", - "resolved": "https://registry.npmjs.org/node-persist/-/node-persist-0.0.12.tgz", - "integrity": "sha512-Fbia3FYnURzaql53wLu0t19dmAwQg/tXT6O7YPmdwNwysNKEyFmgoT2BQlPD3XXQnYeiQVNvR5lfvufGwKuxhg==", - "license": "MIT", - "dependencies": { - "mkdirp": "~0.5.1", - "q": "~1.1.1" - } - }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.11.13", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz", - "integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==", - "dev": true, - "dependencies": { - "@humanwhocodes/object-schema": "^2.0.1", - "debug": "^4.1.1", - "minimatch": "^3.0.5" - }, - "engines": { - "node": ">=10.10.0" - } - }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "dev": true, - "engines": { - "node": ">=12.22" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz", - "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==", - "dev": true - }, - "node_modules/@isaacs/cliui": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", - "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", - "dev": true, - "license": "ISC", - "dependencies": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@isaacs/cliui/node_modules/ansi-regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true, - "license": "MIT" - }, - "node_modules/@isaacs/cliui/node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "dev": true, - "license": "MIT", - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@isaacs/cliui/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/@isaacs/fs-minipass": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", - "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", - "dev": true, - "license": "ISC", - "dependencies": { - "minipass": "^7.0.4" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", - "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", - "dev": true, - "dependencies": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", - "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", - "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", - "dev": true, - "license": "MIT" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.20", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz", - "integrity": "sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==", - "dev": true, - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@leichtgewicht/ip-codec": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz", - "integrity": "sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==", - "license": "MIT" - }, - "node_modules/@napi-rs/wasm-runtime": { - "version": "0.2.12", - "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz", - "integrity": "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@emnapi/core": "^1.4.3", - "@emnapi/runtime": "^1.4.3", - "@tybys/wasm-util": "^0.10.0" - } - }, - "node_modules/@noble/hashes": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz", - "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^14.21.3 || >=16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@node-red/editor-api": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/@node-red/editor-api/-/editor-api-4.1.1.tgz", - "integrity": "sha512-vev2s3NntphqinzP2e3WmPnQY8+cHfSrQyESis9Fy+prp+E8uSgT4yfLjHMFyT116xPMB5WIg6qSDciq5OV1tA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@node-red/editor-client": "4.1.1", - "@node-red/util": "4.1.1", - "bcryptjs": "3.0.2", - "body-parser": "1.20.3", - "clone": "2.1.2", - "cors": "2.8.5", - "express": "4.21.2", - "express-session": "1.18.2", - "memorystore": "1.6.7", - "mime": "3.0.0", - "multer": "2.0.2", - "mustache": "4.2.0", - "oauth2orize": "1.12.0", - "passport": "0.7.0", - "passport-http-bearer": "1.0.1", - "passport-oauth2-client-password": "0.1.2", - "ws": "7.5.10" - }, - "optionalDependencies": { - "@node-rs/bcrypt": "1.10.7" - } - }, - "node_modules/@node-red/editor-client": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/@node-red/editor-client/-/editor-client-4.1.1.tgz", - "integrity": "sha512-JIJirftuB0NrvsFvPZXW3R16c8mLRy2UQh0AyxGU8ZQyz/dmF8auINbbGpQ4qxssBOGFWf9j4ZXP7B8EdLIOBQ==", - "dev": true, - "license": "Apache-2.0" - }, - "node_modules/@node-red/nodes": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/@node-red/nodes/-/nodes-4.1.1.tgz", - "integrity": "sha512-zTTwxpnPebHA5PjDBZEcsGv0BoqMJEjhf27aQIhlGed40/PaNiR0tmc5f5P6HKflmS3Iv6kiwGsY12Mjvyx/3Q==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "acorn": "8.15.0", - "acorn-walk": "8.3.4", - "ajv": "8.17.1", - "body-parser": "1.20.3", - "cheerio": "1.0.0-rc.10", - "content-type": "1.0.5", - "cookie": "0.7.2", - "cookie-parser": "1.4.7", - "cors": "2.8.5", - "cronosjs": "1.7.1", - "denque": "2.1.0", - "form-data": "4.0.4", - "fs-extra": "11.3.0", - "got": "12.6.1", - "hash-sum": "2.0.0", - "hpagent": "1.2.0", - "https-proxy-agent": "5.0.1", - "iconv-lite": "0.6.3", - "is-utf8": "0.2.1", - "js-yaml": "4.1.0", - "media-typer": "1.1.0", - "mqtt": "5.11.0", - "multer": "2.0.2", - "mustache": "4.2.0", - "node-watch": "0.7.4", - "on-headers": "1.1.0", - "raw-body": "3.0.0", - "tough-cookie": "5.1.2", - "uuid": "9.0.1", - "ws": "7.5.10", - "xml2js": "0.6.2" - } - }, - "node_modules/@node-red/nodes/node_modules/ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/@node-red/nodes/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true, - "license": "MIT" - }, - "node_modules/@node-red/nodes/node_modules/raw-body": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.0.tgz", - "integrity": "sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==", - "dev": true, - "license": "MIT", - "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.6.3", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/@node-red/nodes/node_modules/uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", - "dev": true, - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "license": "MIT", - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/@node-red/registry": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/@node-red/registry/-/registry-4.1.1.tgz", - "integrity": "sha512-+5SvdL+6tXzfYW63TpsfgybNP7G4farM+2div5FYYPdMJULE1D9Z8BHD/fprieU5mTTTO100CeyGXHbkzRH+Qg==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@node-red/util": "4.1.1", - "clone": "2.1.2", - "fs-extra": "11.3.0", - "semver": "7.7.1", - "tar": "7.4.3", - "uglify-js": "3.19.3" - } - }, - "node_modules/@node-red/registry/node_modules/semver": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", - "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@node-red/runtime": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/@node-red/runtime/-/runtime-4.1.1.tgz", - "integrity": "sha512-NWV+u2GrLnaPjomJilwVhl5u6WLwJN7tvHEVm5r9/8quW0H8BuYfih5AwCzCl8aly1imhe1+kfiCExSfGVaQUA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@node-red/registry": "4.1.1", - "@node-red/util": "4.1.1", - "async-mutex": "0.5.0", - "clone": "2.1.2", - "cronosjs": "1.7.1", - "express": "4.21.2", - "fs-extra": "11.3.0", - "got": "12.6.1", - "json-stringify-safe": "5.0.1", - "rfdc": "^1.3.1", - "semver": "7.7.1" - } - }, - "node_modules/@node-red/runtime/node_modules/semver": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", - "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@node-red/util": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/@node-red/util/-/util-4.1.1.tgz", - "integrity": "sha512-gnkRXmz49rj2OXjJC/RAPbFUQvDATC3Oy6yGuhN/McPy8mmL7q4YTIflUwWKyrsd6TU3cK17JmmXtPTQBtS8jQ==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "chalk": "^4.1.2", - "fs-extra": "11.3.0", - "i18next": "24.2.3", - "json-stringify-safe": "5.0.1", - "jsonata": "2.0.6", - "lodash.clonedeep": "^4.5.0", - "moment": "2.30.1", - "moment-timezone": "0.5.48" - } - }, - "node_modules/@node-red/util/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@node-red/util/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/@node-red/util/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/@node-red/util/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@node-red/util/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/@node-red/util/node_modules/jsonata": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/jsonata/-/jsonata-2.0.6.tgz", - "integrity": "sha512-WhQB5tXQ32qjkx2GYHFw2XbL90u+LLzjofAYwi+86g6SyZeXHz9F1Q0amy3dWRYczshOC3Haok9J4pOCgHtwyQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/@node-red/util/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@node-rs/bcrypt": { - "version": "1.10.7", - "resolved": "https://registry.npmjs.org/@node-rs/bcrypt/-/bcrypt-1.10.7.tgz", - "integrity": "sha512-1wk0gHsUQC/ap0j6SJa2K34qNhomxXRcEe3T8cI5s+g6fgHBgLTN7U9LzWTG/HE6G4+2tWWLeCabk1wiYGEQSA==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">= 10" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Brooooooklyn" - }, - "optionalDependencies": { - "@node-rs/bcrypt-android-arm-eabi": "1.10.7", - "@node-rs/bcrypt-android-arm64": "1.10.7", - "@node-rs/bcrypt-darwin-arm64": "1.10.7", - "@node-rs/bcrypt-darwin-x64": "1.10.7", - "@node-rs/bcrypt-freebsd-x64": "1.10.7", - "@node-rs/bcrypt-linux-arm-gnueabihf": "1.10.7", - "@node-rs/bcrypt-linux-arm64-gnu": "1.10.7", - "@node-rs/bcrypt-linux-arm64-musl": "1.10.7", - "@node-rs/bcrypt-linux-x64-gnu": "1.10.7", - "@node-rs/bcrypt-linux-x64-musl": "1.10.7", - "@node-rs/bcrypt-wasm32-wasi": "1.10.7", - "@node-rs/bcrypt-win32-arm64-msvc": "1.10.7", - "@node-rs/bcrypt-win32-ia32-msvc": "1.10.7", - "@node-rs/bcrypt-win32-x64-msvc": "1.10.7" - } - }, - "node_modules/@node-rs/bcrypt-android-arm-eabi": { - "version": "1.10.7", - "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-android-arm-eabi/-/bcrypt-android-arm-eabi-1.10.7.tgz", - "integrity": "sha512-8dO6/PcbeMZXS3VXGEtct9pDYdShp2WBOWlDvSbcRwVqyB580aCBh0BEFmKYtXLzLvUK8Wf+CG3U6sCdILW1lA==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@node-rs/bcrypt-android-arm64": { - "version": "1.10.7", - "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-android-arm64/-/bcrypt-android-arm64-1.10.7.tgz", - "integrity": "sha512-UASFBS/CucEMHiCtL/2YYsAY01ZqVR1N7vSb94EOvG5iwW7BQO06kXXCTgj+Xbek9azxixrCUmo3WJnkJZ0hTQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@node-rs/bcrypt-darwin-arm64": { - "version": "1.10.7", - "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-darwin-arm64/-/bcrypt-darwin-arm64-1.10.7.tgz", - "integrity": "sha512-DgzFdAt455KTuiJ/zYIyJcKFobjNDR/hnf9OS7pK5NRS13Nq4gLcSIIyzsgHwZHxsJWbLpHmFc1H23Y7IQoQBw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@node-rs/bcrypt-darwin-x64": { - "version": "1.10.7", - "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-darwin-x64/-/bcrypt-darwin-x64-1.10.7.tgz", - "integrity": "sha512-SPWVfQ6sxSokoUWAKWD0EJauvPHqOGQTd7CxmYatcsUgJ/bruvEHxZ4bIwX1iDceC3FkOtmeHO0cPwR480n/xA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@node-rs/bcrypt-freebsd-x64": { - "version": "1.10.7", - "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-freebsd-x64/-/bcrypt-freebsd-x64-1.10.7.tgz", - "integrity": "sha512-gpa+Ixs6GwEx6U6ehBpsQetzUpuAGuAFbOiuLB2oo4N58yU4AZz1VIcWyWAHrSWRs92O0SHtmo2YPrMrwfBbSw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@node-rs/bcrypt-linux-arm-gnueabihf": { - "version": "1.10.7", - "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-linux-arm-gnueabihf/-/bcrypt-linux-arm-gnueabihf-1.10.7.tgz", - "integrity": "sha512-kYgJnTnpxrzl9sxYqzflobvMp90qoAlaX1oDL7nhNTj8OYJVDIk0jQgblj0bIkjmoPbBed53OJY/iu4uTS+wig==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@node-rs/bcrypt-linux-arm64-gnu": { - "version": "1.10.7", - "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-linux-arm64-gnu/-/bcrypt-linux-arm64-gnu-1.10.7.tgz", - "integrity": "sha512-7cEkK2RA+gBCj2tCVEI1rDSJV40oLbSq7bQ+PNMHNI6jCoXGmj9Uzo7mg7ZRbNZ7piIyNH5zlJqutjo8hh/tmA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@node-rs/bcrypt-linux-arm64-musl": { - "version": "1.10.7", - "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-linux-arm64-musl/-/bcrypt-linux-arm64-musl-1.10.7.tgz", - "integrity": "sha512-X7DRVjshhwxUqzdUKDlF55cwzh+wqWJ2E/tILvZPboO3xaNO07Um568Vf+8cmKcz+tiZCGP7CBmKbBqjvKN/Pw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@node-rs/bcrypt-linux-x64-gnu": { - "version": "1.10.7", - "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-linux-x64-gnu/-/bcrypt-linux-x64-gnu-1.10.7.tgz", - "integrity": "sha512-LXRZsvG65NggPD12hn6YxVgH0W3VR5fsE/o1/o2D5X0nxKcNQGeLWnRzs5cP8KpoFOuk1ilctXQJn8/wq+Gn/Q==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@node-rs/bcrypt-linux-x64-musl": { - "version": "1.10.7", - "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-linux-x64-musl/-/bcrypt-linux-x64-musl-1.10.7.tgz", - "integrity": "sha512-tCjHmct79OfcO3g5q21ME7CNzLzpw1MAsUXCLHLGWH+V6pp/xTvMbIcLwzkDj6TI3mxK6kehTn40SEjBkZ3Rog==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@node-rs/bcrypt-wasm32-wasi": { - "version": "1.10.7", - "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-wasm32-wasi/-/bcrypt-wasm32-wasi-1.10.7.tgz", - "integrity": "sha512-4qXSihIKeVXYglfXZEq/QPtYtBUvR8d3S85k15Lilv3z5B6NSGQ9mYiNleZ7QHVLN2gEc5gmi7jM353DMH9GkA==", - "cpu": [ - "wasm32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@napi-rs/wasm-runtime": "^0.2.5" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@node-rs/bcrypt-win32-arm64-msvc": { - "version": "1.10.7", - "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-win32-arm64-msvc/-/bcrypt-win32-arm64-msvc-1.10.7.tgz", - "integrity": "sha512-FdfUQrqmDfvC5jFhntMBkk8EI+fCJTx/I1v7Rj+Ezlr9rez1j1FmuUnywbBj2Cg15/0BDhwYdbyZ5GCMFli2aQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@node-rs/bcrypt-win32-ia32-msvc": { - "version": "1.10.7", - "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-win32-ia32-msvc/-/bcrypt-win32-ia32-msvc-1.10.7.tgz", - "integrity": "sha512-lZLf4Cx+bShIhU071p5BZft4OvP4PGhyp542EEsb3zk34U5GLsGIyCjOafcF/2DGewZL6u8/aqoxbSuROkgFXg==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@node-rs/bcrypt-win32-x64-msvc": { - "version": "1.10.7", - "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-win32-x64-msvc/-/bcrypt-win32-x64-msvc-1.10.7.tgz", - "integrity": "sha512-hdw7tGmN1DxVAMTzICLdaHpXjy+4rxaxnBMgI8seG1JL5e3VcRGsd1/1vVDogVp2cbsmgq+6d6yAY+D9lW/DCg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nrchkb/logger": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@nrchkb/logger/-/logger-3.1.1.tgz", - "integrity": "sha512-37m4lq7Jemg7qzkBflD+VZ1HnFdZv10k9hgglonFXTBMrLmXxkXllWelCKDGABVkfx1hjijAz6IpQoIF+Oo9yw==", - "license": "Apache-2.0", - "dependencies": { - "debug": "^4.3.5" - } - }, - "node_modules/@paralleldrive/cuid2": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/@paralleldrive/cuid2/-/cuid2-2.3.1.tgz", - "integrity": "sha512-XO7cAxhnTZl0Yggq6jOgjiOHhbgcO4NqFqwSmQpjK3b6TEE6Uj/jfSk6wzYyemh3+I0sHirKSetjQwn5cZktFw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@noble/hashes": "^1.1.5" - } - }, - "node_modules/@pkgjs/parseargs": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=14" - } - }, - "node_modules/@pkgr/core": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.9.tgz", - "integrity": "sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.20.0 || ^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/pkgr" - } - }, - "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.53.3.tgz", - "integrity": "sha512-mRSi+4cBjrRLoaal2PnqH82Wqyb+d3HsPUN/W+WslCXsZsyHa9ZeQQX/pQsZaVIWDkPcpV6jJ+3KLbTbgnwv8w==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-android-arm64": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.53.3.tgz", - "integrity": "sha512-CbDGaMpdE9sh7sCmTrTUyllhrg65t6SwhjlMJsLr+J8YjFuPmCEjbBSx4Z/e4SmDyH3aB5hGaJUP2ltV/vcs4w==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.53.3.tgz", - "integrity": "sha512-Nr7SlQeqIBpOV6BHHGZgYBuSdanCXuw09hon14MGOLGmXAFYjx1wNvquVPmpZnl0tLjg25dEdr4IQ6GgyToCUA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.53.3.tgz", - "integrity": "sha512-DZ8N4CSNfl965CmPktJ8oBnfYr3F8dTTNBQkRlffnUarJ2ohudQD17sZBa097J8xhQ26AwhHJ5mvUyQW8ddTsQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.53.3.tgz", - "integrity": "sha512-yMTrCrK92aGyi7GuDNtGn2sNW+Gdb4vErx4t3Gv/Tr+1zRb8ax4z8GWVRfr3Jw8zJWvpGHNpss3vVlbF58DZ4w==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.53.3.tgz", - "integrity": "sha512-lMfF8X7QhdQzseM6XaX0vbno2m3hlyZFhwcndRMw8fbAGUGL3WFMBdK0hbUBIUYcEcMhVLr1SIamDeuLBnXS+Q==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.53.3.tgz", - "integrity": "sha512-k9oD15soC/Ln6d2Wv/JOFPzZXIAIFLp6B+i14KhxAfnq76ajt0EhYc5YPeX6W1xJkAdItcVT+JhKl1QZh44/qw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.53.3.tgz", - "integrity": "sha512-vTNlKq+N6CK/8UktsrFuc+/7NlEYVxgaEgRXVUVK258Z5ymho29skzW1sutgYjqNnquGwVUObAaxae8rZ6YMhg==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.53.3.tgz", - "integrity": "sha512-RGrFLWgMhSxRs/EWJMIFM1O5Mzuz3Xy3/mnxJp/5cVhZ2XoCAxJnmNsEyeMJtpK+wu0FJFWz+QF4mjCA7AUQ3w==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.53.3.tgz", - "integrity": "sha512-kASyvfBEWYPEwe0Qv4nfu6pNkITLTb32p4yTgzFCocHnJLAHs+9LjUu9ONIhvfT/5lv4YS5muBHyuV84epBo/A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-loong64-gnu": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.53.3.tgz", - "integrity": "sha512-JiuKcp2teLJwQ7vkJ95EwESWkNRFJD7TQgYmCnrPtlu50b4XvT5MOmurWNrCj3IFdyjBQ5p9vnrX4JM6I8OE7g==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.53.3.tgz", - "integrity": "sha512-EoGSa8nd6d3T7zLuqdojxC20oBfNT8nexBbB/rkxgKj5T5vhpAQKKnD+h3UkoMuTyXkP5jTjK/ccNRmQrPNDuw==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.53.3.tgz", - "integrity": "sha512-4s+Wped2IHXHPnAEbIB0YWBv7SDohqxobiiPA1FIWZpX+w9o2i4LezzH/NkFUl8LRci/8udci6cLq+jJQlh+0g==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.53.3.tgz", - "integrity": "sha512-68k2g7+0vs2u9CxDt5ktXTngsxOQkSEV/xBbwlqYcUrAVh6P9EgMZvFsnHy4SEiUl46Xf0IObWVbMvPrr2gw8A==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.53.3.tgz", - "integrity": "sha512-VYsFMpULAz87ZW6BVYw3I6sWesGpsP9OPcyKe8ofdg9LHxSbRMd7zrVrr5xi/3kMZtpWL/wC+UIJWJYVX5uTKg==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.53.3.tgz", - "integrity": "sha512-3EhFi1FU6YL8HTUJZ51imGJWEX//ajQPfqWLI3BQq4TlvHy4X0MOr5q3D2Zof/ka0d5FNdPwZXm3Yyib/UEd+w==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.53.3.tgz", - "integrity": "sha512-eoROhjcc6HbZCJr+tvVT8X4fW3/5g/WkGvvmwz/88sDtSJzO7r/blvoBDgISDiCjDRZmHpwud7h+6Q9JxFwq1Q==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-openharmony-arm64": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.53.3.tgz", - "integrity": "sha512-OueLAWgrNSPGAdUdIjSWXw+u/02BRTcnfw9PN41D2vq/JSEPnJnVuBgw18VkN8wcd4fjUs+jFHVM4t9+kBSNLw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ] - }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.53.3.tgz", - "integrity": "sha512-GOFuKpsxR/whszbF/bzydebLiXIHSgsEUp6M0JI8dWvi+fFa1TD6YQa4aSZHtpmh2/uAlj/Dy+nmby3TJ3pkTw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.53.3.tgz", - "integrity": "sha512-iah+THLcBJdpfZ1TstDFbKNznlzoxa8fmnFYK4V67HvmuNYkVdAywJSoteUszvBQ9/HqN2+9AZghbajMsFT+oA==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-gnu": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.53.3.tgz", - "integrity": "sha512-J9QDiOIZlZLdcot5NXEepDkstocktoVjkaKUtqzgzpt2yWjGlbYiKyp05rWwk4nypbYUNoFAztEgixoLaSETkg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.53.3.tgz", - "integrity": "sha512-UhTd8u31dXadv0MopwGgNOBpUVROFKWVQgAg5N1ESyCz8AuBcMqm4AuTjrwgQKGDfoFuz02EuMRHQIw/frmYKQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@sindresorhus/is": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-5.6.0.tgz", - "integrity": "sha512-TV7t8GKYaJWsn00tFDqBw8+Uqmr8A0fRU1tvTQhyZzGv0sJCGRQL3JGMI3ucuKo3XIZdUP+Lx7/gh2t3lewy7g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sindresorhus/is?sponsor=1" - } - }, - "node_modules/@sindresorhus/merge-streams": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-2.3.0.tgz", - "integrity": "sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@sinonjs/commons": { - "version": "1.8.6", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.6.tgz", - "integrity": "sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ==", - "dev": true, - "dependencies": { - "type-detect": "4.0.8" - } - }, - "node_modules/@sinonjs/fake-timers": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-7.1.2.tgz", - "integrity": "sha512-iQADsW4LBMISqZ6Ci1dupJL9pprqwcVFTcOsEmQOEhW+KLCVn/Y4Jrvg2k19fIHCp+iFprriYPTdRcQR8NbUPg==", - "dev": true, - "dependencies": { - "@sinonjs/commons": "^1.7.0" - } - }, - "node_modules/@sinonjs/samsam": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-6.1.3.tgz", - "integrity": "sha512-nhOb2dWPeb1sd3IQXL/dVPnKHDOAFfvichtBf4xV00/rU1QbPCQqKMbvIheIjqwVjh7qIgf2AHTHi391yMOMpQ==", - "dev": true, - "dependencies": { - "@sinonjs/commons": "^1.6.0", - "lodash.get": "^4.4.2", - "type-detect": "^4.0.8" - } - }, - "node_modules/@sinonjs/text-encoding": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.2.tgz", - "integrity": "sha512-sXXKG+uL9IrKqViTtao2Ws6dy0znu9sOaP1di/jKGW1M6VssO8vlpXCQcpZ+jisQ1tTFAC5Jo/EOzFbggBagFQ==", - "dev": true - }, - "node_modules/@standard-schema/spec": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.0.0.tgz", - "integrity": "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@szmarczak/http-timer": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-5.0.1.tgz", - "integrity": "sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==", - "dev": true, - "license": "MIT", - "dependencies": { - "defer-to-connect": "^2.0.1" - }, - "engines": { - "node": ">=14.16" - } - }, - "node_modules/@tsconfig/node10": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", - "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", - "dev": true - }, - "node_modules/@tsconfig/node12": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", - "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", - "dev": true - }, - "node_modules/@tsconfig/node14": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", - "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", - "dev": true - }, - "node_modules/@tsconfig/node16": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", - "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", - "dev": true - }, - "node_modules/@tybys/wasm-util": { - "version": "0.10.1", - "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz", - "integrity": "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@types/ace": { - "version": "0.0.52", - "resolved": "https://registry.npmjs.org/@types/ace/-/ace-0.0.52.tgz", - "integrity": "sha512-YPF9S7fzpuyrxru+sG/rrTpZkC6gpHBPF14W3x70kqVOD+ks6jkYLapk4yceh36xej7K4HYxcyz9ZDQ2lTvwgQ==", - "dev": true - }, - "node_modules/@types/body-parser": { - "version": "1.19.2", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", - "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", - "dev": true, - "dependencies": { - "@types/connect": "*", - "@types/node": "*" - } - }, - "node_modules/@types/chai": { - "version": "5.2.3", - "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz", - "integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/deep-eql": "*", - "assertion-error": "^2.0.1" - } - }, - "node_modules/@types/connect": { - "version": "3.4.35", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", - "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/cookiejar": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@types/cookiejar/-/cookiejar-2.1.2.tgz", - "integrity": "sha512-t73xJJrvdTjXrn4jLS9VSGRbz0nUY3cl2DMGDU48lKl+HR9dbbjW2A9r3g40VA++mQpy6uuHg33gy7du2BKpog==", - "dev": true - }, - "node_modules/@types/cors": { - "version": "2.8.13", - "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.13.tgz", - "integrity": "sha512-RG8AStHlUiV5ysZQKq97copd2UmVYw3/pRMLefISZ3S1hK104Cwm7iLQ3fTKx+lsUH2CE8FlLaYeEA2LSeqYUA==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/deep-eql": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", - "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/estree": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", - "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/express": { - "version": "4.17.17", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.17.tgz", - "integrity": "sha512-Q4FmmuLGBG58btUnfS1c1r/NQdlp3DMfGDGig8WhfpA2YRUtEkxAjkZb0yvplJGYdF1fsQ81iMDcH24sSCNC/Q==", - "dev": true, - "dependencies": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "^4.17.33", - "@types/qs": "*", - "@types/serve-static": "*" - } - }, - "node_modules/@types/express-serve-static-core": { - "version": "4.17.35", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.35.tgz", - "integrity": "sha512-wALWQwrgiB2AWTT91CB62b6Yt0sNHpznUXeZEcnPU3DRdlDIz74x8Qg1UUYKSVFi+va5vKOLYRBI1bRKiLLKIg==", - "dev": true, - "dependencies": { - "@types/node": "*", - "@types/qs": "*", - "@types/range-parser": "*", - "@types/send": "*" - } - }, - "node_modules/@types/http-cache-semantics": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz", - "integrity": "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/http-errors": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.1.tgz", - "integrity": "sha512-/K3ds8TRAfBvi5vfjuz8y6+GiAYBZ0x4tXv1Av6CWBWn0IlADc+ZX9pMq7oU0fNQPnBwIZl3rmeLp6SBApbxSQ==", - "dev": true - }, - "node_modules/@types/jquery": { - "version": "3.5.30", - "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.30.tgz", - "integrity": "sha512-nbWKkkyb919DOUxjmRVk8vwtDb0/k8FKncmUKFi+NY+QXqWltooxTrswvz4LspQwxvLdvzBN1TImr6cw3aQx2A==", - "dev": true, - "dependencies": { - "@types/sizzle": "*" - } - }, - "node_modules/@types/mime": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", - "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==", - "dev": true - }, - "node_modules/@types/node": { - "version": "20.19.25", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.25.tgz", - "integrity": "sha512-ZsJzA5thDQMSQO788d7IocwwQbI8B5OPzmqNvpf3NY/+MHDAS759Wo0gd2WQeXYt5AAAQjzcrTVC6SKCuYgoCQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "undici-types": "~6.21.0" - } - }, - "node_modules/@types/node-persist": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/@types/node-persist/-/node-persist-3.1.8.tgz", - "integrity": "sha512-QLidg6/SadZYPrTKxtxL1A85XBoQlG40bhoMdhu6DH6+eNCMr2j+RGfFZ9I9+IY8W/PDwQonJ+iBWD62jZjMfg==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/node-red": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/@types/node-red/-/node-red-1.3.5.tgz", - "integrity": "sha512-LBP8TmXJszHOoRgieyxgUrspvatmTZlkPRftlSNGE9TVJCQzSSyX3tF/Qe4evQlIUBmMGOijxcUOcKZSvq4piQ==", - "dev": true, - "dependencies": { - "@types/express": "*", - "@types/node-red__editor-api": "*", - "@types/node-red__editor-client": "*", - "@types/node-red__registry": "*", - "@types/node-red__runtime": "*", - "@types/node-red__util": "*" - } - }, - "node_modules/@types/node-red__editor-api": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/@types/node-red__editor-api/-/node-red__editor-api-1.3.5.tgz", - "integrity": "sha512-VE0o/gJzHVBTD2OBhpWth3sjU06TYLlLvlPh62Whs9FXUY0FdFKqWXbaG+ymYQqZreL1ZvTKfFmj0H7LnVEUeg==", - "dev": true, - "dependencies": { - "@types/express": "*", - "@types/node-red__runtime": "*" - } - }, - "node_modules/@types/node-red__editor-client": { - "version": "1.3.11", - "resolved": "https://registry.npmjs.org/@types/node-red__editor-client/-/node-red__editor-client-1.3.11.tgz", - "integrity": "sha512-Y8FGsMfec4TAVfULabH/Jui+4Cj4F3xx9v4GDpoTN5X9uHwOxdRi9UDtdvG+se/S76CFg6VjsctpJW0WjJUXgw==", - "dev": true, - "dependencies": { - "@types/ace": "*", - "@types/jquery": "*", - "@types/node-red__registry": "*", - "@types/node-red__runtime": "*", - "@types/node-red__util": "*" - } - }, - "node_modules/@types/node-red__registry": { - "version": "1.3.10", - "resolved": "https://registry.npmjs.org/@types/node-red__registry/-/node-red__registry-1.3.10.tgz", - "integrity": "sha512-sWjQMHn/k3OTFlrG7ljcfOMjsl1OdFEvDkRHoBga2srUjbtecELEcPaQ4WY5xsJdoXuhgxvhGh/5+ZPhpNTXEA==", - "dev": true, - "dependencies": { - "@types/express": "*", - "@types/node-red__runtime": "*", - "@types/node-red__util": "*" - } - }, - "node_modules/@types/node-red__runtime": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/@types/node-red__runtime/-/node-red__runtime-1.3.8.tgz", - "integrity": "sha512-v5wsFjL6/kQ/YSz7WjC1J9yvE+NP8r5uivQTMBxnNnBabmDJo+dBmdp0rqJczbPNQS0ze7JGDQWz3Iuve+pYlw==", - "dev": true, - "dependencies": { - "@types/cors": "*", - "@types/express": "*", - "@types/node-red__editor-api": "*", - "@types/node-red__util": "*", - "@types/passport": "*" - } - }, - "node_modules/@types/node-red__util": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/@types/node-red__util/-/node-red__util-1.3.8.tgz", - "integrity": "sha512-FQRxaZyUJlyh2phJevzMSF4H8jrsOUmFg05eyhRX5lvDcc/VqdZWcYdAq9dZPRgIwHJwLBttEh9mG3DAcMJiUg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node-red__registry": "*", - "@types/node-red__runtime": "*", - "jsonata": "2.0.5" - } - }, - "node_modules/@types/node-red-node-test-helper": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@types/node-red-node-test-helper/-/node-red-node-test-helper-0.3.5.tgz", - "integrity": "sha512-ppCrp+3ncOCvciPXwQWhXy5voENjDyK1Xvw98Q9a4tJsSdqiitdy7HsUgtbCSn/mrKStRzZ61l+fHDAknR0BgA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node-red": "*", - "@types/node-red__runtime": "*", - "@types/sinon": "*", - "@types/supertest": "*" - } - }, - "node_modules/@types/passport": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/@types/passport/-/passport-1.0.12.tgz", - "integrity": "sha512-QFdJ2TiAEoXfEQSNDISJR1Tm51I78CymqcBa8imbjo6dNNu+l2huDxxbDEIoFIwOSKMkOfHEikyDuZ38WwWsmw==", - "dev": true, - "dependencies": { - "@types/express": "*" - } - }, - "node_modules/@types/qs": { - "version": "6.9.7", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", - "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==", - "dev": true - }, - "node_modules/@types/range-parser": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", - "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==", - "dev": true - }, - "node_modules/@types/readable-stream": { - "version": "4.0.22", - "resolved": "https://registry.npmjs.org/@types/readable-stream/-/readable-stream-4.0.22.tgz", - "integrity": "sha512-/FFhJpfCLAPwAcN3mFycNUa77ddnr8jTgF5VmSNetaemWB2cIlfCA9t0YTM3JAT0wOcv8D4tjPo7pkDhK3EJIg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/semver": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.7.1.tgz", - "integrity": "sha512-FmgJfu+MOcQ370SD0ev7EI8TlCAfKYU+B4m5T3yXc1CiRN94g/SZPtsCkk506aUDtlMnFZvasDwHHUcZUEaYuA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/send": { - "version": "0.17.1", - "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.1.tgz", - "integrity": "sha512-Cwo8LE/0rnvX7kIIa3QHCkcuF21c05Ayb0ZfxPiv0W8VRiZiNW/WuRupHKpqqGVGf7SUA44QSOUKaEd9lIrd/Q==", - "dev": true, - "dependencies": { - "@types/mime": "^1", - "@types/node": "*" - } - }, - "node_modules/@types/serve-static": { - "version": "1.15.2", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.2.tgz", - "integrity": "sha512-J2LqtvFYCzaj8pVYKw8klQXrLLk7TBZmQ4ShlcdkELFKGwGMfevMLneMMRkMgZxotOD9wg497LpC7O8PcvAmfw==", - "dev": true, - "dependencies": { - "@types/http-errors": "*", - "@types/mime": "*", - "@types/node": "*" - } - }, - "node_modules/@types/sinon": { - "version": "10.0.16", - "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-10.0.16.tgz", - "integrity": "sha512-j2Du5SYpXZjJVJtXBokASpPRj+e2z+VUhCPHmM6WMfe3dpHu6iVKJMU6AiBcMp/XTAYnEj6Wc1trJUWwZ0QaAQ==", - "dev": true, - "dependencies": { - "@types/sinonjs__fake-timers": "*" - } - }, - "node_modules/@types/sinonjs__fake-timers": { - "version": "8.1.2", - "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.2.tgz", - "integrity": "sha512-9GcLXF0/v3t80caGs5p2rRfkB+a8VBGLJZVih6CNFkx8IZ994wiKKLSRs9nuFwk1HevWs/1mnUmkApGrSGsShA==", - "dev": true - }, - "node_modules/@types/sizzle": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.8.tgz", - "integrity": "sha512-0vWLNK2D5MT9dg0iOo8GlKguPAU02QjmZitPEsXRuJXU/OGIOt9vT9Fc26wtYuavLxtO45v9PGleoL9Z0k1LHg==", - "dev": true - }, - "node_modules/@types/superagent": { - "version": "4.1.18", - "resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-4.1.18.tgz", - "integrity": "sha512-LOWgpacIV8GHhrsQU+QMZuomfqXiqzz3ILLkCtKx3Us6AmomFViuzKT9D693QTKgyut2oCytMG8/efOop+DB+w==", - "dev": true, - "dependencies": { - "@types/cookiejar": "*", - "@types/node": "*" - } - }, - "node_modules/@types/supertest": { - "version": "2.0.12", - "resolved": "https://registry.npmjs.org/@types/supertest/-/supertest-2.0.12.tgz", - "integrity": "sha512-X3HPWTwXRerBZS7Mo1k6vMVR1Z6zmJcDVn5O/31whe0tnjE4te6ZJSJGq1RiqHPjzPdMTfjCFogDJmwng9xHaQ==", - "dev": true, - "dependencies": { - "@types/superagent": "*" - } - }, - "node_modules/@types/uuid": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-10.0.0.tgz", - "integrity": "sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==", - "dev": true - }, - "node_modules/@types/ws": { - "version": "8.18.1", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz", - "integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.16.0.tgz", - "integrity": "sha512-py1miT6iQpJcs1BiJjm54AMzeuMPBSPuKPlnT8HlfudbcS5rYeX5jajpLf3mrdRh9dA/Ec2FVUY0ifeVNDIhZw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "7.16.0", - "@typescript-eslint/type-utils": "7.16.0", - "@typescript-eslint/utils": "7.16.0", - "@typescript-eslint/visitor-keys": "7.16.0", - "graphemer": "^1.4.0", - "ignore": "^5.3.1", - "natural-compare": "^1.4.0", - "ts-api-utils": "^1.3.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^7.0.0", - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/parser": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.16.0.tgz", - "integrity": "sha512-ar9E+k7CU8rWi2e5ErzQiC93KKEFAXA2Kky0scAlPcxYblLt8+XZuHUZwlyfXILyQa95P6lQg+eZgh/dDs3+Vw==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "@typescript-eslint/scope-manager": "7.16.0", - "@typescript-eslint/types": "7.16.0", - "@typescript-eslint/typescript-estree": "7.16.0", - "@typescript-eslint/visitor-keys": "7.16.0", - "debug": "^4.3.4" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.16.0.tgz", - "integrity": "sha512-8gVv3kW6n01Q6TrI1cmTZ9YMFi3ucDT7i7aI5lEikk2ebk1AEjrwX8MDTdaX5D7fPXMBLvnsaa0IFTAu+jcfOw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "7.16.0", - "@typescript-eslint/visitor-keys": "7.16.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/type-utils": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.16.0.tgz", - "integrity": "sha512-j0fuUswUjDHfqV/UdW6mLtOQQseORqfdmoBNDFOqs9rvNVR2e+cmu6zJu/Ku4SDuqiJko6YnhwcL8x45r8Oqxg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/typescript-estree": "7.16.0", - "@typescript-eslint/utils": "7.16.0", - "debug": "^4.3.4", - "ts-api-utils": "^1.3.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/types": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.16.0.tgz", - "integrity": "sha512-fecuH15Y+TzlUutvUl9Cc2XJxqdLr7+93SQIbcZfd4XRGGKoxyljK27b+kxKamjRkU7FYC6RrbSCg0ALcZn/xw==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.16.0.tgz", - "integrity": "sha512-a5NTvk51ZndFuOLCh5OaJBELYc2O3Zqxfl3Js78VFE1zE46J2AaVuW+rEbVkQznjkmlzWsUI15BG5tQMixzZLw==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "@typescript-eslint/types": "7.16.0", - "@typescript-eslint/visitor-keys": "7.16.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "minimatch": "^9.0.4", - "semver": "^7.6.0", - "ts-api-utils": "^1.3.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@typescript-eslint/utils": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.16.0.tgz", - "integrity": "sha512-PqP4kP3hb4r7Jav+NiRCntlVzhxBNWq6ZQ+zQwII1y/G/1gdIPeYDCKr2+dH6049yJQsWZiHU6RlwvIFBXXGNA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "7.16.0", - "@typescript-eslint/types": "7.16.0", - "@typescript-eslint/typescript-estree": "7.16.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" - } - }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.16.0.tgz", - "integrity": "sha512-rMo01uPy9C7XxG7AFsxa8zLnWXTF8N3PYclekWSrurvhwiw1eW88mrKiAYe6s53AUY57nTRz8dJsuuXdkAhzCg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "7.16.0", - "eslint-visitor-keys": "^3.4.3" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@ungap/structured-clone": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", - "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", - "dev": true - }, - "node_modules/@vitest/expect": { - "version": "4.0.13", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.0.13.tgz", - "integrity": "sha512-zYtcnNIBm6yS7Gpr7nFTmq8ncowlMdOJkWLqYvhr/zweY6tFbDkDi8BPPOeHxEtK1rSI69H7Fd4+1sqvEGli6w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@standard-schema/spec": "^1.0.0", - "@types/chai": "^5.2.2", - "@vitest/spy": "4.0.13", - "@vitest/utils": "4.0.13", - "chai": "^6.2.1", - "tinyrainbow": "^3.0.3" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/mocker": { - "version": "4.0.13", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.0.13.tgz", - "integrity": "sha512-eNCwzrI5djoauklwP1fuslHBjrbR8rqIVbvNlAnkq1OTa6XT+lX68mrtPirNM9TnR69XUPt4puBCx2Wexseylg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/spy": "4.0.13", - "estree-walker": "^3.0.3", - "magic-string": "^0.30.21" - }, - "funding": { - "url": "https://opencollective.com/vitest" - }, - "peerDependencies": { - "msw": "^2.4.9", - "vite": "^6.0.0 || ^7.0.0-0" - }, - "peerDependenciesMeta": { - "msw": { - "optional": true - }, - "vite": { - "optional": true - } - } - }, - "node_modules/@vitest/pretty-format": { - "version": "4.0.13", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.0.13.tgz", - "integrity": "sha512-ooqfze8URWbI2ozOeLDMh8YZxWDpGXoeY3VOgcDnsUxN0jPyPWSUvjPQWqDGCBks+opWlN1E4oP1UYl3C/2EQA==", - "dev": true, - "license": "MIT", - "dependencies": { - "tinyrainbow": "^3.0.3" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/runner": { - "version": "4.0.13", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.0.13.tgz", - "integrity": "sha512-9IKlAru58wcVaWy7hz6qWPb2QzJTKt+IOVKjAx5vb5rzEFPTL6H4/R9BMvjZ2ppkxKgTrFONEJFtzvnyEpiT+A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/utils": "4.0.13", - "pathe": "^2.0.3" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/snapshot": { - "version": "4.0.13", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.0.13.tgz", - "integrity": "sha512-hb7Usvyika1huG6G6l191qu1urNPsq1iFc2hmdzQY3F5/rTgqQnwwplyf8zoYHkpt7H6rw5UfIw6i/3qf9oSxQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/pretty-format": "4.0.13", - "magic-string": "^0.30.21", - "pathe": "^2.0.3" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/spy": { - "version": "4.0.13", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.0.13.tgz", - "integrity": "sha512-hSu+m4se0lDV5yVIcNWqjuncrmBgwaXa2utFLIrBkQCQkt+pSwyZTPFQAZiiF/63j8jYa8uAeUZ3RSfcdWaYWw==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/utils": { - "version": "4.0.13", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.0.13.tgz", - "integrity": "sha512-ydozWyQ4LZuu8rLp47xFUWis5VOKMdHjXCWhs1LuJsTNKww+pTHQNK4e0assIB9K80TxFyskENL6vCu3j34EYA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/pretty-format": "4.0.13", - "tinyrainbow": "^3.0.3" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "dev": true - }, - "node_modules/abort-controller": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", - "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", - "dev": true, - "license": "MIT", - "dependencies": { - "event-target-shim": "^5.0.0" - }, - "engines": { - "node": ">=6.5" - } - }, - "node_modules/accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", - "dev": true, - "dependencies": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/acorn": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", - "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", - "dev": true, - "license": "MIT", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/acorn-walk": { - "version": "8.3.4", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", - "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", - "dev": true, - "license": "MIT", - "dependencies": { - "acorn": "^8.11.0" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ansi-colors": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", - "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/append-field": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", - "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==", - "dev": true, - "license": "MIT" - }, - "node_modules/arg": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true - }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "node_modules/array-buffer-byte-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", - "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.5", - "is-array-buffer": "^3.0.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array-flatten": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-3.0.0.tgz", - "integrity": "sha512-zPMVc3ZYlGLNk4mpK1NzP2wg0ml9t7fUgDsayR5Y5rSzxQilzR9FGu/EH2jQOcKSAeAfWeylyW8juy3OkWRvNA==", - "license": "MIT" - }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/asap": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", - "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", - "dev": true, - "license": "MIT" - }, - "node_modules/assertion-error": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", - "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - } - }, - "node_modules/async-mutex": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/async-mutex/-/async-mutex-0.5.0.tgz", - "integrity": "sha512-1A94B18jkJ3DYq284ohPxoXbfTA5HsQ7/Mf4DEhcyLx3Bz27Rh59iScbB6EPiP+B+joue6YCxcMXSbFC1tZKwA==", - "dev": true, - "license": "MIT", - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "dev": true, - "license": "MIT" - }, - "node_modules/available-typed-arrays": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", - "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", - "license": "MIT", - "dependencies": { - "possible-typed-array-names": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/axios": { - "version": "1.12.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.12.2.tgz", - "integrity": "sha512-vMJzPewAlRyOgxV2dU0Cuz2O8zzzx9VYtbJOaBgXFeLc4IV/Eg50n4LowmehOOR61S8ZMpc2K5Sa7g6A4jfkUw==", - "dev": true, - "license": "MIT", - "dependencies": { - "follow-redirects": "^1.15.6", - "form-data": "^4.0.4", - "proxy-from-env": "^1.1.0" - } - }, - "node_modules/babel-eslint": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-10.1.0.tgz", - "integrity": "sha512-ifWaTHQ0ce+448CYop8AdrQiBsGrnC+bMgfyKFdi6EsPLTAWG+QfyDeM6OH+FmWnKvEq5NnBMLvlBUPKQZoDSg==", - "deprecated": "babel-eslint is now @babel/eslint-parser. This package will no longer receive updates.", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.0.0", - "@babel/parser": "^7.7.0", - "@babel/traverse": "^7.7.0", - "@babel/types": "^7.7.0", - "eslint-visitor-keys": "^1.0.0", - "resolve": "^1.12.0" - }, - "engines": { - "node": ">=6" - }, - "peerDependencies": { - "eslint": ">= 4.12.1" - } - }, - "node_modules/babel-eslint/node_modules/eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/basic-auth": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", - "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", - "dev": true, - "dependencies": { - "safe-buffer": "5.1.2" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/basic-auth/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/bcryptjs": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-3.0.2.tgz", - "integrity": "sha512-k38b3XOZKv60C4E2hVsXTolJWfkGRMbILBIe2IBITXciy5bOsTKot5kDrf3ZfufQtQOUN5mXceUEpU1rTl9Uog==", - "dev": true, - "license": "BSD-3-Clause", - "bin": { - "bcrypt": "bin/bcrypt" - } - }, - "node_modules/bl": { - "version": "6.1.4", - "resolved": "https://registry.npmjs.org/bl/-/bl-6.1.4.tgz", - "integrity": "sha512-ZV/9asSuknOExbM/zPPA8z00lc1ihPKWaStHkkQrxHNeYx+yY+TmF+v80dpv2G0mv3HVXBu7ryoAsxbFFhf4eg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/readable-stream": "^4.0.0", - "buffer": "^6.0.3", - "inherits": "^2.0.4", - "readable-stream": "^4.2.0" - } - }, - "node_modules/body-parser": { - "version": "1.20.3", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", - "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", - "dev": true, - "license": "MIT", - "dependencies": { - "bytes": "3.1.2", - "content-type": "~1.0.5", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.13.0", - "raw-body": "2.5.2", - "type-is": "~1.6.18", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/body-parser/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/body-parser/node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/body-parser/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "node_modules/bonjour-hap": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/bonjour-hap/-/bonjour-hap-3.9.1.tgz", - "integrity": "sha512-ubpbZSBwRyAx2+j5RLKFO+QuRvB02s+7rinC0rQzICx9hEc0zryjRz56Rr9lxoW7UkE/mnZ4rP4mnTCF4/iUkg==", - "license": "MIT", - "dependencies": { - "array-flatten": "^3.0.0", - "deep-equal": "^2.2.3", - "multicast-dns": "^7.2.5", - "multicast-dns-service-types": "^1.1.0" - } - }, - "node_modules/boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", - "dev": true, - "license": "ISC" - }, - "node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "dev": true, - "dependencies": { - "fill-range": "^7.1.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" - }, - "node_modules/busboy": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", - "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", - "dev": true, - "dependencies": { - "streamsearch": "^1.1.0" - }, - "engines": { - "node": ">=10.16.0" - } - }, - "node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/cacheable-lookup": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-7.0.0.tgz", - "integrity": "sha512-+qJyx4xiKra8mZrcwhjMRMUhD5NR1R8esPkzIYxX96JiecFoxAXFuz/GpR3+ev4PE1WamHip78wV0vcmPQtp8w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14.16" - } - }, - "node_modules/cacheable-request": { - "version": "10.2.14", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-10.2.14.tgz", - "integrity": "sha512-zkDT5WAF4hSSoUgyfg5tFIxz8XQK+25W/TLVojJTMKBaxevLBBtLxgqguAuVQB8PVW79FVjHcU+GJ9tVbDZ9mQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/http-cache-semantics": "^4.0.2", - "get-stream": "^6.0.1", - "http-cache-semantics": "^4.1.1", - "keyv": "^4.5.3", - "mimic-response": "^4.0.0", - "normalize-url": "^8.0.0", - "responselike": "^3.0.0" - }, - "engines": { - "node": ">=14.16" - } - }, - "node_modules/call-bind": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", - "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", - "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/chai": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/chai/-/chai-6.2.1.tgz", - "integrity": "sha512-p4Z49OGG5W/WBCPSS/dH3jQ73kD6tiMmUM+bckNK6Jr5JHMG3k9bg/BvKR8lKmtVBKmOiuVaV2ws8s9oSbwysg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - } - }, - "node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/cheerio": { - "version": "1.0.0-rc.10", - "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.10.tgz", - "integrity": "sha512-g0J0q/O6mW8z5zxQ3A8E8J1hUgp4SMOvEoW/x84OwyHKe/Zccz83PVT4y5Crcr530FV6NgmKI1qvGTKVl9XXVw==", - "dev": true, - "license": "MIT", - "dependencies": { - "cheerio-select": "^1.5.0", - "dom-serializer": "^1.3.2", - "domhandler": "^4.2.0", - "htmlparser2": "^6.1.0", - "parse5": "^6.0.1", - "parse5-htmlparser2-tree-adapter": "^6.0.1", - "tslib": "^2.2.0" - }, - "engines": { - "node": ">= 6" - }, - "funding": { - "url": "https://github.com/cheeriojs/cheerio?sponsor=1" - } - }, - "node_modules/cheerio-select": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-1.6.0.tgz", - "integrity": "sha512-eq0GdBvxVFbqWgmCm7M3XGs1I8oLy/nExUnh6oLqmBditPO9AqQJrkslDpMun/hZ0yyTs8L0m85OHp4ho6Qm9g==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "css-select": "^4.3.0", - "css-what": "^6.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.3.1", - "domutils": "^2.8.0" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/chownr": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", - "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", - "dev": true, - "license": "BlueOak-1.0.0", - "engines": { - "node": ">=18" - } - }, - "node_modules/cli-table": { - "version": "0.3.11", - "resolved": "https://registry.npmjs.org/cli-table/-/cli-table-0.3.11.tgz", - "integrity": "sha512-IqLQi4lO0nIB4tcdTpN4LCB9FI3uqrJZK7RC515EnhZ6qBaglkIgICb1wjeAqpdoOabm1+SuQtkXIPdYC93jhQ==", - "dev": true, - "dependencies": { - "colors": "1.0.3" - }, - "engines": { - "node": ">= 0.2.0" - } - }, - "node_modules/clone": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", - "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==", - "dev": true, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "node_modules/colors": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", - "integrity": "sha512-pFGrxThWcWQ2MsAz6RtgeWe4NK2kUE1WfsrvvlctdII745EW9I0yflqhe7++M5LEc7bV2c/9/5zc8sFcpL0Drw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.1.90" - } - }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, - "license": "MIT", - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/commist": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/commist/-/commist-3.2.0.tgz", - "integrity": "sha512-4PIMoPniho+LqXmpS5d3NuGYncG6XWlkBSVGiWycL22dd42OYdUGil2CWuzklaJoNxyxUSpO4MKIBU94viWNAw==", - "dev": true, - "license": "MIT" - }, - "node_modules/component-emitter": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.1.tgz", - "integrity": "sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true - }, - "node_modules/concat-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", - "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", - "dev": true, - "engines": [ - "node >= 6.0" - ], - "license": "MIT", - "dependencies": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^3.0.2", - "typedarray": "^0.0.6" - } - }, - "node_modules/concat-stream/node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, - "license": "MIT", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/content-disposition": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", - "dev": true, - "dependencies": { - "safe-buffer": "5.2.1" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/content-type": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", - "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", - "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie-parser": { - "version": "1.4.7", - "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.7.tgz", - "integrity": "sha512-nGUvgXnotP3BsjiLX2ypbQnWoGUPIIfHQNZkkC668ntrzGWEZVW70HDEB1qnNGMicPje6EttlIgzo51YSwNQGw==", - "dev": true, - "license": "MIT", - "dependencies": { - "cookie": "0.7.2", - "cookie-signature": "1.0.6" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", - "dev": true - }, - "node_modules/cookiejar": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.4.tgz", - "integrity": "sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==", - "dev": true, - "license": "MIT" - }, - "node_modules/cors": { - "version": "2.8.5", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", - "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", - "dev": true, - "license": "MIT", - "dependencies": { - "object-assign": "^4", - "vary": "^1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/create-require": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", - "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "dev": true - }, - "node_modules/cronosjs": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/cronosjs/-/cronosjs-1.7.1.tgz", - "integrity": "sha512-d6S6+ep7dJxsAG8OQQCdKuByI/S/AV64d9OF5mtmcykOyPu92cAkAnF3Tbc9s5oOaLQBYYQmTNvjqYRkPJ/u5Q==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/cross-spawn": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", - "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", - "dev": true, - "license": "MIT", - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/css-select": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", - "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "boolbase": "^1.0.0", - "css-what": "^6.0.1", - "domhandler": "^4.3.1", - "domutils": "^2.8.0", - "nth-check": "^2.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/css-what": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.2.2.tgz", - "integrity": "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">= 6" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/decompress-response": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", - "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "mimic-response": "^3.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/decompress-response/node_modules/mimic-response": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", - "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/deep-equal": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.3.tgz", - "integrity": "sha512-ZIwpnevOurS8bpT4192sqAowWM76JDKSHYzMLty3BZGSswgq6pBaH3DhCSW5xVAZICZyKdOBPjwww5wfgT/6PA==", - "license": "MIT", - "dependencies": { - "array-buffer-byte-length": "^1.0.0", - "call-bind": "^1.0.5", - "es-get-iterator": "^1.1.3", - "get-intrinsic": "^1.2.2", - "is-arguments": "^1.1.1", - "is-array-buffer": "^3.0.2", - "is-date-object": "^1.0.5", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", - "isarray": "^2.0.5", - "object-is": "^1.1.5", - "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.5.1", - "side-channel": "^1.0.4", - "which-boxed-primitive": "^1.0.2", - "which-collection": "^1.0.1", - "which-typed-array": "^1.1.13" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true - }, - "node_modules/defer-to-connect": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", - "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - } - }, - "node_modules/define-data-property": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", - "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", - "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/define-properties": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", - "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", - "license": "MIT", - "dependencies": { - "define-data-property": "^1.0.1", - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/del": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/del/-/del-8.0.1.tgz", - "integrity": "sha512-gPqh0mKTPvaUZGAuHbrBUYKZWBNAeHG7TU3QH5EhVwPMyKvmfJaNXhcD2jTcXsJRRcffuho4vaYweu80dRrMGA==", - "dev": true, - "license": "MIT", - "dependencies": { - "globby": "^14.0.2", - "is-glob": "^4.0.3", - "is-path-cwd": "^3.0.0", - "is-path-inside": "^4.0.0", - "p-map": "^7.0.2", - "presentable-error": "^0.0.1", - "slash": "^5.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/del-cli": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/del-cli/-/del-cli-7.0.0.tgz", - "integrity": "sha512-fRl4pWJYu9WFQH8jXdQUYvcD0IMtij9WEc7qmB7xOyJEweNJNuE7iKmqNeoOT1DbBUjtRjxlw8Y63qKBI/NQ1g==", - "dev": true, - "license": "MIT", - "dependencies": { - "del": "^8.0.1", - "meow": "^14.0.0", - "presentable-error": "^0.0.1" - }, - "bin": { - "del": "cli.js", - "del-cli": "cli.js" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/del/node_modules/globby": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-14.1.0.tgz", - "integrity": "sha512-0Ia46fDOaT7k4og1PDW4YbodWWr3scS2vAr2lTbsplOt2WkKp0vQbkI9wKis/T5LV/dqPjO3bpS/z6GTJB82LA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@sindresorhus/merge-streams": "^2.1.0", - "fast-glob": "^3.3.3", - "ignore": "^7.0.3", - "path-type": "^6.0.0", - "slash": "^5.1.0", - "unicorn-magic": "^0.3.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/del/node_modules/ignore": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", - "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/del/node_modules/is-path-inside": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-4.0.0.tgz", - "integrity": "sha512-lJJV/5dYS+RcL8uQdBDW9c9uWFLLBNRyFhnAKXw5tVqLlKZ4RMGZKv+YQ/IA3OhD+RpbJa1LLFM1FQPGyIXvOA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/del/node_modules/path-type": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-6.0.0.tgz", - "integrity": "sha512-Vj7sf++t5pBD637NSfkxpHSMfWaeig5+DKWLhcqIYx6mWQz5hdJTGDVMQiJcw1ZYkhs7AazKDGpRVji1LJCZUQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/del/node_modules/slash": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", - "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/denque": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", - "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=0.10" - } - }, - "node_modules/depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/destroy": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", - "dev": true, - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/dezalgo": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.4.tgz", - "integrity": "sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==", - "dev": true, - "license": "ISC", - "dependencies": { - "asap": "^2.0.0", - "wrappy": "1" - } - }, - "node_modules/diff": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", - "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/dns-packet": { - "version": "5.6.1", - "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz", - "integrity": "sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==", - "license": "MIT", - "dependencies": { - "@leichtgewicht/ip-codec": "^2.0.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/dom-serializer": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", - "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", - "dev": true, - "license": "MIT", - "dependencies": { - "domelementtype": "^2.0.1", - "domhandler": "^4.2.0", - "entities": "^2.0.0" - }, - "funding": { - "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" - } - }, - "node_modules/domelementtype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], - "license": "BSD-2-Clause" - }, - "node_modules/domhandler": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", - "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "domelementtype": "^2.2.0" - }, - "engines": { - "node": ">= 4" - }, - "funding": { - "url": "https://github.com/fb55/domhandler?sponsor=1" - } - }, - "node_modules/domutils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", - "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "dom-serializer": "^1.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.2.0" - }, - "funding": { - "url": "https://github.com/fb55/domutils?sponsor=1" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.1", - "es-errors": "^1.3.0", - "gopd": "^1.2.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/duplexer": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", - "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==" - }, - "node_modules/eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "dev": true, - "license": "MIT" - }, - "node_modules/ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", - "dev": true - }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/encodeurl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", - "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/enquirer": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.4.1.tgz", - "integrity": "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-colors": "^4.1.1", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/entities": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", - "dev": true, - "license": "BSD-2-Clause", - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "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==", - "license": "MIT", - "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-get-iterator": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz", - "integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==", - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", - "has-symbols": "^1.0.3", - "is-arguments": "^1.1.1", - "is-map": "^2.0.2", - "is-set": "^2.0.2", - "is-string": "^1.0.7", - "isarray": "^2.0.5", - "stop-iteration-iterator": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-module-lexer": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", - "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", - "dev": true, - "license": "MIT" - }, - "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==", - "license": "MIT", - "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==", - "dev": true, - "license": "MIT", - "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/esbuild": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz", - "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.25.12", - "@esbuild/android-arm": "0.25.12", - "@esbuild/android-arm64": "0.25.12", - "@esbuild/android-x64": "0.25.12", - "@esbuild/darwin-arm64": "0.25.12", - "@esbuild/darwin-x64": "0.25.12", - "@esbuild/freebsd-arm64": "0.25.12", - "@esbuild/freebsd-x64": "0.25.12", - "@esbuild/linux-arm": "0.25.12", - "@esbuild/linux-arm64": "0.25.12", - "@esbuild/linux-ia32": "0.25.12", - "@esbuild/linux-loong64": "0.25.12", - "@esbuild/linux-mips64el": "0.25.12", - "@esbuild/linux-ppc64": "0.25.12", - "@esbuild/linux-riscv64": "0.25.12", - "@esbuild/linux-s390x": "0.25.12", - "@esbuild/linux-x64": "0.25.12", - "@esbuild/netbsd-arm64": "0.25.12", - "@esbuild/netbsd-x64": "0.25.12", - "@esbuild/openbsd-arm64": "0.25.12", - "@esbuild/openbsd-x64": "0.25.12", - "@esbuild/openharmony-arm64": "0.25.12", - "@esbuild/sunos-x64": "0.25.12", - "@esbuild/win32-arm64": "0.25.12", - "@esbuild/win32-ia32": "0.25.12", - "@esbuild/win32-x64": "0.25.12" - } - }, - "node_modules/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", - "dev": true, - "license": "MIT" - }, - "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/eslint": { - "version": "8.56.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.56.0.tgz", - "integrity": "sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==", - "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.56.0", - "@humanwhocodes/config-array": "^0.11.13", - "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "@ungap/structured-clone": "^1.2.0", - "ajv": "^6.12.4", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", - "esquery": "^1.4.2", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", - "ignore": "^5.2.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-config-prettier": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", - "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", - "dev": true, - "bin": { - "eslint-config-prettier": "bin/cli.js" - }, - "peerDependencies": { - "eslint": ">=7.0.0" - } - }, - "node_modules/eslint-plugin-prettier": { - "version": "5.5.4", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.5.4.tgz", - "integrity": "sha512-swNtI95SToIz05YINMA6Ox5R057IMAmWZ26GqPxusAp1TZzj+IdY9tXNWWD3vkF/wEqydCONcwjTFpxybBqZsg==", - "dev": true, - "license": "MIT", - "dependencies": { - "prettier-linter-helpers": "^1.0.0", - "synckit": "^0.11.7" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint-plugin-prettier" - }, - "peerDependencies": { - "@types/eslint": ">=8.0.0", - "eslint": ">=8.0.0", - "eslint-config-prettier": ">= 7.0.0 <10.0.0 || >=10.1.0", - "prettier": ">=3.0.0" - }, - "peerDependenciesMeta": { - "@types/eslint": { - "optional": true - }, - "eslint-config-prettier": { - "optional": true - } - } - }, - "node_modules/eslint-plugin-simple-import-sort": { - "version": "12.1.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-simple-import-sort/-/eslint-plugin-simple-import-sort-12.1.1.tgz", - "integrity": "sha512-6nuzu4xwQtE3332Uz0to+TxDQYRLTKRESSc2hefVT48Zc8JthmN23Gx9lnYhu0FtkRSL1oxny3kJ2aveVhmOVA==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "eslint": ">=5.0.0" - } - }, - "node_modules/eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/eslint/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/eslint/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/eslint/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/eslint/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/globals": { - "version": "13.21.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.21.0.tgz", - "integrity": "sha512-ybyme3s4yy/t/3s35bewwXKOf7cvzfreG2lH0lZl0JB7I4GxRP2ghxOK/Nb9EkRXdbBXZLfq/p/0W2JUONB/Gg==", - "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/eslint/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/eslint/node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", - "dev": true, - "dependencies": { - "acorn": "^8.9.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/esquery": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", - "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", - "dev": true, - "dependencies": { - "estraverse": "^5.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estree-walker": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", - "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.0" - } - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/event-stream": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-4.0.1.tgz", - "integrity": "sha512-qACXdu/9VHPBzcyhdOWR5/IahhGMf0roTeZJfzz077GwylcDd90yOHLouhmv7GJ5XzPi6ekaQWd8AvPP2nOvpA==", - "dependencies": { - "duplexer": "^0.1.1", - "from": "^0.1.7", - "map-stream": "0.0.7", - "pause-stream": "^0.0.11", - "split": "^1.0.1", - "stream-combiner": "^0.2.2", - "through": "^2.3.8" - } - }, - "node_modules/event-target-shim": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", - "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.x" - } - }, - "node_modules/expect-type": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.2.2.tgz", - "integrity": "sha512-JhFGDVJ7tmDJItKhYgJCGLOWjuK9vPxiXoUFLwLDc99NlmklilbiQJwoctZtt13+xMw91MCk/REan6MWHqDjyA==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/express": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", - "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", - "dev": true, - "license": "MIT", - "dependencies": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "1.20.3", - "content-disposition": "0.5.4", - "content-type": "~1.0.4", - "cookie": "0.7.1", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "2.0.0", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "1.3.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "merge-descriptors": "1.0.3", - "methods": "~1.1.2", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.12", - "proxy-addr": "~2.0.7", - "qs": "6.13.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "0.19.0", - "serve-static": "1.16.2", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "engines": { - "node": ">= 0.10.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/express-session": { - "version": "1.18.2", - "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.18.2.tgz", - "integrity": "sha512-SZjssGQC7TzTs9rpPDuUrR23GNZ9+2+IkA/+IJWmvQilTr5OSliEHGF+D9scbIpdC6yGtTI0/VhaHoVes2AN/A==", - "dev": true, - "license": "MIT", - "dependencies": { - "cookie": "0.7.2", - "cookie-signature": "1.0.7", - "debug": "2.6.9", - "depd": "~2.0.0", - "on-headers": "~1.1.0", - "parseurl": "~1.3.3", - "safe-buffer": "5.2.1", - "uid-safe": "~2.1.5" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/express-session/node_modules/cookie-signature": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.7.tgz", - "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==", - "dev": true, - "license": "MIT" - }, - "node_modules/express-session/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/express-session/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true, - "license": "MIT" - }, - "node_modules/express/node_modules/array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", - "dev": true - }, - "node_modules/express/node_modules/cookie": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", - "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/express/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/express/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" - }, - "node_modules/fast-diff": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", - "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", - "dev": true - }, - "node_modules/fast-glob": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", - "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.8" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fast-glob/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true - }, - "node_modules/fast-safe-stringify": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", - "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", - "dev": true, - "license": "MIT" - }, - "node_modules/fast-srp-hap": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/fast-srp-hap/-/fast-srp-hap-2.0.4.tgz", - "integrity": "sha512-lHRYYaaIbMrhZtsdGTwPN82UbqD9Bv8QfOlKs+Dz6YRnByZifOh93EYmf2iEWFtkOEIqR2IK8cFD0UN5wLIWBQ==", - "engines": { - "node": ">=10.17.0" - } - }, - "node_modules/fast-unique-numbers": { - "version": "8.0.13", - "resolved": "https://registry.npmjs.org/fast-unique-numbers/-/fast-unique-numbers-8.0.13.tgz", - "integrity": "sha512-7OnTFAVPefgw2eBJ1xj2PGGR9FwYzSUso9decayHgCDX4sJkHLdcsYTytTg+tYv+wKF3U8gJuSBz2jJpQV4u/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.23.8", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.1.0" - } - }, - "node_modules/fast-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz", - "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ], - "license": "BSD-3-Clause" - }, - "node_modules/fastq": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", - "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", - "dev": true, - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, - "dependencies": { - "flat-cache": "^3.0.4" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dev": true, - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/finalhandler": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", - "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "2.6.9", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "statuses": "2.0.1", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/finalhandler/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/finalhandler/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true, - "license": "MIT" - }, - "node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", - "dev": true, - "dependencies": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/flat-cache/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/flatted": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", - "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", - "dev": true - }, - "node_modules/follow-redirects": { - "version": "1.15.11", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", - "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "license": "MIT", - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } - } - }, - "node_modules/for-each": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", - "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", - "license": "MIT", - "dependencies": { - "is-callable": "^1.1.3" - } - }, - "node_modules/foreground-child": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", - "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", - "dev": true, - "license": "ISC", - "dependencies": { - "cross-spawn": "^7.0.0", - "signal-exit": "^4.0.1" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/form-data": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz", - "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", - "dev": true, - "license": "MIT", - "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/form-data-encoder": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-2.1.4.tgz", - "integrity": "sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 14.17" - } - }, - "node_modules/formidable": { - "version": "3.5.4", - "resolved": "https://registry.npmjs.org/formidable/-/formidable-3.5.4.tgz", - "integrity": "sha512-YikH+7CUTOtP44ZTnUhR7Ic2UASBPOqmaRkRKxRbywPTe5VxF7RRCck4af9wutiZ/QKM5nME9Bie2fFaPz5Gug==", - "dev": true, - "license": "MIT", - "dependencies": { - "@paralleldrive/cuid2": "^2.2.2", - "dezalgo": "^1.0.4", - "once": "^1.4.0" - }, - "engines": { - "node": ">=14.0.0" - }, - "funding": { - "url": "https://ko-fi.com/tunnckoCore/commissions" - } - }, - "node_modules/forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/from": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", - "integrity": "sha512-twe20eF1OxVxp/ML/kq2p1uc6KvFK/+vs8WjEbeKmV2He22MKm7YF2ANIt+EOqhJ5L3K/SuuPhk0hWQDjOM23g==" - }, - "node_modules/fs-extra": { - "version": "11.3.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.0.tgz", - "integrity": "sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew==", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=14.14" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "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/functions-have-names": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", - "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/futoin-hkdf": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/futoin-hkdf/-/futoin-hkdf-1.5.3.tgz", - "integrity": "sha512-SewY5KdMpaoCeh7jachEWFsh1nNlaDjNHZXWqL5IGwtpEYHTgkr2+AMCgNwKWkcc0wpSYrZfR7he4WdmHFtDxQ==", - "engines": { - "node": ">=8" - } - }, - "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==", - "license": "MIT", - "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==", - "license": "MIT", - "dependencies": { - "dunder-proto": "^1.0.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, - "license": "MIT", - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/gopd": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", - "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/got": { - "version": "12.6.1", - "resolved": "https://registry.npmjs.org/got/-/got-12.6.1.tgz", - "integrity": "sha512-mThBblvlAF1d4O5oqyvN+ZxLAYwIJK7bpMxgYqPD9okW0C3qm5FFn7k811QrcuEBwaogR3ngOFoCfs6mRv7teQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@sindresorhus/is": "^5.2.0", - "@szmarczak/http-timer": "^5.0.1", - "cacheable-lookup": "^7.0.0", - "cacheable-request": "^10.2.8", - "decompress-response": "^6.0.0", - "form-data-encoder": "^2.1.2", - "get-stream": "^6.0.1", - "http2-wrapper": "^2.1.10", - "lowercase-keys": "^3.0.0", - "p-cancelable": "^3.0.0", - "responselike": "^3.0.0" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sindresorhus/got?sponsor=1" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true - }, - "node_modules/graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true - }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/has-bigints": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", - "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/has-property-descriptors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", - "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", - "dependencies": { - "es-define-property": "^1.0.0" - }, - "funding": { - "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==", - "license": "MIT", - "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==", - "license": "MIT", - "dependencies": { - "has-symbols": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/hash-sum": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/hash-sum/-/hash-sum-2.0.0.tgz", - "integrity": "sha512-WdZTbAByD+pHfl/g9QSsBIIwy8IT+EsPiKDs0KNX+zSHhdDLFKdZu0BQHljvO+0QI/BasbMSUa8wYNCZTvhslg==", - "dev": true, - "license": "MIT" - }, - "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "license": "MIT", - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/help-me": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/help-me/-/help-me-5.0.0.tgz", - "integrity": "sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==", - "dev": true, - "license": "MIT" - }, - "node_modules/hexy": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/hexy/-/hexy-0.3.5.tgz", - "integrity": "sha512-UCP7TIZPXz5kxYJnNOym+9xaenxCLor/JyhKieo8y8/bJWunGh9xbhy3YrgYJUQ87WwfXGm05X330DszOfINZw==", - "bin": { - "hexy": "bin/hexy_cmd.js" - }, - "engines": { - "node": ">=10.4" - } - }, - "node_modules/hpagent": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/hpagent/-/hpagent-1.2.0.tgz", - "integrity": "sha512-A91dYTeIB6NoXG+PxTQpCCDDnfHsW9kc06Lvpu1TEe9gnd6ZFeiBoRO9JvzEv6xK7EX97/dUE8g/vBMTqTS3CA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14" - } - }, - "node_modules/htmlparser2": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", - "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", - "dev": true, - "funding": [ - "https://github.com/fb55/htmlparser2?sponsor=1", - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], - "license": "MIT", - "dependencies": { - "domelementtype": "^2.0.1", - "domhandler": "^4.0.0", - "domutils": "^2.5.2", - "entities": "^2.0.0" - } - }, - "node_modules/http-cache-semantics": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", - "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==", - "dev": true, - "license": "BSD-2-Clause" - }, - "node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "dev": true, - "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/http2-wrapper": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-2.2.1.tgz", - "integrity": "sha512-V5nVw1PAOgfI3Lmeaj2Exmeg7fenjhRUgz1lPSezy1CuhPYbgQtbQj4jZfEAEMlaL+vupsvhjqCyjzob0yxsmQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "quick-lru": "^5.1.1", - "resolve-alpn": "^1.2.0" - }, - "engines": { - "node": ">=10.19.0" - } - }, - "node_modules/https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "dev": true, - "license": "MIT", - "dependencies": { - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/husky": { - "version": "9.1.7", - "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.7.tgz", - "integrity": "sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==", - "dev": true, - "license": "MIT", - "bin": { - "husky": "bin.js" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/typicode" - } - }, - "node_modules/i18next": { - "version": "24.2.3", - "resolved": "https://registry.npmjs.org/i18next/-/i18next-24.2.3.tgz", - "integrity": "sha512-lfbf80OzkocvX7nmZtu7nSTNbrTYR52sLWxPtlXX1zAhVw8WEnFk4puUkCR4B1dNQwbSpEHHHemcZu//7EcB7A==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://locize.com" - }, - { - "type": "individual", - "url": "https://locize.com/i18next.html" - }, - { - "type": "individual", - "url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project" - } - ], - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.26.10" - }, - "peerDependencies": { - "typescript": "^5" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, - "license": "MIT", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "BSD-3-Clause" - }, - "node_modules/ignore": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", - "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true, - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dev": true, - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "node_modules/internal-slot": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", - "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "hasown": "^2.0.0", - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/ip-address": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.1.0.tgz", - "integrity": "sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 12" - } - }, - "node_modules/ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/is-arguments": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", - "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-array-buffer": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", - "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-bigint": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", - "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", - "license": "MIT", - "dependencies": { - "has-bigints": "^1.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-boolean-object": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", - "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-callable": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", - "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-core-module": { - "version": "2.13.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz", - "integrity": "sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==", - "dev": true, - "dependencies": { - "has": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-date-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", - "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", - "license": "MIT", - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-map": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", - "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-number-object": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", - "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", - "license": "MIT", - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-path-cwd": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-3.0.0.tgz", - "integrity": "sha512-kyiNFFLU0Ampr6SDZitD/DwUo4Zs1nSdnygUBqsu3LooL00Qvb5j+UnvApUn/TTj1J3OuE6BTdQ5rudKmU2ZaA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-regex": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", - "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-set": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", - "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-shared-array-buffer": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", - "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-string": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", - "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", - "license": "MIT", - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-symbol": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", - "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", - "license": "MIT", - "dependencies": { - "has-symbols": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-utf8": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha512-rMYPYvCzsXywIsldgLaSoPlw5PfoB/ssr7hY4pLfcodrA5M/eArza1a9VmTiNIBNMjOGr1Ow9mTyU2o69U6U9Q==", - "dev": true, - "license": "MIT" - }, - "node_modules/is-weakmap": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", - "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-weakset": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.3.tgz", - "integrity": "sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ==", - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "get-intrinsic": "^1.2.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "license": "MIT" - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true - }, - "node_modules/jackspeak": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", - "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" - } - }, - "node_modules/js-sdsl": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", - "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==", - "dev": true, - "license": "MIT", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/js-sdsl" - } - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true, - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/json-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true - }, - "node_modules/json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", - "dev": true, - "license": "ISC" - }, - "node_modules/jsonata": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/jsonata/-/jsonata-2.0.5.tgz", - "integrity": "sha512-wEse9+QLIIU5IaCgtJCPsFi/H4F3qcikWzF4bAELZiRz08ohfx3Q6CjDRf4ZPF5P/92RI3KIHtb7u3jqPaHXdQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/jsonfile": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", - "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", - "dev": true, - "license": "MIT", - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/just-extend": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.2.1.tgz", - "integrity": "sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg==", - "dev": true - }, - "node_modules/keyv": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", - "dev": true, - "license": "MIT", - "dependencies": { - "json-buffer": "3.0.1" - } - }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lodash.clonedeep": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", - "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.get": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==", - "dev": true - }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true - }, - "node_modules/long": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz", - "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==", - "license": "Apache-2.0" - }, - "node_modules/lowercase-keys": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-3.0.0.tgz", - "integrity": "sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", - "dev": true, - "license": "ISC", - "dependencies": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, - "node_modules/magic-string": { - "version": "0.30.21", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", - "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.5" - } - }, - "node_modules/make-error": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true - }, - "node_modules/map-stream": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.0.7.tgz", - "integrity": "sha512-C0X0KQmGm3N2ftbTGBhSyuydQ+vV1LC3f3zPvT3RXHXNZrvfPZcoXp/N5DOa8vedX/rTMm2CjTtivFg2STJMRQ==" - }, - "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==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/media-typer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", - "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/memorystore": { - "version": "1.6.7", - "resolved": "https://registry.npmjs.org/memorystore/-/memorystore-1.6.7.tgz", - "integrity": "sha512-OZnmNY/NDrKohPQ+hxp0muBcBKrzKNtHr55DbqSx9hLsYVNnomSAMRAtI7R64t3gf3ID7tHQA7mG4oL3Hu9hdw==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^4.3.0", - "lru-cache": "^4.0.3" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/meow": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-14.0.0.tgz", - "integrity": "sha512-JhC3R1f6dbspVtmF3vKjAWz1EVIvwFrGGPLSdU6rK79xBwHWTuHoLnRX/t1/zHS1Ch1Y2UtIrih7DAHuH9JFJA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/merge-descriptors": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", - "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/micromatch": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", - "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", - "dev": true, - "license": "MIT", - "dependencies": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/mime": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", - "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", - "dev": true, - "license": "MIT", - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mimic-response": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-4.0.0.tgz", - "integrity": "sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/minizlib": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.0.1.tgz", - "integrity": "sha512-umcy022ILvb5/3Djuu8LWeqUa8D68JaBzlttKeMWen48SjabqS3iY5w/vzeMzMUNhLDifyhbOwKDSznB1vvrwg==", - "dev": true, - "license": "MIT", - "dependencies": { - "minipass": "^7.0.4", - "rimraf": "^5.0.5" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "dependencies": { - "minimist": "^1.2.6" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, - "node_modules/moment": { - "version": "2.30.1", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", - "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", - "dev": true, - "license": "MIT", - "engines": { - "node": "*" - } - }, - "node_modules/moment-timezone": { - "version": "0.5.48", - "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.48.tgz", - "integrity": "sha512-f22b8LV1gbTO2ms2j2z13MuPogNoh5UzxL3nzNAYKGraILnbGc9NEE6dyiiiLv46DGRb8A4kg8UKWLjPthxBHw==", - "dev": true, - "license": "MIT", - "dependencies": { - "moment": "^2.29.4" - }, - "engines": { - "node": "*" - } - }, - "node_modules/mqtt": { - "version": "5.11.0", - "resolved": "https://registry.npmjs.org/mqtt/-/mqtt-5.11.0.tgz", - "integrity": "sha512-VDqfADTNvohwcY02NgxPb7OojIeDrNQ1q62r/DcM+bnIWY8LBi3nMTvdEaFEp6Bu4ejBIpHjJVthUEgnvGLemA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/readable-stream": "^4.0.18", - "@types/ws": "^8.5.14", - "commist": "^3.2.0", - "concat-stream": "^2.0.0", - "debug": "^4.4.0", - "help-me": "^5.0.0", - "lru-cache": "^10.4.3", - "minimist": "^1.2.8", - "mqtt-packet": "^9.0.2", - "number-allocator": "^1.0.14", - "readable-stream": "^4.7.0", - "reinterval": "^1.1.0", - "rfdc": "^1.4.1", - "socks": "^2.8.3", - "split2": "^4.2.0", - "worker-timers": "^7.1.8", - "ws": "^8.18.0" - }, - "bin": { - "mqtt": "build/bin/mqtt.js", - "mqtt_pub": "build/bin/pub.js", - "mqtt_sub": "build/bin/sub.js" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/mqtt-packet": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-9.0.2.tgz", - "integrity": "sha512-MvIY0B8/qjq7bKxdN1eD+nrljoeaai+qjLJgfRn3TiMuz0pamsIWY2bFODPZMSNmabsLANXsLl4EMoWvlaTZWA==", - "dev": true, - "license": "MIT", - "dependencies": { - "bl": "^6.0.8", - "debug": "^4.3.4", - "process-nextick-args": "^2.0.1" - } - }, - "node_modules/mqtt/node_modules/lru-cache": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/mqtt/node_modules/ws": { - "version": "8.18.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", - "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "license": "MIT" - }, - "node_modules/multer": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/multer/-/multer-2.0.2.tgz", - "integrity": "sha512-u7f2xaZ/UG8oLXHvtF/oWTRvT44p9ecwBBqTwgJVq0+4BW1g8OW01TyMEGWBHbyMOYVHXslaut7qEQ1meATXgw==", - "dev": true, - "license": "MIT", - "dependencies": { - "append-field": "^1.0.0", - "busboy": "^1.6.0", - "concat-stream": "^2.0.0", - "mkdirp": "^0.5.6", - "object-assign": "^4.1.1", - "type-is": "^1.6.18", - "xtend": "^4.0.2" - }, - "engines": { - "node": ">= 10.16.0" - } - }, - "node_modules/multicast-dns": { - "version": "7.2.5", - "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz", - "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==", - "license": "MIT", - "dependencies": { - "dns-packet": "^5.2.2", - "thunky": "^1.0.2" - }, - "bin": { - "multicast-dns": "cli.js" - } - }, - "node_modules/multicast-dns-service-types": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz", - "integrity": "sha512-cnAsSVxIDsYt0v7HmC0hWZFwwXSh+E6PgCrREDuN/EsjgLwA5XRmlMHhSiDPrt6HxY1gTivEa/Zh7GtODoLevQ==", - "license": "MIT" - }, - "node_modules/mustache": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/mustache/-/mustache-4.2.0.tgz", - "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==", - "dev": true, - "license": "MIT", - "bin": { - "mustache": "bin/mustache" - } - }, - "node_modules/mute-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-1.0.0.tgz", - "integrity": "sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==", - "dev": true, - "license": "ISC", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/nanoid": { - "version": "3.3.11", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", - "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true - }, - "node_modules/negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/nise": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/nise/-/nise-5.1.4.tgz", - "integrity": "sha512-8+Ib8rRJ4L0o3kfmyVCL7gzrohyDe0cMFTBa2d364yIrEGMEoetznKJx899YxjybU6bL9SQkYPSBBs1gyYs8Xg==", - "dev": true, - "dependencies": { - "@sinonjs/commons": "^2.0.0", - "@sinonjs/fake-timers": "^10.0.2", - "@sinonjs/text-encoding": "^0.7.1", - "just-extend": "^4.0.2", - "path-to-regexp": "^1.7.0" - } - }, - "node_modules/nise/node_modules/@sinonjs/commons": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-2.0.0.tgz", - "integrity": "sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg==", - "dev": true, - "dependencies": { - "type-detect": "4.0.8" - } - }, - "node_modules/nise/node_modules/@sinonjs/fake-timers": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", - "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", - "dev": true, - "dependencies": { - "@sinonjs/commons": "^3.0.0" - } - }, - "node_modules/nise/node_modules/@sinonjs/fake-timers/node_modules/@sinonjs/commons": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.0.tgz", - "integrity": "sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA==", - "dev": true, - "dependencies": { - "type-detect": "4.0.8" - } - }, - "node_modules/nise/node_modules/isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==", - "dev": true - }, - "node_modules/nise/node_modules/path-to-regexp": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.9.0.tgz", - "integrity": "sha512-xIp7/apCFJuUHdDLWe8O1HIkb0kQrOMb/0u6FXQjemHn/ii5LrIzU6bdECnsiTF/GjZkMEKg1xdiZwNqDYlZ6g==", - "dev": true, - "license": "MIT", - "dependencies": { - "isarray": "0.0.1" - } - }, - "node_modules/node-persist": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/node-persist/-/node-persist-3.1.3.tgz", - "integrity": "sha512-CaFv+kSZtsc+VeDRldK1yR47k1vPLBpzYB9re2z7LIwITxwBtljMq3s8VQnnr+x3E8pQfHbc5r2IyJsBLJhtXg==", - "license": "MIT", - "engines": { - "node": ">=10.12.0" - } - }, - "node_modules/node-red": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/node-red/-/node-red-4.1.1.tgz", - "integrity": "sha512-yk8cornC+ELzbmQk8yw3KY1jS+djTMDupMOwZ85HeC+zcxJK0LNYUbJPCFI+Bm2NQny9pd863lNj9/tLwCDotg==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@node-red/editor-api": "4.1.1", - "@node-red/nodes": "4.1.1", - "@node-red/runtime": "4.1.1", - "@node-red/util": "4.1.1", - "basic-auth": "2.0.1", - "bcryptjs": "3.0.2", - "cors": "2.8.5", - "express": "4.21.2", - "fs-extra": "11.3.0", - "node-red-admin": "^4.1.2", - "nopt": "5.0.0", - "semver": "7.7.1" - }, - "bin": { - "node-red": "red.js", - "node-red-pi": "bin/node-red-pi" - }, - "engines": { - "node": ">=18.5" - }, - "optionalDependencies": { - "@node-rs/bcrypt": "1.10.7" - } - }, - "node_modules/node-red-admin": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/node-red-admin/-/node-red-admin-4.1.2.tgz", - "integrity": "sha512-Yqe3dREfZZmc/BqT3Ntg0DEXivbP3HBNYCbjDkUaakkIIrapNR8TK1vj3RgkSW6FMtpfcVXBcLGI4cA0I1zbOw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "ansi-colors": "^4.1.3", - "axios": "1.12.2", - "bcryptjs": "3.0.2", - "cli-table": "^0.3.11", - "enquirer": "^2.3.6", - "minimist": "^1.2.8", - "mustache": "^4.2.0", - "read": "^3.0.1" - }, - "bin": { - "node-red-admin": "node-red-admin.js" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@node-rs/bcrypt": "1.10.7" - } - }, - "node_modules/node-red-node-test-helper": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/node-red-node-test-helper/-/node-red-node-test-helper-0.3.5.tgz", - "integrity": "sha512-sUsg++CoO19UguqlK6j9q2VmluS7kpYgs45o+U3SAv4wW6BSoXwtuO7pJ+9KVQVmd27zwojw6uaeyLsDsRpL3Q==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "body-parser": "^1.20.3", - "express": "^4.21.0", - "semver": "^7.5.4", - "should": "^13.2.3", - "should-sinon": "^0.0.6", - "sinon": "^11.1.2", - "stoppable": "^1.1.0", - "supertest": "^7.1.4" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/node-red/node_modules/semver": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", - "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/node-watch": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/node-watch/-/node-watch-0.7.4.tgz", - "integrity": "sha512-RinNxoz4W1cep1b928fuFhvAQ5ag/+1UlMDV7rbyGthBIgsiEouS4kvRayvvboxii4m8eolKOIBo3OjDqbc+uQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/nopt": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", - "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", - "dev": true, - "dependencies": { - "abbrev": "1" - }, - "bin": { - "nopt": "bin/nopt.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/normalize-url": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-8.1.0.tgz", - "integrity": "sha512-X06Mfd/5aKsRHc0O0J5CUedwnPmnDtLF2+nq+KN9KSDlJHkPuh0JUviWjEWMe0SW/9TDdSLVPuk7L5gGTIA1/w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/nth-check": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", - "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "boolbase": "^1.0.0" - }, - "funding": { - "url": "https://github.com/fb55/nth-check?sponsor=1" - } - }, - "node_modules/number-allocator": { - "version": "1.0.14", - "resolved": "https://registry.npmjs.org/number-allocator/-/number-allocator-1.0.14.tgz", - "integrity": "sha512-OrL44UTVAvkKdOdRQZIJpLkAdjXGTRda052sN4sO77bKEzYYqWKMBjQvrJFzqygI99gL6Z4u2xctPW1tB8ErvA==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^4.3.1", - "js-sdsl": "4.3.0" - } - }, - "node_modules/oauth2orize": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/oauth2orize/-/oauth2orize-1.12.0.tgz", - "integrity": "sha512-j4XtFDQUBsvUHPjUmvmNDUDMYed2MphMIJBhyxVVe8hGCjkuYnjIsW+D9qk8c5ciXRdnk6x6tEbiO6PLeOZdCQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "2.x.x", - "uid2": "0.0.x", - "utils-merge": "1.x.x" - }, - "engines": { - "node": ">= 0.4.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/jaredhanson" - } - }, - "node_modules/oauth2orize/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/oauth2orize/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true, - "license": "MIT" - }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-inspect": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", - "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object-is": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz", - "integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==", - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.assign": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", - "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.5", - "define-properties": "^1.2.1", - "has-symbols": "^1.0.3", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "dev": true, - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/on-headers": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.1.0.tgz", - "integrity": "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/optionator": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", - "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", - "dev": true, - "dependencies": { - "@aashutoshrathi/word-wrap": "^1.2.3", - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/p-cancelable": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-3.0.0.tgz", - "integrity": "sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12.20" - } - }, - "node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-map": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-7.0.4.tgz", - "integrity": "sha512-tkAQEw8ysMzmkhgw8k+1U/iPhWNhykKnSk4Rd5zLoPJCuJaGRPo6YposrZgaxHKzDHdDWWZvE/Sk7hsL2X/CpQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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, - "license": "BlueOak-1.0.0" - }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/parse5": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", - "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", - "dev": true, - "license": "MIT" - }, - "node_modules/parse5-htmlparser2-tree-adapter": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz", - "integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==", - "dev": true, - "license": "MIT", - "dependencies": { - "parse5": "^6.0.1" - } - }, - "node_modules/parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/passport": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/passport/-/passport-0.7.0.tgz", - "integrity": "sha512-cPLl+qZpSc+ireUvt+IzqbED1cHHkDoVYMo30jbJIdOOjQ1MQYZBPiNvmi8UM6lJuOpTPXJGZQk0DtC4y61MYQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "passport-strategy": "1.x.x", - "pause": "0.0.1", - "utils-merge": "^1.0.1" - }, - "engines": { - "node": ">= 0.4.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/jaredhanson" - } - }, - "node_modules/passport-http-bearer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/passport-http-bearer/-/passport-http-bearer-1.0.1.tgz", - "integrity": "sha512-SELQM+dOTuMigr9yu8Wo4Fm3ciFfkMq5h/ZQ8ffi4ELgZrX1xh9PlglqZdcUZ1upzJD/whVyt+YWF62s3U6Ipw==", - "dev": true, - "dependencies": { - "passport-strategy": "1.x.x" - }, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/passport-oauth2-client-password": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/passport-oauth2-client-password/-/passport-oauth2-client-password-0.1.2.tgz", - "integrity": "sha512-GHQH4UtaEZvCLulAxGKHYoSsPRoPRmGsdmaZtMh5nmz80yMLQbdMA9Bg2sp4/UW3PIxJH/143hVjPTiXaNngTQ==", - "dev": true, - "dependencies": { - "passport-strategy": "1.x.x" - }, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/passport-strategy": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz", - "integrity": "sha512-CB97UUvDKJde2V0KDWWB3lyf6PC3FaZP7YxZ2G8OAtn9p4HI9j9JLP9qjOGZFvyl8uwNT8qM+hGnz/n16NI7oA==", - "dev": true, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "node_modules/path-scurry": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", - "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "lru-cache": "^10.2.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" - }, - "engines": { - "node": ">=16 || 14 >=14.18" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/path-scurry/node_modules/lru-cache": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/path-to-regexp": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", - "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/pathe": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", - "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", - "dev": true, - "license": "MIT" - }, - "node_modules/pause": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", - "integrity": "sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg==", - "dev": true - }, - "node_modules/pause-stream": { - "version": "0.0.11", - "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", - "integrity": "sha512-e3FBlXLmN/D1S+zHzanP4E/4Z60oFAa3O051qt1pxa7DEJWKAyil6upYVXCWadEnuoqa4Pkc9oUx9zsxYeRv8A==", - "dependencies": { - "through": "~2.3" - } - }, - "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true, - "license": "ISC" - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/possible-typed-array-names": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", - "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/postcss": { - "version": "8.5.6", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", - "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "nanoid": "^3.3.11", - "picocolors": "^1.1.1", - "source-map-js": "^1.2.1" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/presentable-error": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/presentable-error/-/presentable-error-0.0.1.tgz", - "integrity": "sha512-E6rsNU1QNJgB3sjj7OANinGncFKuK+164sLXw1/CqBjj/EkXSoSdHCtWQGBNlREIGLnL7IEUEGa08YFVUbrhVg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/prettier": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz", - "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==", - "dev": true, - "license": "MIT", - "bin": { - "prettier": "bin/prettier.cjs" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" - } - }, - "node_modules/prettier-linter-helpers": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", - "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", - "dev": true, - "dependencies": { - "fast-diff": "^1.1.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/process": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6.0" - } - }, - "node_modules/process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true, - "license": "MIT" - }, - "node_modules/proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", - "dev": true, - "dependencies": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", - "dev": true, - "license": "MIT" - }, - "node_modules/pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/q": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/q/-/q-1.1.2.tgz", - "integrity": "sha512-ROtylwux7Vkc4C07oKE/ReigUmb33kVoLtcR4SJ1QVqwaZkBEDL3vX4/kwFzIERQ5PfCl0XafbU8u2YUhyGgVA==", - "deprecated": "You or someone you depend on is using Q, the JavaScript Promise library that gave JavaScript developers strong feelings about promises. They can almost certainly migrate to the native JavaScript promise now. Thank you literally everyone for joining me in this bet against the odds. Be excellent to each other.\n\n(For a CapTP with native promises, see @endo/eventual-send and @endo/captp)", - "engines": { - "node": ">=0.6.0", - "teleport": ">=0.2.0" - } - }, - "node_modules/qs": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", - "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "side-channel": "^1.0.6" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/quick-lru": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", - "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/random-bytes": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", - "integrity": "sha512-iv7LhNVO047HzYR3InF6pUcUsPQiHTM1Qal51DcGSuZFBil1aBBWG5eHPNek7bvILMaYJ/8RU1e8w1AMdHmLQQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/raw-body": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", - "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", - "dev": true, - "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/raw-body/node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/read": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/read/-/read-3.0.1.tgz", - "integrity": "sha512-SLBrDU/Srs/9EoWhU5GdbAoxG1GzpQHo/6qiGItaoLJ1thmYpcNIM1qISEUvyHBzfGlWIyd6p2DNi1oV1VmAuw==", - "dev": true, - "license": "ISC", - "dependencies": { - "mute-stream": "^1.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/readable-stream": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz", - "integrity": "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==", - "dev": true, - "license": "MIT", - "dependencies": { - "abort-controller": "^3.0.0", - "buffer": "^6.0.3", - "events": "^3.3.0", - "process": "^0.11.10", - "string_decoder": "^1.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/regexp.prototype.flags": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", - "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==", - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.6", - "define-properties": "^1.2.1", - "es-errors": "^1.3.0", - "set-function-name": "^2.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/reinterval": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/reinterval/-/reinterval-1.1.0.tgz", - "integrity": "sha512-QIRet3SYrGp0HUHO88jVskiG6seqUGC5iAG7AwI/BV4ypGcuqk9Du6YQBUOUqm9c8pw1eyLoIaONifRua1lsEQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/resolve": { - "version": "1.22.4", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.4.tgz", - "integrity": "sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg==", - "dev": true, - "dependencies": { - "is-core-module": "^2.13.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/resolve-alpn": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", - "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", - "dev": true, - "license": "MIT" - }, - "node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/responselike": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-3.0.0.tgz", - "integrity": "sha512-40yHxbNcl2+rzXvZuVkrYohathsSJlMTXKryG5y8uciHv1+xDLHQpgjG64JUO9nrEq2jGLH6IZ8BcZyw3wrweg==", - "dev": true, - "license": "MIT", - "dependencies": { - "lowercase-keys": "^3.0.0" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true, - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rfdc": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", - "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", - "dev": true, - "license": "MIT" - }, - "node_modules/rimraf": { - "version": "5.0.10", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.10.tgz", - "integrity": "sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "glob": "^10.3.7" - }, - "bin": { - "rimraf": "dist/esm/bin.mjs" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/rimraf/node_modules/brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/rimraf/node_modules/glob": { - "version": "10.5.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", - "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", - "dev": true, - "license": "ISC", - "dependencies": { - "foreground-child": "^3.1.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/esm/bin.mjs" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/rimraf/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/rollup": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.53.3.tgz", - "integrity": "sha512-w8GmOxZfBmKknvdXU1sdM9NHcoQejwF/4mNgj2JuEEdRaHwwF12K7e9eXn1nLZ07ad+du76mkVsyeb2rKGllsA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "1.0.8" - }, - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=18.0.0", - "npm": ">=8.0.0" - }, - "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.53.3", - "@rollup/rollup-android-arm64": "4.53.3", - "@rollup/rollup-darwin-arm64": "4.53.3", - "@rollup/rollup-darwin-x64": "4.53.3", - "@rollup/rollup-freebsd-arm64": "4.53.3", - "@rollup/rollup-freebsd-x64": "4.53.3", - "@rollup/rollup-linux-arm-gnueabihf": "4.53.3", - "@rollup/rollup-linux-arm-musleabihf": "4.53.3", - "@rollup/rollup-linux-arm64-gnu": "4.53.3", - "@rollup/rollup-linux-arm64-musl": "4.53.3", - "@rollup/rollup-linux-loong64-gnu": "4.53.3", - "@rollup/rollup-linux-ppc64-gnu": "4.53.3", - "@rollup/rollup-linux-riscv64-gnu": "4.53.3", - "@rollup/rollup-linux-riscv64-musl": "4.53.3", - "@rollup/rollup-linux-s390x-gnu": "4.53.3", - "@rollup/rollup-linux-x64-gnu": "4.53.3", - "@rollup/rollup-linux-x64-musl": "4.53.3", - "@rollup/rollup-openharmony-arm64": "4.53.3", - "@rollup/rollup-win32-arm64-msvc": "4.53.3", - "@rollup/rollup-win32-ia32-msvc": "4.53.3", - "@rollup/rollup-win32-x64-gnu": "4.53.3", - "@rollup/rollup-win32-x64-msvc": "4.53.3", - "fsevents": "~2.3.2" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true - }, - "node_modules/sax": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz", - "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==" - }, - "node_modules/semver": { - "version": "7.7.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", - "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/send": { - "version": "0.19.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", - "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "2.4.1", - "range-parser": "~1.2.1", - "statuses": "2.0.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/send/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/send/node_modules/debug/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true, - "license": "MIT" - }, - "node_modules/send/node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/send/node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "dev": true, - "license": "MIT", - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/serve-static": { - "version": "1.16.2", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", - "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", - "dev": true, - "license": "MIT", - "dependencies": { - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.19.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/set-function-length": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.1.tgz", - "integrity": "sha512-j4t6ccc+VsKwYHso+kElc5neZpjtq9EnRICFZtWyBsLojhmeF/ZBd/elqm22WJh/BziDe/SBiOeAt0m2mfLD0g==", - "dependencies": { - "define-data-property": "^1.1.2", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.3", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/set-function-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", - "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", - "license": "MIT", - "dependencies": { - "define-data-property": "^1.1.4", - "es-errors": "^1.3.0", - "functions-have-names": "^1.2.3", - "has-property-descriptors": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", - "dev": true - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/should": { - "version": "13.2.3", - "resolved": "https://registry.npmjs.org/should/-/should-13.2.3.tgz", - "integrity": "sha512-ggLesLtu2xp+ZxI+ysJTmNjh2U0TsC+rQ/pfED9bUZZ4DKefP27D+7YJVVTvKsmjLpIi9jAa7itwDGkDDmt1GQ==", - "dev": true, - "dependencies": { - "should-equal": "^2.0.0", - "should-format": "^3.0.3", - "should-type": "^1.4.0", - "should-type-adaptors": "^1.0.1", - "should-util": "^1.0.0" - } - }, - "node_modules/should-equal": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/should-equal/-/should-equal-2.0.0.tgz", - "integrity": "sha512-ZP36TMrK9euEuWQYBig9W55WPC7uo37qzAEmbjHz4gfyuXrEUgF8cUvQVO+w+d3OMfPvSRQJ22lSm8MQJ43LTA==", - "dev": true, - "dependencies": { - "should-type": "^1.4.0" - } - }, - "node_modules/should-format": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/should-format/-/should-format-3.0.3.tgz", - "integrity": "sha512-hZ58adtulAk0gKtua7QxevgUaXTTXxIi8t41L3zo9AHvjXO1/7sdLECuHeIN2SRtYXpNkmhoUP2pdeWgricQ+Q==", - "dev": true, - "dependencies": { - "should-type": "^1.3.0", - "should-type-adaptors": "^1.0.1" - } - }, - "node_modules/should-sinon": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/should-sinon/-/should-sinon-0.0.6.tgz", - "integrity": "sha512-ScBOH5uW5QVFaONmUnIXANSR6z5B8IKzEmBP3HE5sPOCDuZ88oTMdUdnKoCVQdLcCIrRrhRLPS5YT+7H40a04g==", - "dev": true, - "peerDependencies": { - "should": ">= 8.x" - } - }, - "node_modules/should-type": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/should-type/-/should-type-1.4.0.tgz", - "integrity": "sha512-MdAsTu3n25yDbIe1NeN69G4n6mUnJGtSJHygX3+oN0ZbO3DTiATnf7XnYJdGT42JCXurTb1JI0qOBR65shvhPQ==", - "dev": true - }, - "node_modules/should-type-adaptors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/should-type-adaptors/-/should-type-adaptors-1.1.0.tgz", - "integrity": "sha512-JA4hdoLnN+kebEp2Vs8eBe9g7uy0zbRo+RMcU0EsNy+R+k049Ki+N5tT5Jagst2g7EAja+euFuoXFCa8vIklfA==", - "dev": true, - "dependencies": { - "should-type": "^1.3.0", - "should-util": "^1.0.0" - } - }, - "node_modules/should-util": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/should-util/-/should-util-1.0.1.tgz", - "integrity": "sha512-oXF8tfxx5cDk8r2kYqlkUJzZpDBqVY/II2WhvU0n9Y3XYvAYRmeaf1PvvIvTgPnv4KJ+ES5M0PyDq5Jp+Ygy2g==", - "dev": true - }, - "node_modules/side-channel": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", - "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4", - "object-inspect": "^1.13.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/siginfo": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", - "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", - "dev": true, - "license": "ISC" - }, - "node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/sinon": { - "version": "11.1.2", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-11.1.2.tgz", - "integrity": "sha512-59237HChms4kg7/sXhiRcUzdSkKuydDeTiamT/jesUVHshBgL8XAmhgFo0GfK6RruMDM/iRSij1EybmMog9cJw==", - "dev": true, - "dependencies": { - "@sinonjs/commons": "^1.8.3", - "@sinonjs/fake-timers": "^7.1.2", - "@sinonjs/samsam": "^6.0.2", - "diff": "^5.0.0", - "nise": "^5.1.0", - "supports-color": "^7.2.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/sinon" - } - }, - "node_modules/sinon/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/sinon/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/smart-buffer": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", - "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 6.0.0", - "npm": ">= 3.0.0" - } - }, - "node_modules/socks": { - "version": "2.8.7", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.7.tgz", - "integrity": "sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==", - "dev": true, - "license": "MIT", - "dependencies": { - "ip-address": "^10.0.1", - "smart-buffer": "^4.2.0" - }, - "engines": { - "node": ">= 10.0.0", - "npm": ">= 3.0.0" - } - }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/split": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", - "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", - "dependencies": { - "through": "2" - }, - "engines": { - "node": "*" - } - }, - "node_modules/split2": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", - "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">= 10.x" - } - }, - "node_modules/stackback": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", - "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", - "dev": true, - "license": "MIT" - }, - "node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/std-env": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz", - "integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==", - "dev": true, - "license": "MIT" - }, - "node_modules/stop-iteration-iterator": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz", - "integrity": "sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==", - "license": "MIT", - "dependencies": { - "internal-slot": "^1.0.4" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/stoppable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/stoppable/-/stoppable-1.1.0.tgz", - "integrity": "sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw==", - "dev": true, - "engines": { - "node": ">=4", - "npm": ">=6" - } - }, - "node_modules/stream-combiner": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.2.2.tgz", - "integrity": "sha512-6yHMqgLYDzQDcAkL+tjJDC5nSNuNIx0vZtRZeiPh7Saef7VHX9H5Ijn9l2VIol2zaNYlYEX6KyuT/237A58qEQ==", - "dependencies": { - "duplexer": "~0.1.1", - "through": "~2.3.4" - } - }, - "node_modules/streamsearch": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", - "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", - "dev": true, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, - "license": "MIT", - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, - "node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/string-width-cjs": { - "name": "string-width", - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi-cjs": { - "name": "strip-ansi", - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/superagent": { - "version": "10.2.3", - "resolved": "https://registry.npmjs.org/superagent/-/superagent-10.2.3.tgz", - "integrity": "sha512-y/hkYGeXAj7wUMjxRbB21g/l6aAEituGXM9Rwl4o20+SX3e8YOSV6BxFXl+dL3Uk0mjSL3kCbNkwURm8/gEDig==", - "dev": true, - "license": "MIT", - "dependencies": { - "component-emitter": "^1.3.1", - "cookiejar": "^2.1.4", - "debug": "^4.3.7", - "fast-safe-stringify": "^2.1.1", - "form-data": "^4.0.4", - "formidable": "^3.5.4", - "methods": "^1.1.2", - "mime": "2.6.0", - "qs": "^6.11.2" - }, - "engines": { - "node": ">=14.18.0" - } - }, - "node_modules/superagent/node_modules/mime": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", - "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", - "dev": true, - "license": "MIT", - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/supertest": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/supertest/-/supertest-7.1.4.tgz", - "integrity": "sha512-tjLPs7dVyqgItVFirHYqe2T+MfWc2VOBQ8QFKKbWTA3PU7liZR8zoSpAi/C1k1ilm9RsXIKYf197oap9wXGVYg==", - "dev": true, - "license": "MIT", - "dependencies": { - "methods": "^1.1.2", - "superagent": "^10.2.3" - }, - "engines": { - "node": ">=14.18.0" - } - }, - "node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/synckit": { - "version": "0.11.11", - "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.11.tgz", - "integrity": "sha512-MeQTA1r0litLUf0Rp/iisCaL8761lKAZHaimlbGK4j0HysC4PLfqygQj9srcs0m2RdtDYnF8UuYyKpbjHYp7Jw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@pkgr/core": "^0.2.9" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/synckit" - } - }, - "node_modules/tar": { - "version": "7.4.3", - "resolved": "https://registry.npmjs.org/tar/-/tar-7.4.3.tgz", - "integrity": "sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==", - "dev": true, - "license": "ISC", - "dependencies": { - "@isaacs/fs-minipass": "^4.0.0", - "chownr": "^3.0.0", - "minipass": "^7.1.2", - "minizlib": "^3.0.1", - "mkdirp": "^3.0.1", - "yallist": "^5.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/tar/node_modules/mkdirp": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", - "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", - "dev": true, - "license": "MIT", - "bin": { - "mkdirp": "dist/cjs/src/bin.js" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/tar/node_modules/yallist": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", - "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", - "dev": true, - "license": "BlueOak-1.0.0", - "engines": { - "node": ">=18" - } - }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true - }, - "node_modules/through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==" - }, - "node_modules/thunky": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", - "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", - "license": "MIT" - }, - "node_modules/tinybench": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", - "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", - "dev": true, - "license": "MIT" - }, - "node_modules/tinyexec": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz", - "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==", - "dev": true, - "license": "MIT" - }, - "node_modules/tinyglobby": { - "version": "0.2.15", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", - "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "fdir": "^6.5.0", - "picomatch": "^4.0.3" - }, - "engines": { - "node": ">=12.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/SuperchupuDev" - } - }, - "node_modules/tinyglobby/node_modules/fdir": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", - "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "picomatch": "^3 || ^4" - }, - "peerDependenciesMeta": { - "picomatch": { - "optional": true - } - } - }, - "node_modules/tinyglobby/node_modules/picomatch": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/tinyrainbow": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.0.3.tgz", - "integrity": "sha512-PSkbLUoxOFRzJYjjxHJt9xro7D+iilgMX/C9lawzVuYiIdcihh9DXmVibBe8lmcFrRi/VzlPjBxbN7rH24q8/Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/tldts": { - "version": "6.1.86", - "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.86.tgz", - "integrity": "sha512-WMi/OQ2axVTf/ykqCQgXiIct+mSQDFdH2fkwhPwgEwvJ1kSzZRiinb0zF2Xb8u4+OqPChmyI6MEu4EezNJz+FQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "tldts-core": "^6.1.86" - }, - "bin": { - "tldts": "bin/cli.js" - } - }, - "node_modules/tldts-core": { - "version": "6.1.86", - "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.86.tgz", - "integrity": "sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA==", - "dev": true, - "license": "MIT" - }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", - "dev": true, - "engines": { - "node": ">=0.6" - } - }, - "node_modules/tough-cookie": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.1.2.tgz", - "integrity": "sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "tldts": "^6.1.32" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/ts-api-utils": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", - "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", - "dev": true, - "engines": { - "node": ">=16" - }, - "peerDependencies": { - "typescript": ">=4.2.0" - } - }, - "node_modules/ts-node": { - "version": "10.9.2", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", - "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@cspotcode/source-map-support": "^0.8.0", - "@tsconfig/node10": "^1.0.7", - "@tsconfig/node12": "^1.0.7", - "@tsconfig/node14": "^1.0.0", - "@tsconfig/node16": "^1.0.2", - "acorn": "^8.4.1", - "acorn-walk": "^8.1.1", - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.1", - "yn": "3.1.1" - }, - "bin": { - "ts-node": "dist/bin.js", - "ts-node-cwd": "dist/bin-cwd.js", - "ts-node-esm": "dist/bin-esm.js", - "ts-node-script": "dist/bin-script.js", - "ts-node-transpile-only": "dist/bin-transpile.js", - "ts-script": "dist/bin-script-deprecated.js" - }, - "peerDependencies": { - "@swc/core": ">=1.2.50", - "@swc/wasm": ">=1.2.50", - "@types/node": "*", - "typescript": ">=2.7" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "@swc/wasm": { - "optional": true - } - } - }, - "node_modules/ts-node/node_modules/diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true, - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" - }, - "node_modules/tweetnacl": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", - "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==" - }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "dev": true, - "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/type-is/node_modules/media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==", - "dev": true, - "license": "MIT" - }, - "node_modules/typescript": { - "version": "5.9.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", - "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/uglify-js": { - "version": "3.19.3", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", - "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==", - "dev": true, - "license": "BSD-2-Clause", - "bin": { - "uglifyjs": "bin/uglifyjs" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/uid-safe": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", - "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==", - "dev": true, - "license": "MIT", - "dependencies": { - "random-bytes": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/uid2": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/uid2/-/uid2-0.0.4.tgz", - "integrity": "sha512-IevTus0SbGwQzYh3+fRsAMTVVPOoIVufzacXcHPmdlle1jUpq7BRL+mw3dgeLanvGZdwwbWhRV6XrcFNdBmjWA==", - "dev": true, - "license": "MIT" - }, - "node_modules/undici-types": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", - "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/unicorn-magic": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.3.0.tgz", - "integrity": "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true, - "license": "MIT" - }, - "node_modules/utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", - "dev": true, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/uuid": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-13.0.0.tgz", - "integrity": "sha512-XQegIaBTVUjSHliKqcnFqYypAd4S+WCYt5NIeRs6w/UAry7z8Y9j5ZwRRL4kzq9U3sD6v+85er9FvkEaBpji2w==", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "license": "MIT", - "bin": { - "uuid": "dist-node/bin/uuid" - } - }, - "node_modules/v8-compile-cache-lib": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", - "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", - "dev": true - }, - "node_modules/vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/vite": { - "version": "7.2.4", - "resolved": "https://registry.npmjs.org/vite/-/vite-7.2.4.tgz", - "integrity": "sha512-NL8jTlbo0Tn4dUEXEsUg8KeyG/Lkmc4Fnzb8JXN/Ykm9G4HNImjtABMJgkQoVjOBN/j2WAwDTRytdqJbZsah7w==", - "dev": true, - "license": "MIT", - "dependencies": { - "esbuild": "^0.25.0", - "fdir": "^6.5.0", - "picomatch": "^4.0.3", - "postcss": "^8.5.6", - "rollup": "^4.43.0", - "tinyglobby": "^0.2.15" - }, - "bin": { - "vite": "bin/vite.js" - }, - "engines": { - "node": "^20.19.0 || >=22.12.0" - }, - "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - }, - "peerDependencies": { - "@types/node": "^20.19.0 || >=22.12.0", - "jiti": ">=1.21.0", - "less": "^4.0.0", - "lightningcss": "^1.21.0", - "sass": "^1.70.0", - "sass-embedded": "^1.70.0", - "stylus": ">=0.54.8", - "sugarss": "^5.0.0", - "terser": "^5.16.0", - "tsx": "^4.8.1", - "yaml": "^2.4.2" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "jiti": { - "optional": true - }, - "less": { - "optional": true - }, - "lightningcss": { - "optional": true - }, - "sass": { - "optional": true - }, - "sass-embedded": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - }, - "tsx": { - "optional": true - }, - "yaml": { - "optional": true - } - } - }, - "node_modules/vite/node_modules/fdir": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", - "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "picomatch": "^3 || ^4" - }, - "peerDependenciesMeta": { - "picomatch": { - "optional": true - } - } - }, - "node_modules/vite/node_modules/picomatch": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/vitest": { - "version": "4.0.13", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.0.13.tgz", - "integrity": "sha512-QSD4I0fN6uZQfftryIXuqvqgBxTvJ3ZNkF6RWECd82YGAYAfhcppBLFXzXJHQAAhVFyYEuFTrq6h0hQqjB7jIQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/expect": "4.0.13", - "@vitest/mocker": "4.0.13", - "@vitest/pretty-format": "4.0.13", - "@vitest/runner": "4.0.13", - "@vitest/snapshot": "4.0.13", - "@vitest/spy": "4.0.13", - "@vitest/utils": "4.0.13", - "debug": "^4.4.3", - "es-module-lexer": "^1.7.0", - "expect-type": "^1.2.2", - "magic-string": "^0.30.21", - "pathe": "^2.0.3", - "picomatch": "^4.0.3", - "std-env": "^3.10.0", - "tinybench": "^2.9.0", - "tinyexec": "^0.3.2", - "tinyglobby": "^0.2.15", - "tinyrainbow": "^3.0.3", - "vite": "^6.0.0 || ^7.0.0", - "why-is-node-running": "^2.3.0" - }, - "bin": { - "vitest": "vitest.mjs" - }, - "engines": { - "node": "^20.0.0 || ^22.0.0 || >=24.0.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - }, - "peerDependencies": { - "@edge-runtime/vm": "*", - "@opentelemetry/api": "^1.9.0", - "@types/debug": "^4.1.12", - "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", - "@vitest/browser-playwright": "4.0.13", - "@vitest/browser-preview": "4.0.13", - "@vitest/browser-webdriverio": "4.0.13", - "@vitest/ui": "4.0.13", - "happy-dom": "*", - "jsdom": "*" - }, - "peerDependenciesMeta": { - "@edge-runtime/vm": { - "optional": true - }, - "@opentelemetry/api": { - "optional": true - }, - "@types/debug": { - "optional": true - }, - "@types/node": { - "optional": true - }, - "@vitest/browser-playwright": { - "optional": true - }, - "@vitest/browser-preview": { - "optional": true - }, - "@vitest/browser-webdriverio": { - "optional": true - }, - "@vitest/ui": { - "optional": true - }, - "happy-dom": { - "optional": true - }, - "jsdom": { - "optional": true - } - } - }, - "node_modules/vitest/node_modules/picomatch": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/which-boxed-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", - "license": "MIT", - "dependencies": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-collection": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", - "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", - "license": "MIT", - "dependencies": { - "is-map": "^2.0.3", - "is-set": "^2.0.3", - "is-weakmap": "^2.0.2", - "is-weakset": "^2.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-typed-array": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", - "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", - "license": "MIT", - "dependencies": { - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/why-is-node-running": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", - "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", - "dev": true, - "license": "MIT", - "dependencies": { - "siginfo": "^2.0.0", - "stackback": "0.0.2" - }, - "bin": { - "why-is-node-running": "cli.js" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/worker-timers": { - "version": "7.1.8", - "resolved": "https://registry.npmjs.org/worker-timers/-/worker-timers-7.1.8.tgz", - "integrity": "sha512-R54psRKYVLuzff7c1OTFcq/4Hue5Vlz4bFtNEIarpSiCYhpifHU3aIQI29S84o1j87ePCYqbmEJPqwBTf+3sfw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.24.5", - "tslib": "^2.6.2", - "worker-timers-broker": "^6.1.8", - "worker-timers-worker": "^7.0.71" - } - }, - "node_modules/worker-timers-broker": { - "version": "6.1.8", - "resolved": "https://registry.npmjs.org/worker-timers-broker/-/worker-timers-broker-6.1.8.tgz", - "integrity": "sha512-FUCJu9jlK3A8WqLTKXM9E6kAmI/dR1vAJ8dHYLMisLNB/n3GuaFIjJ7pn16ZcD1zCOf7P6H62lWIEBi+yz/zQQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.24.5", - "fast-unique-numbers": "^8.0.13", - "tslib": "^2.6.2", - "worker-timers-worker": "^7.0.71" - } - }, - "node_modules/worker-timers-worker": { - "version": "7.0.71", - "resolved": "https://registry.npmjs.org/worker-timers-worker/-/worker-timers-worker-7.0.71.tgz", - "integrity": "sha512-ks/5YKwZsto1c2vmljroppOKCivB/ma97g9y77MAAz2TBBjPPgpoOiS1qYQKIgvGTr2QYPT3XhJWIB6Rj2MVPQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.24.5", - "tslib": "^2.6.2" - } - }, - "node_modules/wrap-ansi-cjs": { - "name": "wrap-ansi", - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/wrap-ansi-cjs/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/wrap-ansi-cjs/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, - "license": "MIT" - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true - }, - "node_modules/ws": { - "version": "7.5.10", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", - "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8.3.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/xml2js": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.6.2.tgz", - "integrity": "sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA==", - "dependencies": { - "sax": ">=0.6.0", - "xmlbuilder": "~11.0.0" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/xmlbuilder": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", - "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.4" - } - }, - "node_modules/yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==", - "dev": true, - "license": "ISC" - }, - "node_modules/yn": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", - "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } + "name": "node-red-contrib-homekit-bridged", + "version": "2.0.0-dev.1", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "node-red-contrib-homekit-bridged", + "version": "2.0.0-dev.1", + "license": "Apache-2.0", + "dependencies": { + "@homebridge/hap-nodejs": "2.0.2", + "@nrchkb/logger": "~3.1.1", + "node-persist": "^3.1.3", + "semver": "~7.7.3", + "uuid": "~13.0.0" + }, + "devDependencies": { + "@biomejs/biome": "2.3.7", + "@homebridge/ciao": "~1.3.4", + "@node-red/registry": "^4.1.1", + "@types/node": "^20", + "@types/node-persist": "^3.1.8", + "@types/node-red": "^1.3.5", + "@types/node-red-node-test-helper": "^0.3.5", + "@types/semver": "^7.7.1", + "@types/uuid": "^10.0.0", + "del-cli": "^7.0.0", + "husky": "^9.1.7", + "node-red": "^4.1.1", + "node-red-node-test-helper": "^0.3.5", + "ts-node": "^10.9.2", + "typescript": "^5.9.3", + "vitest": "^4.0.13" + }, + "engines": { + "node": "^20 || ^22 || ^24" + } + }, + "node_modules/@babel/runtime": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.4.tgz", + "integrity": "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@biomejs/biome": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/@biomejs/biome/-/biome-2.3.7.tgz", + "integrity": "sha512-CTbAS/jNAiUc6rcq94BrTB8z83O9+BsgWj2sBCQg9rD6Wkh2gjfR87usjx0Ncx0zGXP1NKgT7JNglay5Zfs9jw==", + "dev": true, + "license": "MIT OR Apache-2.0", + "bin": { + "biome": "bin/biome" + }, + "engines": { + "node": ">=14.21.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/biome" + }, + "optionalDependencies": { + "@biomejs/cli-darwin-arm64": "2.3.7", + "@biomejs/cli-darwin-x64": "2.3.7", + "@biomejs/cli-linux-arm64": "2.3.7", + "@biomejs/cli-linux-arm64-musl": "2.3.7", + "@biomejs/cli-linux-x64": "2.3.7", + "@biomejs/cli-linux-x64-musl": "2.3.7", + "@biomejs/cli-win32-arm64": "2.3.7", + "@biomejs/cli-win32-x64": "2.3.7" + } + }, + "node_modules/@biomejs/cli-darwin-arm64": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-2.3.7.tgz", + "integrity": "sha512-LirkamEwzIUULhXcf2D5b+NatXKeqhOwilM+5eRkbrnr6daKz9rsBL0kNZ16Hcy4b8RFq22SG4tcLwM+yx/wFA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-darwin-x64": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-x64/-/cli-darwin-x64-2.3.7.tgz", + "integrity": "sha512-Q4TO633kvrMQkKIV7wmf8HXwF0dhdTD9S458LGE24TYgBjSRbuhvio4D5eOQzirEYg6eqxfs53ga/rbdd8nBKg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-linux-arm64": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64/-/cli-linux-arm64-2.3.7.tgz", + "integrity": "sha512-inHOTdlstUBzgjDcx0ge71U4SVTbwAljmkfi3MC5WzsYCRhancqfeL+sa4Ke6v2ND53WIwCFD5hGsYExoI3EZQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-linux-arm64-musl": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.3.7.tgz", + "integrity": "sha512-/afy8lto4CB8scWfMdt+NoCZtatBUF62Tk3ilWH2w8ENd5spLhM77zKlFZEvsKJv9AFNHknMl03zO67CiklL2Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-linux-x64": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64/-/cli-linux-x64-2.3.7.tgz", + "integrity": "sha512-fJMc3ZEuo/NaMYo5rvoWjdSS5/uVSW+HPRQujucpZqm2ZCq71b8MKJ9U4th9yrv2L5+5NjPF0nqqILCl8HY/fg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-linux-x64-musl": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64-musl/-/cli-linux-x64-musl-2.3.7.tgz", + "integrity": "sha512-CQUtgH1tIN6e5wiYSJqzSwJumHYolNtaj1dwZGCnZXm2PZU1jOJof9TsyiP3bXNDb+VOR7oo7ZvY01If0W3iFQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-win32-arm64": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-arm64/-/cli-win32-arm64-2.3.7.tgz", + "integrity": "sha512-aJAE8eCNyRpcfx2JJAtsPtISnELJ0H4xVVSwnxm13bzI8RwbXMyVtxy2r5DV1xT3WiSP+7LxORcApWw0LM8HiA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-win32-x64": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-x64/-/cli-win32-x64-2.3.7.tgz", + "integrity": "sha512-pulzUshqv9Ed//MiE8MOUeeEkbkSHVDVY5Cz5wVAnH1DUqliCQG3j6s1POaITTFqFfo7AVIx2sWdKpx/GS+Nqw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@emnapi/core": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.7.1.tgz", + "integrity": "sha512-o1uhUASyo921r2XtHYOHy7gdkGLge8ghBEQHMWmyJFoXlpU58kIrhhN3w26lpQb6dspetweapMn2CSNwQ8I4wg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.1.0", + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.7.1.tgz", + "integrity": "sha512-PVtJr5CmLwYAU9PZDMITZoR5iAOShYREoR45EyyLrbntV50mdePTgUn4AmOw90Ifcj+x2kRjdzr1HP3RrNiHGA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/wasi-threads": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.1.0.tgz", + "integrity": "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", + "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz", + "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz", + "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz", + "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz", + "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz", + "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz", + "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz", + "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz", + "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz", + "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz", + "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz", + "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz", + "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz", + "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz", + "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz", + "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz", + "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz", + "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz", + "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz", + "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz", + "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz", + "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz", + "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz", + "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz", + "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz", + "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@homebridge/ciao": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/@homebridge/ciao/-/ciao-1.3.4.tgz", + "integrity": "sha512-qK6ZgGx0wwOubq/MY6eTbhApQHBUQCvCOsTYpQE01uLvfA2/Prm6egySHlZouKaina1RPuDwfLhCmsRCxwHj3Q==", + "license": "MIT", + "dependencies": { + "debug": "^4.4.1", + "fast-deep-equal": "^3.1.3", + "source-map-support": "^0.5.21", + "tslib": "^2.8.1" + }, + "bin": { + "ciao-bcs": "lib/bonjour-conformance-testing.js" + } + }, + "node_modules/@homebridge/dbus-native": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/@homebridge/dbus-native/-/dbus-native-0.7.2.tgz", + "integrity": "sha512-BNVe6YNxiy5x/E5/ZXDIWMD6Njv9cjW59PM/1CMpYe0jLAJ8pJN+Tq/JhVs3gXwmTavz2S86/sspmHquChet8A==", + "license": "MIT", + "dependencies": { + "event-stream": "^4.0.1", + "hexy": "^0.3.5", + "long": "^5.3.2", + "minimist": "^1.2.8", + "safe-buffer": "^5.1.2", + "xml2js": "^0.6.2" + }, + "bin": { + "dbus2js": "bin/dbus2js.js" + } + }, + "node_modules/@homebridge/hap-nodejs": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@homebridge/hap-nodejs/-/hap-nodejs-2.0.2.tgz", + "integrity": "sha512-HqlMqVQ8bzh7uFqL0vNI6a5PJHAmCyPzHuPbBxf6XcPVKn02ELwCMDQ8ud5oS1fPO5z20lvV7rIfAqTbSlZ7Uw==", + "license": "Apache-2.0", + "dependencies": { + "@homebridge/ciao": "^1.3.4", + "@homebridge/dbus-native": "^0.7.2", + "bonjour-hap": "^3.9.1", + "debug": "^4.4.3", + "fast-srp-hap": "^2.0.4", + "futoin-hkdf": "^1.5.3", + "node-persist": "^0.0.12", + "source-map-support": "^0.5.21", + "tslib": "^2.8.1", + "tweetnacl": "^1.0.3" + }, + "engines": { + "node": "^20 || ^22 || ^24" + } + }, + "node_modules/@homebridge/hap-nodejs/node_modules/node-persist": { + "version": "0.0.12", + "resolved": "https://registry.npmjs.org/node-persist/-/node-persist-0.0.12.tgz", + "integrity": "sha512-Fbia3FYnURzaql53wLu0t19dmAwQg/tXT6O7YPmdwNwysNKEyFmgoT2BQlPD3XXQnYeiQVNvR5lfvufGwKuxhg==", + "license": "MIT", + "dependencies": { + "mkdirp": "~0.5.1", + "q": "~1.1.1" + } + }, + "node_modules/@isaacs/fs-minipass": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", + "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "minipass": "^7.0.4" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@leichtgewicht/ip-codec": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz", + "integrity": "sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==", + "license": "MIT" + }, + "node_modules/@napi-rs/wasm-runtime": { + "version": "0.2.12", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz", + "integrity": "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "^1.4.3", + "@emnapi/runtime": "^1.4.3", + "@tybys/wasm-util": "^0.10.0" + } + }, + "node_modules/@noble/hashes": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz", + "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@node-red/editor-api": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@node-red/editor-api/-/editor-api-4.1.1.tgz", + "integrity": "sha512-vev2s3NntphqinzP2e3WmPnQY8+cHfSrQyESis9Fy+prp+E8uSgT4yfLjHMFyT116xPMB5WIg6qSDciq5OV1tA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@node-red/editor-client": "4.1.1", + "@node-red/util": "4.1.1", + "bcryptjs": "3.0.2", + "body-parser": "1.20.3", + "clone": "2.1.2", + "cors": "2.8.5", + "express": "4.21.2", + "express-session": "1.18.2", + "memorystore": "1.6.7", + "mime": "3.0.0", + "multer": "2.0.2", + "mustache": "4.2.0", + "oauth2orize": "1.12.0", + "passport": "0.7.0", + "passport-http-bearer": "1.0.1", + "passport-oauth2-client-password": "0.1.2", + "ws": "7.5.10" + }, + "optionalDependencies": { + "@node-rs/bcrypt": "1.10.7" + } + }, + "node_modules/@node-red/editor-client": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@node-red/editor-client/-/editor-client-4.1.1.tgz", + "integrity": "sha512-JIJirftuB0NrvsFvPZXW3R16c8mLRy2UQh0AyxGU8ZQyz/dmF8auINbbGpQ4qxssBOGFWf9j4ZXP7B8EdLIOBQ==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/@node-red/nodes": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@node-red/nodes/-/nodes-4.1.1.tgz", + "integrity": "sha512-zTTwxpnPebHA5PjDBZEcsGv0BoqMJEjhf27aQIhlGed40/PaNiR0tmc5f5P6HKflmS3Iv6kiwGsY12Mjvyx/3Q==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "acorn": "8.15.0", + "acorn-walk": "8.3.4", + "ajv": "8.17.1", + "body-parser": "1.20.3", + "cheerio": "1.0.0-rc.10", + "content-type": "1.0.5", + "cookie": "0.7.2", + "cookie-parser": "1.4.7", + "cors": "2.8.5", + "cronosjs": "1.7.1", + "denque": "2.1.0", + "form-data": "4.0.4", + "fs-extra": "11.3.0", + "got": "12.6.1", + "hash-sum": "2.0.0", + "hpagent": "1.2.0", + "https-proxy-agent": "5.0.1", + "iconv-lite": "0.6.3", + "is-utf8": "0.2.1", + "js-yaml": "4.1.0", + "media-typer": "1.1.0", + "mqtt": "5.11.0", + "multer": "2.0.2", + "mustache": "4.2.0", + "node-watch": "0.7.4", + "on-headers": "1.1.0", + "raw-body": "3.0.0", + "tough-cookie": "5.1.2", + "uuid": "9.0.1", + "ws": "7.5.10", + "xml2js": "0.6.2" + } + }, + "node_modules/@node-red/nodes/node_modules/form-data": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz", + "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", + "dev": true, + "license": "MIT", + "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/@node-red/nodes/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "dev": true, + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/@node-red/registry": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@node-red/registry/-/registry-4.1.1.tgz", + "integrity": "sha512-+5SvdL+6tXzfYW63TpsfgybNP7G4farM+2div5FYYPdMJULE1D9Z8BHD/fprieU5mTTTO100CeyGXHbkzRH+Qg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@node-red/util": "4.1.1", + "clone": "2.1.2", + "fs-extra": "11.3.0", + "semver": "7.7.1", + "tar": "7.4.3", + "uglify-js": "3.19.3" + } + }, + "node_modules/@node-red/registry/node_modules/semver": { + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@node-red/runtime": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@node-red/runtime/-/runtime-4.1.1.tgz", + "integrity": "sha512-NWV+u2GrLnaPjomJilwVhl5u6WLwJN7tvHEVm5r9/8quW0H8BuYfih5AwCzCl8aly1imhe1+kfiCExSfGVaQUA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@node-red/registry": "4.1.1", + "@node-red/util": "4.1.1", + "async-mutex": "0.5.0", + "clone": "2.1.2", + "cronosjs": "1.7.1", + "express": "4.21.2", + "fs-extra": "11.3.0", + "got": "12.6.1", + "json-stringify-safe": "5.0.1", + "rfdc": "^1.3.1", + "semver": "7.7.1" + } + }, + "node_modules/@node-red/runtime/node_modules/semver": { + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@node-red/util": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@node-red/util/-/util-4.1.1.tgz", + "integrity": "sha512-gnkRXmz49rj2OXjJC/RAPbFUQvDATC3Oy6yGuhN/McPy8mmL7q4YTIflUwWKyrsd6TU3cK17JmmXtPTQBtS8jQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "chalk": "^4.1.2", + "fs-extra": "11.3.0", + "i18next": "24.2.3", + "json-stringify-safe": "5.0.1", + "jsonata": "2.0.6", + "lodash.clonedeep": "^4.5.0", + "moment": "2.30.1", + "moment-timezone": "0.5.48" + } + }, + "node_modules/@node-rs/bcrypt": { + "version": "1.10.7", + "resolved": "https://registry.npmjs.org/@node-rs/bcrypt/-/bcrypt-1.10.7.tgz", + "integrity": "sha512-1wk0gHsUQC/ap0j6SJa2K34qNhomxXRcEe3T8cI5s+g6fgHBgLTN7U9LzWTG/HE6G4+2tWWLeCabk1wiYGEQSA==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + }, + "optionalDependencies": { + "@node-rs/bcrypt-android-arm-eabi": "1.10.7", + "@node-rs/bcrypt-android-arm64": "1.10.7", + "@node-rs/bcrypt-darwin-arm64": "1.10.7", + "@node-rs/bcrypt-darwin-x64": "1.10.7", + "@node-rs/bcrypt-freebsd-x64": "1.10.7", + "@node-rs/bcrypt-linux-arm-gnueabihf": "1.10.7", + "@node-rs/bcrypt-linux-arm64-gnu": "1.10.7", + "@node-rs/bcrypt-linux-arm64-musl": "1.10.7", + "@node-rs/bcrypt-linux-x64-gnu": "1.10.7", + "@node-rs/bcrypt-linux-x64-musl": "1.10.7", + "@node-rs/bcrypt-wasm32-wasi": "1.10.7", + "@node-rs/bcrypt-win32-arm64-msvc": "1.10.7", + "@node-rs/bcrypt-win32-ia32-msvc": "1.10.7", + "@node-rs/bcrypt-win32-x64-msvc": "1.10.7" + } + }, + "node_modules/@node-rs/bcrypt-android-arm-eabi": { + "version": "1.10.7", + "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-android-arm-eabi/-/bcrypt-android-arm-eabi-1.10.7.tgz", + "integrity": "sha512-8dO6/PcbeMZXS3VXGEtct9pDYdShp2WBOWlDvSbcRwVqyB580aCBh0BEFmKYtXLzLvUK8Wf+CG3U6sCdILW1lA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@node-rs/bcrypt-android-arm64": { + "version": "1.10.7", + "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-android-arm64/-/bcrypt-android-arm64-1.10.7.tgz", + "integrity": "sha512-UASFBS/CucEMHiCtL/2YYsAY01ZqVR1N7vSb94EOvG5iwW7BQO06kXXCTgj+Xbek9azxixrCUmo3WJnkJZ0hTQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@node-rs/bcrypt-darwin-arm64": { + "version": "1.10.7", + "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-darwin-arm64/-/bcrypt-darwin-arm64-1.10.7.tgz", + "integrity": "sha512-DgzFdAt455KTuiJ/zYIyJcKFobjNDR/hnf9OS7pK5NRS13Nq4gLcSIIyzsgHwZHxsJWbLpHmFc1H23Y7IQoQBw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@node-rs/bcrypt-darwin-x64": { + "version": "1.10.7", + "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-darwin-x64/-/bcrypt-darwin-x64-1.10.7.tgz", + "integrity": "sha512-SPWVfQ6sxSokoUWAKWD0EJauvPHqOGQTd7CxmYatcsUgJ/bruvEHxZ4bIwX1iDceC3FkOtmeHO0cPwR480n/xA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@node-rs/bcrypt-freebsd-x64": { + "version": "1.10.7", + "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-freebsd-x64/-/bcrypt-freebsd-x64-1.10.7.tgz", + "integrity": "sha512-gpa+Ixs6GwEx6U6ehBpsQetzUpuAGuAFbOiuLB2oo4N58yU4AZz1VIcWyWAHrSWRs92O0SHtmo2YPrMrwfBbSw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@node-rs/bcrypt-linux-arm-gnueabihf": { + "version": "1.10.7", + "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-linux-arm-gnueabihf/-/bcrypt-linux-arm-gnueabihf-1.10.7.tgz", + "integrity": "sha512-kYgJnTnpxrzl9sxYqzflobvMp90qoAlaX1oDL7nhNTj8OYJVDIk0jQgblj0bIkjmoPbBed53OJY/iu4uTS+wig==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@node-rs/bcrypt-linux-arm64-gnu": { + "version": "1.10.7", + "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-linux-arm64-gnu/-/bcrypt-linux-arm64-gnu-1.10.7.tgz", + "integrity": "sha512-7cEkK2RA+gBCj2tCVEI1rDSJV40oLbSq7bQ+PNMHNI6jCoXGmj9Uzo7mg7ZRbNZ7piIyNH5zlJqutjo8hh/tmA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@node-rs/bcrypt-linux-arm64-musl": { + "version": "1.10.7", + "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-linux-arm64-musl/-/bcrypt-linux-arm64-musl-1.10.7.tgz", + "integrity": "sha512-X7DRVjshhwxUqzdUKDlF55cwzh+wqWJ2E/tILvZPboO3xaNO07Um568Vf+8cmKcz+tiZCGP7CBmKbBqjvKN/Pw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@node-rs/bcrypt-linux-x64-gnu": { + "version": "1.10.7", + "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-linux-x64-gnu/-/bcrypt-linux-x64-gnu-1.10.7.tgz", + "integrity": "sha512-LXRZsvG65NggPD12hn6YxVgH0W3VR5fsE/o1/o2D5X0nxKcNQGeLWnRzs5cP8KpoFOuk1ilctXQJn8/wq+Gn/Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@node-rs/bcrypt-linux-x64-musl": { + "version": "1.10.7", + "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-linux-x64-musl/-/bcrypt-linux-x64-musl-1.10.7.tgz", + "integrity": "sha512-tCjHmct79OfcO3g5q21ME7CNzLzpw1MAsUXCLHLGWH+V6pp/xTvMbIcLwzkDj6TI3mxK6kehTn40SEjBkZ3Rog==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@node-rs/bcrypt-wasm32-wasi": { + "version": "1.10.7", + "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-wasm32-wasi/-/bcrypt-wasm32-wasi-1.10.7.tgz", + "integrity": "sha512-4qXSihIKeVXYglfXZEq/QPtYtBUvR8d3S85k15Lilv3z5B6NSGQ9mYiNleZ7QHVLN2gEc5gmi7jM353DMH9GkA==", + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@napi-rs/wasm-runtime": "^0.2.5" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@node-rs/bcrypt-win32-arm64-msvc": { + "version": "1.10.7", + "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-win32-arm64-msvc/-/bcrypt-win32-arm64-msvc-1.10.7.tgz", + "integrity": "sha512-FdfUQrqmDfvC5jFhntMBkk8EI+fCJTx/I1v7Rj+Ezlr9rez1j1FmuUnywbBj2Cg15/0BDhwYdbyZ5GCMFli2aQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@node-rs/bcrypt-win32-ia32-msvc": { + "version": "1.10.7", + "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-win32-ia32-msvc/-/bcrypt-win32-ia32-msvc-1.10.7.tgz", + "integrity": "sha512-lZLf4Cx+bShIhU071p5BZft4OvP4PGhyp542EEsb3zk34U5GLsGIyCjOafcF/2DGewZL6u8/aqoxbSuROkgFXg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@node-rs/bcrypt-win32-x64-msvc": { + "version": "1.10.7", + "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-win32-x64-msvc/-/bcrypt-win32-x64-msvc-1.10.7.tgz", + "integrity": "sha512-hdw7tGmN1DxVAMTzICLdaHpXjy+4rxaxnBMgI8seG1JL5e3VcRGsd1/1vVDogVp2cbsmgq+6d6yAY+D9lW/DCg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nrchkb/logger": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@nrchkb/logger/-/logger-3.1.1.tgz", + "integrity": "sha512-37m4lq7Jemg7qzkBflD+VZ1HnFdZv10k9hgglonFXTBMrLmXxkXllWelCKDGABVkfx1hjijAz6IpQoIF+Oo9yw==", + "license": "Apache-2.0", + "dependencies": { + "debug": "^4.3.5" + } + }, + "node_modules/@paralleldrive/cuid2": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/@paralleldrive/cuid2/-/cuid2-2.3.1.tgz", + "integrity": "sha512-XO7cAxhnTZl0Yggq6jOgjiOHhbgcO4NqFqwSmQpjK3b6TEE6Uj/jfSk6wzYyemh3+I0sHirKSetjQwn5cZktFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@noble/hashes": "^1.1.5" + } + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.53.3.tgz", + "integrity": "sha512-mRSi+4cBjrRLoaal2PnqH82Wqyb+d3HsPUN/W+WslCXsZsyHa9ZeQQX/pQsZaVIWDkPcpV6jJ+3KLbTbgnwv8w==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.53.3.tgz", + "integrity": "sha512-CbDGaMpdE9sh7sCmTrTUyllhrg65t6SwhjlMJsLr+J8YjFuPmCEjbBSx4Z/e4SmDyH3aB5hGaJUP2ltV/vcs4w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.53.3.tgz", + "integrity": "sha512-Nr7SlQeqIBpOV6BHHGZgYBuSdanCXuw09hon14MGOLGmXAFYjx1wNvquVPmpZnl0tLjg25dEdr4IQ6GgyToCUA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.53.3.tgz", + "integrity": "sha512-DZ8N4CSNfl965CmPktJ8oBnfYr3F8dTTNBQkRlffnUarJ2ohudQD17sZBa097J8xhQ26AwhHJ5mvUyQW8ddTsQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.53.3.tgz", + "integrity": "sha512-yMTrCrK92aGyi7GuDNtGn2sNW+Gdb4vErx4t3Gv/Tr+1zRb8ax4z8GWVRfr3Jw8zJWvpGHNpss3vVlbF58DZ4w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.53.3.tgz", + "integrity": "sha512-lMfF8X7QhdQzseM6XaX0vbno2m3hlyZFhwcndRMw8fbAGUGL3WFMBdK0hbUBIUYcEcMhVLr1SIamDeuLBnXS+Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.53.3.tgz", + "integrity": "sha512-k9oD15soC/Ln6d2Wv/JOFPzZXIAIFLp6B+i14KhxAfnq76ajt0EhYc5YPeX6W1xJkAdItcVT+JhKl1QZh44/qw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.53.3.tgz", + "integrity": "sha512-vTNlKq+N6CK/8UktsrFuc+/7NlEYVxgaEgRXVUVK258Z5ymho29skzW1sutgYjqNnquGwVUObAaxae8rZ6YMhg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.53.3.tgz", + "integrity": "sha512-RGrFLWgMhSxRs/EWJMIFM1O5Mzuz3Xy3/mnxJp/5cVhZ2XoCAxJnmNsEyeMJtpK+wu0FJFWz+QF4mjCA7AUQ3w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.53.3.tgz", + "integrity": "sha512-kASyvfBEWYPEwe0Qv4nfu6pNkITLTb32p4yTgzFCocHnJLAHs+9LjUu9ONIhvfT/5lv4YS5muBHyuV84epBo/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.53.3.tgz", + "integrity": "sha512-JiuKcp2teLJwQ7vkJ95EwESWkNRFJD7TQgYmCnrPtlu50b4XvT5MOmurWNrCj3IFdyjBQ5p9vnrX4JM6I8OE7g==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.53.3.tgz", + "integrity": "sha512-EoGSa8nd6d3T7zLuqdojxC20oBfNT8nexBbB/rkxgKj5T5vhpAQKKnD+h3UkoMuTyXkP5jTjK/ccNRmQrPNDuw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.53.3.tgz", + "integrity": "sha512-4s+Wped2IHXHPnAEbIB0YWBv7SDohqxobiiPA1FIWZpX+w9o2i4LezzH/NkFUl8LRci/8udci6cLq+jJQlh+0g==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.53.3.tgz", + "integrity": "sha512-68k2g7+0vs2u9CxDt5ktXTngsxOQkSEV/xBbwlqYcUrAVh6P9EgMZvFsnHy4SEiUl46Xf0IObWVbMvPrr2gw8A==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.53.3.tgz", + "integrity": "sha512-VYsFMpULAz87ZW6BVYw3I6sWesGpsP9OPcyKe8ofdg9LHxSbRMd7zrVrr5xi/3kMZtpWL/wC+UIJWJYVX5uTKg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.53.3.tgz", + "integrity": "sha512-3EhFi1FU6YL8HTUJZ51imGJWEX//ajQPfqWLI3BQq4TlvHy4X0MOr5q3D2Zof/ka0d5FNdPwZXm3Yyib/UEd+w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.53.3.tgz", + "integrity": "sha512-eoROhjcc6HbZCJr+tvVT8X4fW3/5g/WkGvvmwz/88sDtSJzO7r/blvoBDgISDiCjDRZmHpwud7h+6Q9JxFwq1Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.53.3.tgz", + "integrity": "sha512-OueLAWgrNSPGAdUdIjSWXw+u/02BRTcnfw9PN41D2vq/JSEPnJnVuBgw18VkN8wcd4fjUs+jFHVM4t9+kBSNLw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.53.3.tgz", + "integrity": "sha512-GOFuKpsxR/whszbF/bzydebLiXIHSgsEUp6M0JI8dWvi+fFa1TD6YQa4aSZHtpmh2/uAlj/Dy+nmby3TJ3pkTw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.53.3.tgz", + "integrity": "sha512-iah+THLcBJdpfZ1TstDFbKNznlzoxa8fmnFYK4V67HvmuNYkVdAywJSoteUszvBQ9/HqN2+9AZghbajMsFT+oA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.53.3.tgz", + "integrity": "sha512-J9QDiOIZlZLdcot5NXEepDkstocktoVjkaKUtqzgzpt2yWjGlbYiKyp05rWwk4nypbYUNoFAztEgixoLaSETkg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.53.3.tgz", + "integrity": "sha512-UhTd8u31dXadv0MopwGgNOBpUVROFKWVQgAg5N1ESyCz8AuBcMqm4AuTjrwgQKGDfoFuz02EuMRHQIw/frmYKQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@sindresorhus/is": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-5.6.0.tgz", + "integrity": "sha512-TV7t8GKYaJWsn00tFDqBw8+Uqmr8A0fRU1tvTQhyZzGv0sJCGRQL3JGMI3ucuKo3XIZdUP+Lx7/gh2t3lewy7g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" + } + }, + "node_modules/@sindresorhus/merge-streams": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-2.3.0.tgz", + "integrity": "sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@sinonjs/commons": { + "version": "1.8.6", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.6.tgz", + "integrity": "sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-7.1.2.tgz", + "integrity": "sha512-iQADsW4LBMISqZ6Ci1dupJL9pprqwcVFTcOsEmQOEhW+KLCVn/Y4Jrvg2k19fIHCp+iFprriYPTdRcQR8NbUPg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@sinonjs/commons": "^1.7.0" + } + }, + "node_modules/@sinonjs/samsam": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-6.1.3.tgz", + "integrity": "sha512-nhOb2dWPeb1sd3IQXL/dVPnKHDOAFfvichtBf4xV00/rU1QbPCQqKMbvIheIjqwVjh7qIgf2AHTHi391yMOMpQ==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@sinonjs/commons": "^1.6.0", + "lodash.get": "^4.4.2", + "type-detect": "^4.0.8" + } + }, + "node_modules/@sinonjs/text-encoding": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.3.tgz", + "integrity": "sha512-DE427ROAphMQzU4ENbliGYrBSYPXF+TtLg9S8vzeA+OF4ZKzoDdzfL8sxuMUGS/lgRhM6j1URSk9ghf7Xo1tyA==", + "dev": true, + "license": "(Unlicense OR Apache-2.0)" + }, + "node_modules/@standard-schema/spec": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.0.0.tgz", + "integrity": "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@szmarczak/http-timer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-5.0.1.tgz", + "integrity": "sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==", + "dev": true, + "license": "MIT", + "dependencies": { + "defer-to-connect": "^2.0.1" + }, + "engines": { + "node": ">=14.16" + } + }, + "node_modules/@tsconfig/node10": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.12.tgz", + "integrity": "sha512-UCYBaeFvM11aU2y3YPZ//O5Rhj+xKyzy7mvcIoAjASbigy8mHMryP5cK7dgjlz2hWxh1g5pLw084E0a/wlUSFQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tybys/wasm-util": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz", + "integrity": "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@types/ace": { + "version": "0.0.52", + "resolved": "https://registry.npmjs.org/@types/ace/-/ace-0.0.52.tgz", + "integrity": "sha512-YPF9S7fzpuyrxru+sG/rrTpZkC6gpHBPF14W3x70kqVOD+ks6jkYLapk4yceh36xej7K4HYxcyz9ZDQ2lTvwgQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/body-parser": { + "version": "1.19.6", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.6.tgz", + "integrity": "sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/chai": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz", + "integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/deep-eql": "*", + "assertion-error": "^2.0.1" + } + }, + "node_modules/@types/connect": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/cookiejar": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@types/cookiejar/-/cookiejar-2.1.5.tgz", + "integrity": "sha512-he+DHOWReW0nghN24E1WUqM0efK4kI9oTqDm6XmK8ZPe2djZ90BSNdGnIyCLzCPw7/pogPlGbzI2wHGGmi4O/Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/cors": { + "version": "2.8.19", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.19.tgz", + "integrity": "sha512-mFNylyeyqN93lfe/9CSxOGREz8cpzAhH+E93xJ4xWQf62V8sQ/24reV2nyzUWM6H6Xji+GGHpkbLe7pVoUEskg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/deep-eql": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", + "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/express": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/@types/express/-/express-5.0.5.tgz", + "integrity": "sha512-LuIQOcb6UmnF7C1PCFmEU1u2hmiHL43fgFQX67sN3H4Z+0Yk0Neo++mFsBjhOAuLzvlQeqAAkeDOZrJs9rzumQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^5.0.0", + "@types/serve-static": "^1" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.1.0.tgz", + "integrity": "sha512-jnHMsrd0Mwa9Cf4IdOzbz543y4XJepXrbia2T4b6+spXC2We3t1y6K44D3mR8XMFSXMCf3/l7rCgddfx7UNVBA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "node_modules/@types/http-cache-semantics": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz", + "integrity": "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/http-errors": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.5.tgz", + "integrity": "sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/jquery": { + "version": "3.5.33", + "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.33.tgz", + "integrity": "sha512-SeyVJXlCZpEki5F0ghuYe+L+PprQta6nRZqhONt9F13dWBtR/ftoaIbdRQ7cis7womE+X2LKhsDdDtkkDhJS6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/sizzle": "*" + } + }, + "node_modules/@types/methods": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@types/methods/-/methods-1.1.4.tgz", + "integrity": "sha512-ymXWVrDiCxTBE3+RIrrP533E70eA+9qu7zdWoHuOmGujkYtzf4HQF96b8nwHLqhuf4ykX61IGRIB38CC6/sImQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/mime": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "20.19.25", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.25.tgz", + "integrity": "sha512-ZsJzA5thDQMSQO788d7IocwwQbI8B5OPzmqNvpf3NY/+MHDAS759Wo0gd2WQeXYt5AAAQjzcrTVC6SKCuYgoCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@types/node-persist": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/@types/node-persist/-/node-persist-3.1.8.tgz", + "integrity": "sha512-QLidg6/SadZYPrTKxtxL1A85XBoQlG40bhoMdhu6DH6+eNCMr2j+RGfFZ9I9+IY8W/PDwQonJ+iBWD62jZjMfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/node-red": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/node-red/-/node-red-1.3.5.tgz", + "integrity": "sha512-LBP8TmXJszHOoRgieyxgUrspvatmTZlkPRftlSNGE9TVJCQzSSyX3tF/Qe4evQlIUBmMGOijxcUOcKZSvq4piQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/express": "*", + "@types/node-red__editor-api": "*", + "@types/node-red__editor-client": "*", + "@types/node-red__registry": "*", + "@types/node-red__runtime": "*", + "@types/node-red__util": "*" + } + }, + "node_modules/@types/node-red__editor-api": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/node-red__editor-api/-/node-red__editor-api-1.3.5.tgz", + "integrity": "sha512-VE0o/gJzHVBTD2OBhpWth3sjU06TYLlLvlPh62Whs9FXUY0FdFKqWXbaG+ymYQqZreL1ZvTKfFmj0H7LnVEUeg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/express": "*", + "@types/node-red__runtime": "*" + } + }, + "node_modules/@types/node-red__editor-client": { + "version": "1.3.11", + "resolved": "https://registry.npmjs.org/@types/node-red__editor-client/-/node-red__editor-client-1.3.11.tgz", + "integrity": "sha512-Y8FGsMfec4TAVfULabH/Jui+4Cj4F3xx9v4GDpoTN5X9uHwOxdRi9UDtdvG+se/S76CFg6VjsctpJW0WjJUXgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/ace": "*", + "@types/jquery": "*", + "@types/node-red__registry": "*", + "@types/node-red__runtime": "*", + "@types/node-red__util": "*" + } + }, + "node_modules/@types/node-red__registry": { + "version": "1.3.11", + "resolved": "https://registry.npmjs.org/@types/node-red__registry/-/node-red__registry-1.3.11.tgz", + "integrity": "sha512-q0ALCNdNzq6x2HWBq0Ezeio0u0IrHLtwYT6WNdBG+zbWhNJqXikUpw27ElvnMCstwMiaXM44VQPL7VoTx8OuYw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/express": "*", + "@types/node-red__runtime": "*", + "@types/node-red__util": "*" + } + }, + "node_modules/@types/node-red__runtime": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/@types/node-red__runtime/-/node-red__runtime-1.3.8.tgz", + "integrity": "sha512-v5wsFjL6/kQ/YSz7WjC1J9yvE+NP8r5uivQTMBxnNnBabmDJo+dBmdp0rqJczbPNQS0ze7JGDQWz3Iuve+pYlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/cors": "*", + "@types/express": "*", + "@types/node-red__editor-api": "*", + "@types/node-red__util": "*", + "@types/passport": "*" + } + }, + "node_modules/@types/node-red__util": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/@types/node-red__util/-/node-red__util-1.3.8.tgz", + "integrity": "sha512-FQRxaZyUJlyh2phJevzMSF4H8jrsOUmFg05eyhRX5lvDcc/VqdZWcYdAq9dZPRgIwHJwLBttEh9mG3DAcMJiUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node-red__registry": "*", + "@types/node-red__runtime": "*", + "jsonata": "2.0.5" + } + }, + "node_modules/@types/node-red__util/node_modules/jsonata": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/jsonata/-/jsonata-2.0.5.tgz", + "integrity": "sha512-wEse9+QLIIU5IaCgtJCPsFi/H4F3qcikWzF4bAELZiRz08ohfx3Q6CjDRf4ZPF5P/92RI3KIHtb7u3jqPaHXdQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@types/node-red-node-test-helper": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@types/node-red-node-test-helper/-/node-red-node-test-helper-0.3.5.tgz", + "integrity": "sha512-ppCrp+3ncOCvciPXwQWhXy5voENjDyK1Xvw98Q9a4tJsSdqiitdy7HsUgtbCSn/mrKStRzZ61l+fHDAknR0BgA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node-red": "*", + "@types/node-red__runtime": "*", + "@types/sinon": "*", + "@types/supertest": "*" + } + }, + "node_modules/@types/passport": { + "version": "1.0.17", + "resolved": "https://registry.npmjs.org/@types/passport/-/passport-1.0.17.tgz", + "integrity": "sha512-aciLyx+wDwT2t2/kJGJR2AEeBz0nJU4WuRX04Wu9Dqc5lSUtwu0WERPHYsLhF9PtseiAMPBGNUOtFjxZ56prsg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/express": "*" + } + }, + "node_modules/@types/qs": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.14.0.tgz", + "integrity": "sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/range-parser": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/readable-stream": { + "version": "4.0.22", + "resolved": "https://registry.npmjs.org/@types/readable-stream/-/readable-stream-4.0.22.tgz", + "integrity": "sha512-/FFhJpfCLAPwAcN3mFycNUa77ddnr8jTgF5VmSNetaemWB2cIlfCA9t0YTM3JAT0wOcv8D4tjPo7pkDhK3EJIg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/semver": { + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-FmgJfu+MOcQ370SD0ev7EI8TlCAfKYU+B4m5T3yXc1CiRN94g/SZPtsCkk506aUDtlMnFZvasDwHHUcZUEaYuA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/send": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@types/send/-/send-1.2.1.tgz", + "integrity": "sha512-arsCikDvlU99zl1g69TcAB3mzZPpxgw0UQnaHeC1Nwb015xp8bknZv5rIfri9xTOcMuaVgvabfIRA7PSZVuZIQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/serve-static": { + "version": "1.15.10", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.10.tgz", + "integrity": "sha512-tRs1dB+g8Itk72rlSI2ZrW6vZg0YrLI81iQSTkMmOqnqCaNr/8Ek4VwWcN5vZgCYWbg/JJSGBlUaYGAOP73qBw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/http-errors": "*", + "@types/node": "*", + "@types/send": "<1" + } + }, + "node_modules/@types/serve-static/node_modules/@types/send": { + "version": "0.17.6", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.6.tgz", + "integrity": "sha512-Uqt8rPBE8SY0RK8JB1EzVOIZ32uqy8HwdxCnoCOsYrvnswqmFZ/k+9Ikidlk/ImhsdvBsloHbAlewb2IEBV/Og==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "node_modules/@types/sinon": { + "version": "21.0.0", + "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-21.0.0.tgz", + "integrity": "sha512-+oHKZ0lTI+WVLxx1IbJDNmReQaIsQJjN2e7UUrJHEeByG7bFeKJYsv1E75JxTQ9QKJDp21bAa/0W2Xo4srsDnw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/sinonjs__fake-timers": "*" + } + }, + "node_modules/@types/sinonjs__fake-timers": { + "version": "15.0.1", + "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-15.0.1.tgz", + "integrity": "sha512-Ko2tjWJq8oozHzHV+reuvS5KYIRAokHnGbDwGh/J64LntgpbuylF74ipEL24HCyRjf9FOlBiBHWBR1RlVKsI1w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/sizzle": { + "version": "2.3.10", + "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.10.tgz", + "integrity": "sha512-TC0dmN0K8YcWEAEfiPi5gJP14eJe30TTGjkvek3iM/1NdHHsdCA/Td6GvNndMOo/iSnIsZ4HuuhrYPDAmbxzww==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/superagent": { + "version": "8.1.9", + "resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-8.1.9.tgz", + "integrity": "sha512-pTVjI73witn+9ILmoJdajHGW2jkSaOzhiFYF1Rd3EQ94kymLqB9PjD9ISg7WaALC7+dCHT0FGe9T2LktLq/3GQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/cookiejar": "^2.1.5", + "@types/methods": "^1.1.4", + "@types/node": "*", + "form-data": "^4.0.0" + } + }, + "node_modules/@types/supertest": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/@types/supertest/-/supertest-6.0.3.tgz", + "integrity": "sha512-8WzXq62EXFhJ7QsH3Ocb/iKQ/Ty9ZVWnVzoTKc9tyyFRRF3a74Tk2+TLFgaFFw364Ere+npzHKEJ6ga2LzIL7w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/methods": "^1.1.4", + "@types/superagent": "^8.1.0" + } + }, + "node_modules/@types/uuid": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-10.0.0.tgz", + "integrity": "sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/ws": { + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz", + "integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@vitest/expect": { + "version": "4.0.13", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.0.13.tgz", + "integrity": "sha512-zYtcnNIBm6yS7Gpr7nFTmq8ncowlMdOJkWLqYvhr/zweY6tFbDkDi8BPPOeHxEtK1rSI69H7Fd4+1sqvEGli6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@standard-schema/spec": "^1.0.0", + "@types/chai": "^5.2.2", + "@vitest/spy": "4.0.13", + "@vitest/utils": "4.0.13", + "chai": "^6.2.1", + "tinyrainbow": "^3.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/mocker": { + "version": "4.0.13", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.0.13.tgz", + "integrity": "sha512-eNCwzrI5djoauklwP1fuslHBjrbR8rqIVbvNlAnkq1OTa6XT+lX68mrtPirNM9TnR69XUPt4puBCx2Wexseylg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/spy": "4.0.13", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.21" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "msw": "^2.4.9", + "vite": "^6.0.0 || ^7.0.0-0" + }, + "peerDependenciesMeta": { + "msw": { + "optional": true + }, + "vite": { + "optional": true + } + } + }, + "node_modules/@vitest/pretty-format": { + "version": "4.0.13", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.0.13.tgz", + "integrity": "sha512-ooqfze8URWbI2ozOeLDMh8YZxWDpGXoeY3VOgcDnsUxN0jPyPWSUvjPQWqDGCBks+opWlN1E4oP1UYl3C/2EQA==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyrainbow": "^3.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner": { + "version": "4.0.13", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.0.13.tgz", + "integrity": "sha512-9IKlAru58wcVaWy7hz6qWPb2QzJTKt+IOVKjAx5vb5rzEFPTL6H4/R9BMvjZ2ppkxKgTrFONEJFtzvnyEpiT+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/utils": "4.0.13", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/snapshot": { + "version": "4.0.13", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.0.13.tgz", + "integrity": "sha512-hb7Usvyika1huG6G6l191qu1urNPsq1iFc2hmdzQY3F5/rTgqQnwwplyf8zoYHkpt7H6rw5UfIw6i/3qf9oSxQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "4.0.13", + "magic-string": "^0.30.21", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/spy": { + "version": "4.0.13", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.0.13.tgz", + "integrity": "sha512-hSu+m4se0lDV5yVIcNWqjuncrmBgwaXa2utFLIrBkQCQkt+pSwyZTPFQAZiiF/63j8jYa8uAeUZ3RSfcdWaYWw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils": { + "version": "4.0.13", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.0.13.tgz", + "integrity": "sha512-ydozWyQ4LZuu8rLp47xFUWis5VOKMdHjXCWhs1LuJsTNKww+pTHQNK4e0assIB9K80TxFyskENL6vCu3j34EYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "4.0.13", + "tinyrainbow": "^3.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "dev": true, + "license": "ISC" + }, + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "dev": true, + "license": "MIT", + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", + "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-colors": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/append-field": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", + "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==", + "dev": true, + "license": "MIT" + }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true, + "license": "MIT" + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz", + "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "is-array-buffer": "^3.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-flatten": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-3.0.0.tgz", + "integrity": "sha512-zPMVc3ZYlGLNk4mpK1NzP2wg0ml9t7fUgDsayR5Y5rSzxQilzR9FGu/EH2jQOcKSAeAfWeylyW8juy3OkWRvNA==", + "license": "MIT" + }, + "node_modules/asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", + "dev": true, + "license": "MIT" + }, + "node_modules/assertion-error": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + } + }, + "node_modules/async-mutex": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/async-mutex/-/async-mutex-0.5.0.tgz", + "integrity": "sha512-1A94B18jkJ3DYq284ohPxoXbfTA5HsQ7/Mf4DEhcyLx3Bz27Rh59iScbB6EPiP+B+joue6YCxcMXSbFC1tZKwA==", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "license": "MIT", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/axios": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.12.2.tgz", + "integrity": "sha512-vMJzPewAlRyOgxV2dU0Cuz2O8zzzx9VYtbJOaBgXFeLc4IV/Eg50n4LowmehOOR61S8ZMpc2K5Sa7g6A4jfkUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.4", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/basic-auth": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", + "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "5.1.2" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/basic-auth/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true, + "license": "MIT" + }, + "node_modules/bcryptjs": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-3.0.2.tgz", + "integrity": "sha512-k38b3XOZKv60C4E2hVsXTolJWfkGRMbILBIe2IBITXciy5bOsTKot5kDrf3ZfufQtQOUN5mXceUEpU1rTl9Uog==", + "dev": true, + "license": "BSD-3-Clause", + "bin": { + "bcrypt": "bin/bcrypt" + } + }, + "node_modules/bl": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/bl/-/bl-6.1.4.tgz", + "integrity": "sha512-ZV/9asSuknOExbM/zPPA8z00lc1ihPKWaStHkkQrxHNeYx+yY+TmF+v80dpv2G0mv3HVXBu7ryoAsxbFFhf4eg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/readable-stream": "^4.0.0", + "buffer": "^6.0.3", + "inherits": "^2.0.4", + "readable-stream": "^4.2.0" + } + }, + "node_modules/body-parser": { + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", + "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", + "dev": true, + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.13.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/body-parser/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/body-parser/node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/body-parser/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true, + "license": "MIT" + }, + "node_modules/body-parser/node_modules/raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "dev": true, + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/bonjour-hap": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/bonjour-hap/-/bonjour-hap-3.9.1.tgz", + "integrity": "sha512-ubpbZSBwRyAx2+j5RLKFO+QuRvB02s+7rinC0rQzICx9hEc0zryjRz56Rr9lxoW7UkE/mnZ4rP4mnTCF4/iUkg==", + "license": "MIT", + "dependencies": { + "array-flatten": "^3.0.0", + "deep-equal": "^2.2.3", + "multicast-dns": "^7.2.5", + "multicast-dns-service-types": "^1.1.0" + } + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "dev": true, + "license": "ISC" + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "license": "MIT" + }, + "node_modules/busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "dev": true, + "dependencies": { + "streamsearch": "^1.1.0" + }, + "engines": { + "node": ">=10.16.0" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/cacheable-lookup": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-7.0.0.tgz", + "integrity": "sha512-+qJyx4xiKra8mZrcwhjMRMUhD5NR1R8esPkzIYxX96JiecFoxAXFuz/GpR3+ev4PE1WamHip78wV0vcmPQtp8w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.16" + } + }, + "node_modules/cacheable-request": { + "version": "10.2.14", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-10.2.14.tgz", + "integrity": "sha512-zkDT5WAF4hSSoUgyfg5tFIxz8XQK+25W/TLVojJTMKBaxevLBBtLxgqguAuVQB8PVW79FVjHcU+GJ9tVbDZ9mQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/http-cache-semantics": "^4.0.2", + "get-stream": "^6.0.1", + "http-cache-semantics": "^4.1.1", + "keyv": "^4.5.3", + "mimic-response": "^4.0.0", + "normalize-url": "^8.0.0", + "responselike": "^3.0.0" + }, + "engines": { + "node": ">=14.16" + } + }, + "node_modules/call-bind": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", + "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.0", + "es-define-property": "^1.0.0", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/chai": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/chai/-/chai-6.2.1.tgz", + "integrity": "sha512-p4Z49OGG5W/WBCPSS/dH3jQ73kD6tiMmUM+bckNK6Jr5JHMG3k9bg/BvKR8lKmtVBKmOiuVaV2ws8s9oSbwysg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/cheerio": { + "version": "1.0.0-rc.10", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.10.tgz", + "integrity": "sha512-g0J0q/O6mW8z5zxQ3A8E8J1hUgp4SMOvEoW/x84OwyHKe/Zccz83PVT4y5Crcr530FV6NgmKI1qvGTKVl9XXVw==", + "dev": true, + "license": "MIT", + "dependencies": { + "cheerio-select": "^1.5.0", + "dom-serializer": "^1.3.2", + "domhandler": "^4.2.0", + "htmlparser2": "^6.1.0", + "parse5": "^6.0.1", + "parse5-htmlparser2-tree-adapter": "^6.0.1", + "tslib": "^2.2.0" + }, + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/cheeriojs/cheerio?sponsor=1" + } + }, + "node_modules/cheerio-select": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-1.6.0.tgz", + "integrity": "sha512-eq0GdBvxVFbqWgmCm7M3XGs1I8oLy/nExUnh6oLqmBditPO9AqQJrkslDpMun/hZ0yyTs8L0m85OHp4ho6Qm9g==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "css-select": "^4.3.0", + "css-what": "^6.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.3.1", + "domutils": "^2.8.0" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/chownr": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", + "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/cli-table": { + "version": "0.3.11", + "resolved": "https://registry.npmjs.org/cli-table/-/cli-table-0.3.11.tgz", + "integrity": "sha512-IqLQi4lO0nIB4tcdTpN4LCB9FI3uqrJZK7RC515EnhZ6qBaglkIgICb1wjeAqpdoOabm1+SuQtkXIPdYC93jhQ==", + "dev": true, + "dependencies": { + "colors": "1.0.3" + }, + "engines": { + "node": ">= 0.2.0" + } + }, + "node_modules/clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/colors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", + "integrity": "sha512-pFGrxThWcWQ2MsAz6RtgeWe4NK2kUE1WfsrvvlctdII745EW9I0yflqhe7++M5LEc7bV2c/9/5zc8sFcpL0Drw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commist": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/commist/-/commist-3.2.0.tgz", + "integrity": "sha512-4PIMoPniho+LqXmpS5d3NuGYncG6XWlkBSVGiWycL22dd42OYdUGil2CWuzklaJoNxyxUSpO4MKIBU94viWNAw==", + "dev": true, + "license": "MIT" + }, + "node_modules/component-emitter": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.1.tgz", + "integrity": "sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "dev": true, + "engines": [ + "node >= 6.0" + ], + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/concat-stream/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-parser": { + "version": "1.4.7", + "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.7.tgz", + "integrity": "sha512-nGUvgXnotP3BsjiLX2ypbQnWoGUPIIfHQNZkkC668ntrzGWEZVW70HDEB1qnNGMicPje6EttlIgzo51YSwNQGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "cookie": "0.7.2", + "cookie-signature": "1.0.6" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/cookiejar": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.4.tgz", + "integrity": "sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==", + "dev": true, + "license": "MIT" + }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/cronosjs": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/cronosjs/-/cronosjs-1.7.1.tgz", + "integrity": "sha512-d6S6+ep7dJxsAG8OQQCdKuByI/S/AV64d9OF5mtmcykOyPu92cAkAnF3Tbc9s5oOaLQBYYQmTNvjqYRkPJ/u5Q==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/css-select": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", + "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.0.1", + "domhandler": "^4.3.1", + "domutils": "^2.8.0", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-what": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.2.2.tgz", + "integrity": "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/decompress-response/node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-equal": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.3.tgz", + "integrity": "sha512-ZIwpnevOurS8bpT4192sqAowWM76JDKSHYzMLty3BZGSswgq6pBaH3DhCSW5xVAZICZyKdOBPjwww5wfgT/6PA==", + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.0", + "call-bind": "^1.0.5", + "es-get-iterator": "^1.1.3", + "get-intrinsic": "^1.2.2", + "is-arguments": "^1.1.1", + "is-array-buffer": "^3.0.2", + "is-date-object": "^1.0.5", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "isarray": "^2.0.5", + "object-is": "^1.1.5", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.5.1", + "side-channel": "^1.0.4", + "which-boxed-primitive": "^1.0.2", + "which-collection": "^1.0.1", + "which-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/defer-to-connect": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", + "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "license": "MIT", + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/del": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/del/-/del-8.0.1.tgz", + "integrity": "sha512-gPqh0mKTPvaUZGAuHbrBUYKZWBNAeHG7TU3QH5EhVwPMyKvmfJaNXhcD2jTcXsJRRcffuho4vaYweu80dRrMGA==", + "dev": true, + "license": "MIT", + "dependencies": { + "globby": "^14.0.2", + "is-glob": "^4.0.3", + "is-path-cwd": "^3.0.0", + "is-path-inside": "^4.0.0", + "p-map": "^7.0.2", + "presentable-error": "^0.0.1", + "slash": "^5.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/del-cli": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/del-cli/-/del-cli-7.0.0.tgz", + "integrity": "sha512-fRl4pWJYu9WFQH8jXdQUYvcD0IMtij9WEc7qmB7xOyJEweNJNuE7iKmqNeoOT1DbBUjtRjxlw8Y63qKBI/NQ1g==", + "dev": true, + "license": "MIT", + "dependencies": { + "del": "^8.0.1", + "meow": "^14.0.0", + "presentable-error": "^0.0.1" + }, + "bin": { + "del": "cli.js", + "del-cli": "cli.js" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/denque": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", + "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/dezalgo": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.4.tgz", + "integrity": "sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==", + "dev": true, + "license": "ISC", + "dependencies": { + "asap": "^2.0.0", + "wrappy": "1" + } + }, + "node_modules/diff": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", + "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/dns-packet": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz", + "integrity": "sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==", + "license": "MIT", + "dependencies": { + "@leichtgewicht/ip-codec": "^2.0.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/dom-serializer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", + "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", + "dev": true, + "license": "MIT", + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "BSD-2-Clause" + }, + "node_modules/domhandler": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", + "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "domelementtype": "^2.2.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "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==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/duplexer": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", + "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", + "license": "MIT" + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "dev": true, + "license": "MIT" + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/enquirer": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.4.1.tgz", + "integrity": "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-colors": "^4.1.1", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "dev": true, + "license": "BSD-2-Clause", + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "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==", + "license": "MIT", + "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==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-get-iterator": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz", + "integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "has-symbols": "^1.0.3", + "is-arguments": "^1.1.1", + "is-map": "^2.0.2", + "is-set": "^2.0.2", + "is-string": "^1.0.7", + "isarray": "^2.0.5", + "stop-iteration-iterator": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-module-lexer": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", + "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", + "dev": true, + "license": "MIT" + }, + "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==", + "license": "MIT", + "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==", + "dev": true, + "license": "MIT", + "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/esbuild": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz", + "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.12", + "@esbuild/android-arm": "0.25.12", + "@esbuild/android-arm64": "0.25.12", + "@esbuild/android-x64": "0.25.12", + "@esbuild/darwin-arm64": "0.25.12", + "@esbuild/darwin-x64": "0.25.12", + "@esbuild/freebsd-arm64": "0.25.12", + "@esbuild/freebsd-x64": "0.25.12", + "@esbuild/linux-arm": "0.25.12", + "@esbuild/linux-arm64": "0.25.12", + "@esbuild/linux-ia32": "0.25.12", + "@esbuild/linux-loong64": "0.25.12", + "@esbuild/linux-mips64el": "0.25.12", + "@esbuild/linux-ppc64": "0.25.12", + "@esbuild/linux-riscv64": "0.25.12", + "@esbuild/linux-s390x": "0.25.12", + "@esbuild/linux-x64": "0.25.12", + "@esbuild/netbsd-arm64": "0.25.12", + "@esbuild/netbsd-x64": "0.25.12", + "@esbuild/openbsd-arm64": "0.25.12", + "@esbuild/openbsd-x64": "0.25.12", + "@esbuild/openharmony-arm64": "0.25.12", + "@esbuild/sunos-x64": "0.25.12", + "@esbuild/win32-arm64": "0.25.12", + "@esbuild/win32-ia32": "0.25.12", + "@esbuild/win32-x64": "0.25.12" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "dev": true, + "license": "MIT" + }, + "node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/event-stream": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-4.0.1.tgz", + "integrity": "sha512-qACXdu/9VHPBzcyhdOWR5/IahhGMf0roTeZJfzz077GwylcDd90yOHLouhmv7GJ5XzPi6ekaQWd8AvPP2nOvpA==", + "license": "MIT", + "dependencies": { + "duplexer": "^0.1.1", + "from": "^0.1.7", + "map-stream": "0.0.7", + "pause-stream": "^0.0.11", + "split": "^1.0.1", + "stream-combiner": "^0.2.2", + "through": "^2.3.8" + } + }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/expect-type": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.2.2.tgz", + "integrity": "sha512-JhFGDVJ7tmDJItKhYgJCGLOWjuK9vPxiXoUFLwLDc99NlmklilbiQJwoctZtt13+xMw91MCk/REan6MWHqDjyA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/express": { + "version": "4.21.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", + "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.3", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.7.1", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.3.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.3", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.12", + "proxy-addr": "~2.0.7", + "qs": "6.13.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.19.0", + "serve-static": "1.16.2", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/express-session": { + "version": "1.18.2", + "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.18.2.tgz", + "integrity": "sha512-SZjssGQC7TzTs9rpPDuUrR23GNZ9+2+IkA/+IJWmvQilTr5OSliEHGF+D9scbIpdC6yGtTI0/VhaHoVes2AN/A==", + "dev": true, + "license": "MIT", + "dependencies": { + "cookie": "0.7.2", + "cookie-signature": "1.0.7", + "debug": "2.6.9", + "depd": "~2.0.0", + "on-headers": "~1.1.0", + "parseurl": "~1.3.3", + "safe-buffer": "5.2.1", + "uid-safe": "~2.1.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/express-session/node_modules/cookie-signature": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.7.tgz", + "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==", + "dev": true, + "license": "MIT" + }, + "node_modules/express-session/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/express-session/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true, + "license": "MIT" + }, + "node_modules/express/node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/express/node_modules/cookie": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", + "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/express/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "license": "MIT" + }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-safe-stringify": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", + "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-srp-hap": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/fast-srp-hap/-/fast-srp-hap-2.0.4.tgz", + "integrity": "sha512-lHRYYaaIbMrhZtsdGTwPN82UbqD9Bv8QfOlKs+Dz6YRnByZifOh93EYmf2iEWFtkOEIqR2IK8cFD0UN5wLIWBQ==", + "license": "MIT", + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/fast-unique-numbers": { + "version": "8.0.13", + "resolved": "https://registry.npmjs.org/fast-unique-numbers/-/fast-unique-numbers-8.0.13.tgz", + "integrity": "sha512-7OnTFAVPefgw2eBJ1xj2PGGR9FwYzSUso9decayHgCDX4sJkHLdcsYTytTg+tYv+wKF3U8gJuSBz2jJpQV4u/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.23.8", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.1.0" + } + }, + "node_modules/fast-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz", + "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/fastq": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", + "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", + "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true, + "license": "MIT" + }, + "node_modules/follow-redirects": { + "version": "1.15.11", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", + "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/for-each": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", + "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", + "license": "MIT", + "dependencies": { + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/form-data": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", + "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", + "dev": true, + "license": "MIT", + "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/form-data-encoder": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-2.1.4.tgz", + "integrity": "sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.17" + } + }, + "node_modules/formidable": { + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/formidable/-/formidable-3.5.4.tgz", + "integrity": "sha512-YikH+7CUTOtP44ZTnUhR7Ic2UASBPOqmaRkRKxRbywPTe5VxF7RRCck4af9wutiZ/QKM5nME9Bie2fFaPz5Gug==", + "dev": true, + "license": "MIT", + "dependencies": { + "@paralleldrive/cuid2": "^2.2.2", + "dezalgo": "^1.0.4", + "once": "^1.4.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "url": "https://ko-fi.com/tunnckoCore/commissions" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/from": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", + "integrity": "sha512-twe20eF1OxVxp/ML/kq2p1uc6KvFK/+vs8WjEbeKmV2He22MKm7YF2ANIt+EOqhJ5L3K/SuuPhk0hWQDjOM23g==", + "license": "MIT" + }, + "node_modules/fs-extra": { + "version": "11.3.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.0.tgz", + "integrity": "sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "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==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/futoin-hkdf": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/futoin-hkdf/-/futoin-hkdf-1.5.3.tgz", + "integrity": "sha512-SewY5KdMpaoCeh7jachEWFsh1nNlaDjNHZXWqL5IGwtpEYHTgkr2+AMCgNwKWkcc0wpSYrZfR7he4WdmHFtDxQ==", + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "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==", + "license": "MIT", + "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==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/globby": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-14.1.0.tgz", + "integrity": "sha512-0Ia46fDOaT7k4og1PDW4YbodWWr3scS2vAr2lTbsplOt2WkKp0vQbkI9wKis/T5LV/dqPjO3bpS/z6GTJB82LA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sindresorhus/merge-streams": "^2.1.0", + "fast-glob": "^3.3.3", + "ignore": "^7.0.3", + "path-type": "^6.0.0", + "slash": "^5.1.0", + "unicorn-magic": "^0.3.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/got": { + "version": "12.6.1", + "resolved": "https://registry.npmjs.org/got/-/got-12.6.1.tgz", + "integrity": "sha512-mThBblvlAF1d4O5oqyvN+ZxLAYwIJK7bpMxgYqPD9okW0C3qm5FFn7k811QrcuEBwaogR3ngOFoCfs6mRv7teQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sindresorhus/is": "^5.2.0", + "@szmarczak/http-timer": "^5.0.1", + "cacheable-lookup": "^7.0.0", + "cacheable-request": "^10.2.8", + "decompress-response": "^6.0.0", + "form-data-encoder": "^2.1.2", + "get-stream": "^6.0.1", + "http2-wrapper": "^2.1.10", + "lowercase-keys": "^3.0.0", + "p-cancelable": "^3.0.0", + "responselike": "^3.0.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sindresorhus/got?sponsor=1" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/has-bigints": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", + "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "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==", + "license": "MIT", + "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==", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hash-sum": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/hash-sum/-/hash-sum-2.0.0.tgz", + "integrity": "sha512-WdZTbAByD+pHfl/g9QSsBIIwy8IT+EsPiKDs0KNX+zSHhdDLFKdZu0BQHljvO+0QI/BasbMSUa8wYNCZTvhslg==", + "dev": true, + "license": "MIT" + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/help-me": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-5.0.0.tgz", + "integrity": "sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==", + "dev": true, + "license": "MIT" + }, + "node_modules/hexy": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/hexy/-/hexy-0.3.5.tgz", + "integrity": "sha512-UCP7TIZPXz5kxYJnNOym+9xaenxCLor/JyhKieo8y8/bJWunGh9xbhy3YrgYJUQ87WwfXGm05X330DszOfINZw==", + "license": "MIT", + "bin": { + "hexy": "bin/hexy_cmd.js" + }, + "engines": { + "node": ">=10.4" + } + }, + "node_modules/hpagent": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/hpagent/-/hpagent-1.2.0.tgz", + "integrity": "sha512-A91dYTeIB6NoXG+PxTQpCCDDnfHsW9kc06Lvpu1TEe9gnd6ZFeiBoRO9JvzEv6xK7EX97/dUE8g/vBMTqTS3CA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + } + }, + "node_modules/htmlparser2": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", + "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", + "dev": true, + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "MIT", + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.0.0", + "domutils": "^2.5.2", + "entities": "^2.0.0" + } + }, + "node_modules/http-cache-semantics": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", + "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http2-wrapper": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-2.2.1.tgz", + "integrity": "sha512-V5nVw1PAOgfI3Lmeaj2Exmeg7fenjhRUgz1lPSezy1CuhPYbgQtbQj4jZfEAEMlaL+vupsvhjqCyjzob0yxsmQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "quick-lru": "^5.1.1", + "resolve-alpn": "^1.2.0" + }, + "engines": { + "node": ">=10.19.0" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/husky": { + "version": "9.1.7", + "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.7.tgz", + "integrity": "sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==", + "dev": true, + "license": "MIT", + "bin": { + "husky": "bin.js" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/typicode" + } + }, + "node_modules/i18next": { + "version": "24.2.3", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-24.2.3.tgz", + "integrity": "sha512-lfbf80OzkocvX7nmZtu7nSTNbrTYR52sLWxPtlXX1zAhVw8WEnFk4puUkCR4B1dNQwbSpEHHHemcZu//7EcB7A==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://locize.com" + }, + { + "type": "individual", + "url": "https://locize.com/i18next.html" + }, + { + "type": "individual", + "url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project" + } + ], + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.26.10" + }, + "peerDependencies": { + "typescript": "^5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/internal-slot": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", + "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "hasown": "^2.0.2", + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ip-address": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.1.0.tgz", + "integrity": "sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-arguments": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.2.0.tgz", + "integrity": "sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", + "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-bigint": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz", + "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", + "license": "MIT", + "dependencies": { + "has-bigints": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-boolean-object": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz", + "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz", + "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", + "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-number-object": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz", + "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-path-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-3.0.0.tgz", + "integrity": "sha512-kyiNFFLU0Ampr6SDZitD/DwUo4Zs1nSdnygUBqsu3LooL00Qvb5j+UnvApUn/TTj1J3OuE6BTdQ5rudKmU2ZaA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-path-inside": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-4.0.0.tgz", + "integrity": "sha512-lJJV/5dYS+RcL8uQdBDW9c9uWFLLBNRyFhnAKXw5tVqLlKZ4RMGZKv+YQ/IA3OhD+RpbJa1LLFM1FQPGyIXvOA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-regex": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", + "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-set": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", + "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz", + "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-string": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", + "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz", + "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-symbols": "^1.1.0", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha512-rMYPYvCzsXywIsldgLaSoPlw5PfoB/ssr7hY4pLfcodrA5M/eArza1a9VmTiNIBNMjOGr1Ow9mTyU2o69U6U9Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/is-weakmap": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", + "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakset": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz", + "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "license": "MIT" + }, + "node_modules/js-sdsl": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", + "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==", + "dev": true, + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/js-sdsl" + } + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", + "dev": true, + "license": "ISC" + }, + "node_modules/jsonata": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/jsonata/-/jsonata-2.0.6.tgz", + "integrity": "sha512-WhQB5tXQ32qjkx2GYHFw2XbL90u+LLzjofAYwi+86g6SyZeXHz9F1Q0amy3dWRYczshOC3Haok9J4pOCgHtwyQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/jsonfile": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/just-extend": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-6.2.0.tgz", + "integrity": "sha512-cYofQu2Xpom82S6qD778jBDpwvvy39s1l/hrYij2u9AMdQcGRpaBu6kY4mVhuno5kJVi1DAz4aiphA2WI1/OAw==", + "dev": true, + "license": "MIT" + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==", + "deprecated": "This package is deprecated. Use the optional chaining (?.) operator instead.", + "dev": true, + "license": "MIT" + }, + "node_modules/long": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz", + "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==", + "license": "Apache-2.0" + }, + "node_modules/lowercase-keys": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-3.0.0.tgz", + "integrity": "sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "dev": true, + "license": "ISC", + "dependencies": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true, + "license": "ISC" + }, + "node_modules/map-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.0.7.tgz", + "integrity": "sha512-C0X0KQmGm3N2ftbTGBhSyuydQ+vV1LC3f3zPvT3RXHXNZrvfPZcoXp/N5DOa8vedX/rTMm2CjTtivFg2STJMRQ==", + "license": "MIT" + }, + "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==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/media-typer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", + "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/memorystore": { + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/memorystore/-/memorystore-1.6.7.tgz", + "integrity": "sha512-OZnmNY/NDrKohPQ+hxp0muBcBKrzKNtHr55DbqSx9hLsYVNnomSAMRAtI7R64t3gf3ID7tHQA7mG4oL3Hu9hdw==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.3.0", + "lru-cache": "^4.0.3" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/meow": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-14.0.0.tgz", + "integrity": "sha512-JhC3R1f6dbspVtmF3vKjAWz1EVIvwFrGGPLSdU6rK79xBwHWTuHoLnRX/t1/zHS1Ch1Y2UtIrih7DAHuH9JFJA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", + "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", + "dev": true, + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-response": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-4.0.0.tgz", + "integrity": "sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/minizlib": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.1.0.tgz", + "integrity": "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "minipass": "^7.1.2" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "license": "MIT", + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/moment": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/moment-timezone": { + "version": "0.5.48", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.48.tgz", + "integrity": "sha512-f22b8LV1gbTO2ms2j2z13MuPogNoh5UzxL3nzNAYKGraILnbGc9NEE6dyiiiLv46DGRb8A4kg8UKWLjPthxBHw==", + "dev": true, + "license": "MIT", + "dependencies": { + "moment": "^2.29.4" + }, + "engines": { + "node": "*" + } + }, + "node_modules/mqtt": { + "version": "5.11.0", + "resolved": "https://registry.npmjs.org/mqtt/-/mqtt-5.11.0.tgz", + "integrity": "sha512-VDqfADTNvohwcY02NgxPb7OojIeDrNQ1q62r/DcM+bnIWY8LBi3nMTvdEaFEp6Bu4ejBIpHjJVthUEgnvGLemA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/readable-stream": "^4.0.18", + "@types/ws": "^8.5.14", + "commist": "^3.2.0", + "concat-stream": "^2.0.0", + "debug": "^4.4.0", + "help-me": "^5.0.0", + "lru-cache": "^10.4.3", + "minimist": "^1.2.8", + "mqtt-packet": "^9.0.2", + "number-allocator": "^1.0.14", + "readable-stream": "^4.7.0", + "reinterval": "^1.1.0", + "rfdc": "^1.4.1", + "socks": "^2.8.3", + "split2": "^4.2.0", + "worker-timers": "^7.1.8", + "ws": "^8.18.0" + }, + "bin": { + "mqtt": "build/bin/mqtt.js", + "mqtt_pub": "build/bin/pub.js", + "mqtt_sub": "build/bin/sub.js" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/mqtt-packet": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-9.0.2.tgz", + "integrity": "sha512-MvIY0B8/qjq7bKxdN1eD+nrljoeaai+qjLJgfRn3TiMuz0pamsIWY2bFODPZMSNmabsLANXsLl4EMoWvlaTZWA==", + "dev": true, + "license": "MIT", + "dependencies": { + "bl": "^6.0.8", + "debug": "^4.3.4", + "process-nextick-args": "^2.0.1" + } + }, + "node_modules/mqtt/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/mqtt/node_modules/ws": { + "version": "8.18.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", + "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/multer": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/multer/-/multer-2.0.2.tgz", + "integrity": "sha512-u7f2xaZ/UG8oLXHvtF/oWTRvT44p9ecwBBqTwgJVq0+4BW1g8OW01TyMEGWBHbyMOYVHXslaut7qEQ1meATXgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "append-field": "^1.0.0", + "busboy": "^1.6.0", + "concat-stream": "^2.0.0", + "mkdirp": "^0.5.6", + "object-assign": "^4.1.1", + "type-is": "^1.6.18", + "xtend": "^4.0.2" + }, + "engines": { + "node": ">= 10.16.0" + } + }, + "node_modules/multicast-dns": { + "version": "7.2.5", + "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz", + "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==", + "license": "MIT", + "dependencies": { + "dns-packet": "^5.2.2", + "thunky": "^1.0.2" + }, + "bin": { + "multicast-dns": "cli.js" + } + }, + "node_modules/multicast-dns-service-types": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz", + "integrity": "sha512-cnAsSVxIDsYt0v7HmC0hWZFwwXSh+E6PgCrREDuN/EsjgLwA5XRmlMHhSiDPrt6HxY1gTivEa/Zh7GtODoLevQ==", + "license": "MIT" + }, + "node_modules/mustache": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/mustache/-/mustache-4.2.0.tgz", + "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==", + "dev": true, + "license": "MIT", + "bin": { + "mustache": "bin/mustache" + } + }, + "node_modules/mute-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-1.0.0.tgz", + "integrity": "sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/nise": { + "version": "5.1.9", + "resolved": "https://registry.npmjs.org/nise/-/nise-5.1.9.tgz", + "integrity": "sha512-qOnoujW4SV6e40dYxJOb3uvuoPHtmLzIk4TFo+j0jPJoC+5Z9xja5qH5JZobEPsa8+YYphMrOSwnrshEhG2qww==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@sinonjs/commons": "^3.0.0", + "@sinonjs/fake-timers": "^11.2.2", + "@sinonjs/text-encoding": "^0.7.2", + "just-extend": "^6.2.0", + "path-to-regexp": "^6.2.1" + } + }, + "node_modules/nise/node_modules/@sinonjs/commons": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/nise/node_modules/@sinonjs/fake-timers": { + "version": "11.3.1", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-11.3.1.tgz", + "integrity": "sha512-EVJO7nW5M/F5Tur0Rf2z/QoMo+1Ia963RiMtapiQrEWvY0iBUvADo8Beegwjpnle5BHkyHuoxSTW3jF43H1XRA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@sinonjs/commons": "^3.0.1" + } + }, + "node_modules/nise/node_modules/path-to-regexp": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.3.0.tgz", + "integrity": "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-persist": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/node-persist/-/node-persist-3.1.3.tgz", + "integrity": "sha512-CaFv+kSZtsc+VeDRldK1yR47k1vPLBpzYB9re2z7LIwITxwBtljMq3s8VQnnr+x3E8pQfHbc5r2IyJsBLJhtXg==", + "license": "MIT", + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/node-red": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/node-red/-/node-red-4.1.1.tgz", + "integrity": "sha512-yk8cornC+ELzbmQk8yw3KY1jS+djTMDupMOwZ85HeC+zcxJK0LNYUbJPCFI+Bm2NQny9pd863lNj9/tLwCDotg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@node-red/editor-api": "4.1.1", + "@node-red/nodes": "4.1.1", + "@node-red/runtime": "4.1.1", + "@node-red/util": "4.1.1", + "basic-auth": "2.0.1", + "bcryptjs": "3.0.2", + "cors": "2.8.5", + "express": "4.21.2", + "fs-extra": "11.3.0", + "node-red-admin": "^4.1.2", + "nopt": "5.0.0", + "semver": "7.7.1" + }, + "bin": { + "node-red": "red.js", + "node-red-pi": "bin/node-red-pi" + }, + "engines": { + "node": ">=18.5" + }, + "optionalDependencies": { + "@node-rs/bcrypt": "1.10.7" + } + }, + "node_modules/node-red-admin": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/node-red-admin/-/node-red-admin-4.1.2.tgz", + "integrity": "sha512-Yqe3dREfZZmc/BqT3Ntg0DEXivbP3HBNYCbjDkUaakkIIrapNR8TK1vj3RgkSW6FMtpfcVXBcLGI4cA0I1zbOw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "ansi-colors": "^4.1.3", + "axios": "1.12.2", + "bcryptjs": "3.0.2", + "cli-table": "^0.3.11", + "enquirer": "^2.3.6", + "minimist": "^1.2.8", + "mustache": "^4.2.0", + "read": "^3.0.1" + }, + "bin": { + "node-red-admin": "node-red-admin.js" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@node-rs/bcrypt": "1.10.7" + } + }, + "node_modules/node-red-node-test-helper": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/node-red-node-test-helper/-/node-red-node-test-helper-0.3.5.tgz", + "integrity": "sha512-sUsg++CoO19UguqlK6j9q2VmluS7kpYgs45o+U3SAv4wW6BSoXwtuO7pJ+9KVQVmd27zwojw6uaeyLsDsRpL3Q==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "body-parser": "^1.20.3", + "express": "^4.21.0", + "semver": "^7.5.4", + "should": "^13.2.3", + "should-sinon": "^0.0.6", + "sinon": "^11.1.2", + "stoppable": "^1.1.0", + "supertest": "^7.1.4" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/node-red/node_modules/semver": { + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-watch": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/node-watch/-/node-watch-0.7.4.tgz", + "integrity": "sha512-RinNxoz4W1cep1b928fuFhvAQ5ag/+1UlMDV7rbyGthBIgsiEouS4kvRayvvboxii4m8eolKOIBo3OjDqbc+uQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/nopt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/normalize-url": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-8.1.0.tgz", + "integrity": "sha512-X06Mfd/5aKsRHc0O0J5CUedwnPmnDtLF2+nq+KN9KSDlJHkPuh0JUviWjEWMe0SW/9TDdSLVPuk7L5gGTIA1/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/number-allocator": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/number-allocator/-/number-allocator-1.0.14.tgz", + "integrity": "sha512-OrL44UTVAvkKdOdRQZIJpLkAdjXGTRda052sN4sO77bKEzYYqWKMBjQvrJFzqygI99gL6Z4u2xctPW1tB8ErvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.3.1", + "js-sdsl": "4.3.0" + } + }, + "node_modules/oauth2orize": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/oauth2orize/-/oauth2orize-1.12.0.tgz", + "integrity": "sha512-j4XtFDQUBsvUHPjUmvmNDUDMYed2MphMIJBhyxVVe8hGCjkuYnjIsW+D9qk8c5ciXRdnk6x6tEbiO6PLeOZdCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "2.x.x", + "uid2": "0.0.x", + "utils-merge": "1.x.x" + }, + "engines": { + "node": ">= 0.4.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/jaredhanson" + } + }, + "node_modules/oauth2orize/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/oauth2orize/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true, + "license": "MIT" + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-is": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz", + "integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", + "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0", + "has-symbols": "^1.1.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/on-headers": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.1.0.tgz", + "integrity": "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/p-cancelable": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-3.0.0.tgz", + "integrity": "sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.20" + } + }, + "node_modules/p-map": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-7.0.4.tgz", + "integrity": "sha512-tkAQEw8ysMzmkhgw8k+1U/iPhWNhykKnSk4Rd5zLoPJCuJaGRPo6YposrZgaxHKzDHdDWWZvE/Sk7hsL2X/CpQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", + "dev": true, + "license": "MIT" + }, + "node_modules/parse5-htmlparser2-tree-adapter": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz", + "integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==", + "dev": true, + "license": "MIT", + "dependencies": { + "parse5": "^6.0.1" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/passport": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/passport/-/passport-0.7.0.tgz", + "integrity": "sha512-cPLl+qZpSc+ireUvt+IzqbED1cHHkDoVYMo30jbJIdOOjQ1MQYZBPiNvmi8UM6lJuOpTPXJGZQk0DtC4y61MYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "passport-strategy": "1.x.x", + "pause": "0.0.1", + "utils-merge": "^1.0.1" + }, + "engines": { + "node": ">= 0.4.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/jaredhanson" + } + }, + "node_modules/passport-http-bearer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/passport-http-bearer/-/passport-http-bearer-1.0.1.tgz", + "integrity": "sha512-SELQM+dOTuMigr9yu8Wo4Fm3ciFfkMq5h/ZQ8ffi4ELgZrX1xh9PlglqZdcUZ1upzJD/whVyt+YWF62s3U6Ipw==", + "dev": true, + "dependencies": { + "passport-strategy": "1.x.x" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/passport-oauth2-client-password": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/passport-oauth2-client-password/-/passport-oauth2-client-password-0.1.2.tgz", + "integrity": "sha512-GHQH4UtaEZvCLulAxGKHYoSsPRoPRmGsdmaZtMh5nmz80yMLQbdMA9Bg2sp4/UW3PIxJH/143hVjPTiXaNngTQ==", + "dev": true, + "dependencies": { + "passport-strategy": "1.x.x" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/passport-strategy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz", + "integrity": "sha512-CB97UUvDKJde2V0KDWWB3lyf6PC3FaZP7YxZ2G8OAtn9p4HI9j9JLP9qjOGZFvyl8uwNT8qM+hGnz/n16NI7oA==", + "dev": true, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/path-to-regexp": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", + "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/path-type": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-6.0.0.tgz", + "integrity": "sha512-Vj7sf++t5pBD637NSfkxpHSMfWaeig5+DKWLhcqIYx6mWQz5hdJTGDVMQiJcw1ZYkhs7AazKDGpRVji1LJCZUQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "dev": true, + "license": "MIT" + }, + "node_modules/pause": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", + "integrity": "sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg==", + "dev": true + }, + "node_modules/pause-stream": { + "version": "0.0.11", + "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", + "integrity": "sha512-e3FBlXLmN/D1S+zHzanP4E/4Z60oFAa3O051qt1pxa7DEJWKAyil6upYVXCWadEnuoqa4Pkc9oUx9zsxYeRv8A==", + "license": [ + "MIT", + "Apache2" + ], + "dependencies": { + "through": "~2.3" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/possible-typed-array-names": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", + "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/postcss": { + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/presentable-error": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/presentable-error/-/presentable-error-0.0.1.tgz", + "integrity": "sha512-E6rsNU1QNJgB3sjj7OANinGncFKuK+164sLXw1/CqBjj/EkXSoSdHCtWQGBNlREIGLnL7IEUEGa08YFVUbrhVg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true, + "license": "MIT" + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "dev": true, + "license": "MIT" + }, + "node_modules/pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/q": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/q/-/q-1.1.2.tgz", + "integrity": "sha512-ROtylwux7Vkc4C07oKE/ReigUmb33kVoLtcR4SJ1QVqwaZkBEDL3vX4/kwFzIERQ5PfCl0XafbU8u2YUhyGgVA==", + "deprecated": "You or someone you depend on is using Q, the JavaScript Promise library that gave JavaScript developers strong feelings about promises. They can almost certainly migrate to the native JavaScript promise now. Thank you literally everyone for joining me in this bet against the odds. Be excellent to each other.\n\n(For a CapTP with native promises, see @endo/eventual-send and @endo/captp)", + "license": "MIT", + "engines": { + "node": ">=0.6.0", + "teleport": ">=0.2.0" + } + }, + "node_modules/qs": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/random-bytes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", + "integrity": "sha512-iv7LhNVO047HzYR3InF6pUcUsPQiHTM1Qal51DcGSuZFBil1aBBWG5eHPNek7bvILMaYJ/8RU1e8w1AMdHmLQQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.0.tgz", + "integrity": "sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.6.3", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/read": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/read/-/read-3.0.1.tgz", + "integrity": "sha512-SLBrDU/Srs/9EoWhU5GdbAoxG1GzpQHo/6qiGItaoLJ1thmYpcNIM1qISEUvyHBzfGlWIyd6p2DNi1oV1VmAuw==", + "dev": true, + "license": "ISC", + "dependencies": { + "mute-stream": "^1.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/readable-stream": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz", + "integrity": "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==", + "dev": true, + "license": "MIT", + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", + "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "set-function-name": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/reinterval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reinterval/-/reinterval-1.1.0.tgz", + "integrity": "sha512-QIRet3SYrGp0HUHO88jVskiG6seqUGC5iAG7AwI/BV4ypGcuqk9Du6YQBUOUqm9c8pw1eyLoIaONifRua1lsEQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve-alpn": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", + "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", + "dev": true, + "license": "MIT" + }, + "node_modules/responselike": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-3.0.0.tgz", + "integrity": "sha512-40yHxbNcl2+rzXvZuVkrYohathsSJlMTXKryG5y8uciHv1+xDLHQpgjG64JUO9nrEq2jGLH6IZ8BcZyw3wrweg==", + "dev": true, + "license": "MIT", + "dependencies": { + "lowercase-keys": "^3.0.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rfdc": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", + "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", + "dev": true, + "license": "MIT" + }, + "node_modules/rollup": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.53.3.tgz", + "integrity": "sha512-w8GmOxZfBmKknvdXU1sdM9NHcoQejwF/4mNgj2JuEEdRaHwwF12K7e9eXn1nLZ07ad+du76mkVsyeb2rKGllsA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.8" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.53.3", + "@rollup/rollup-android-arm64": "4.53.3", + "@rollup/rollup-darwin-arm64": "4.53.3", + "@rollup/rollup-darwin-x64": "4.53.3", + "@rollup/rollup-freebsd-arm64": "4.53.3", + "@rollup/rollup-freebsd-x64": "4.53.3", + "@rollup/rollup-linux-arm-gnueabihf": "4.53.3", + "@rollup/rollup-linux-arm-musleabihf": "4.53.3", + "@rollup/rollup-linux-arm64-gnu": "4.53.3", + "@rollup/rollup-linux-arm64-musl": "4.53.3", + "@rollup/rollup-linux-loong64-gnu": "4.53.3", + "@rollup/rollup-linux-ppc64-gnu": "4.53.3", + "@rollup/rollup-linux-riscv64-gnu": "4.53.3", + "@rollup/rollup-linux-riscv64-musl": "4.53.3", + "@rollup/rollup-linux-s390x-gnu": "4.53.3", + "@rollup/rollup-linux-x64-gnu": "4.53.3", + "@rollup/rollup-linux-x64-musl": "4.53.3", + "@rollup/rollup-openharmony-arm64": "4.53.3", + "@rollup/rollup-win32-arm64-msvc": "4.53.3", + "@rollup/rollup-win32-ia32-msvc": "4.53.3", + "@rollup/rollup-win32-x64-gnu": "4.53.3", + "@rollup/rollup-win32-x64-msvc": "4.53.3", + "fsevents": "~2.3.2" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/safe-regex-test": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", + "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-regex": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true, + "license": "MIT" + }, + "node_modules/sax": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.3.tgz", + "integrity": "sha512-yqYn1JhPczigF94DMS+shiDMjDowYO6y9+wB/4WgO0Y19jWYk0lQ4tuG5KI7kj4FTp1wxPj5IFfcrz/s1c3jjQ==", + "license": "BlueOak-1.0.0" + }, + "node_modules/semver": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/send": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true, + "license": "MIT" + }, + "node_modules/send/node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/send/node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true, + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/serve-static": { + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", + "dev": true, + "license": "MIT", + "dependencies": { + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.19.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "dev": true, + "license": "ISC" + }, + "node_modules/should": { + "version": "13.2.3", + "resolved": "https://registry.npmjs.org/should/-/should-13.2.3.tgz", + "integrity": "sha512-ggLesLtu2xp+ZxI+ysJTmNjh2U0TsC+rQ/pfED9bUZZ4DKefP27D+7YJVVTvKsmjLpIi9jAa7itwDGkDDmt1GQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "should-equal": "^2.0.0", + "should-format": "^3.0.3", + "should-type": "^1.4.0", + "should-type-adaptors": "^1.0.1", + "should-util": "^1.0.0" + } + }, + "node_modules/should-equal": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/should-equal/-/should-equal-2.0.0.tgz", + "integrity": "sha512-ZP36TMrK9euEuWQYBig9W55WPC7uo37qzAEmbjHz4gfyuXrEUgF8cUvQVO+w+d3OMfPvSRQJ22lSm8MQJ43LTA==", + "dev": true, + "license": "MIT", + "dependencies": { + "should-type": "^1.4.0" + } + }, + "node_modules/should-format": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/should-format/-/should-format-3.0.3.tgz", + "integrity": "sha512-hZ58adtulAk0gKtua7QxevgUaXTTXxIi8t41L3zo9AHvjXO1/7sdLECuHeIN2SRtYXpNkmhoUP2pdeWgricQ+Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "should-type": "^1.3.0", + "should-type-adaptors": "^1.0.1" + } + }, + "node_modules/should-sinon": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/should-sinon/-/should-sinon-0.0.6.tgz", + "integrity": "sha512-ScBOH5uW5QVFaONmUnIXANSR6z5B8IKzEmBP3HE5sPOCDuZ88oTMdUdnKoCVQdLcCIrRrhRLPS5YT+7H40a04g==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "should": ">= 8.x" + } + }, + "node_modules/should-type": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/should-type/-/should-type-1.4.0.tgz", + "integrity": "sha512-MdAsTu3n25yDbIe1NeN69G4n6mUnJGtSJHygX3+oN0ZbO3DTiATnf7XnYJdGT42JCXurTb1JI0qOBR65shvhPQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/should-type-adaptors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/should-type-adaptors/-/should-type-adaptors-1.1.0.tgz", + "integrity": "sha512-JA4hdoLnN+kebEp2Vs8eBe9g7uy0zbRo+RMcU0EsNy+R+k049Ki+N5tT5Jagst2g7EAja+euFuoXFCa8vIklfA==", + "dev": true, + "license": "MIT", + "dependencies": { + "should-type": "^1.3.0", + "should-util": "^1.0.0" + } + }, + "node_modules/should-util": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/should-util/-/should-util-1.0.1.tgz", + "integrity": "sha512-oXF8tfxx5cDk8r2kYqlkUJzZpDBqVY/II2WhvU0n9Y3XYvAYRmeaf1PvvIvTgPnv4KJ+ES5M0PyDq5Jp+Ygy2g==", + "dev": true, + "license": "MIT" + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/siginfo": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", + "dev": true, + "license": "ISC" + }, + "node_modules/sinon": { + "version": "11.1.2", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-11.1.2.tgz", + "integrity": "sha512-59237HChms4kg7/sXhiRcUzdSkKuydDeTiamT/jesUVHshBgL8XAmhgFo0GfK6RruMDM/iRSij1EybmMog9cJw==", + "deprecated": "16.1.1", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@sinonjs/commons": "^1.8.3", + "@sinonjs/fake-timers": "^7.1.2", + "@sinonjs/samsam": "^6.0.2", + "diff": "^5.0.0", + "nise": "^5.1.0", + "supports-color": "^7.2.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/sinon" + } + }, + "node_modules/slash": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", + "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks": { + "version": "2.8.7", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.7.tgz", + "integrity": "sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ip-address": "^10.0.1", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/split": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", + "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", + "license": "MIT", + "dependencies": { + "through": "2" + }, + "engines": { + "node": "*" + } + }, + "node_modules/split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">= 10.x" + } + }, + "node_modules/stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", + "dev": true, + "license": "MIT" + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/std-env": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz", + "integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==", + "dev": true, + "license": "MIT" + }, + "node_modules/stop-iteration-iterator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz", + "integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "internal-slot": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/stoppable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/stoppable/-/stoppable-1.1.0.tgz", + "integrity": "sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4", + "npm": ">=6" + } + }, + "node_modules/stream-combiner": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.2.2.tgz", + "integrity": "sha512-6yHMqgLYDzQDcAkL+tjJDC5nSNuNIx0vZtRZeiPh7Saef7VHX9H5Ijn9l2VIol2zaNYlYEX6KyuT/237A58qEQ==", + "license": "MIT", + "dependencies": { + "duplexer": "~0.1.1", + "through": "~2.3.4" + } + }, + "node_modules/streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "dev": true, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/superagent": { + "version": "10.2.3", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-10.2.3.tgz", + "integrity": "sha512-y/hkYGeXAj7wUMjxRbB21g/l6aAEituGXM9Rwl4o20+SX3e8YOSV6BxFXl+dL3Uk0mjSL3kCbNkwURm8/gEDig==", + "dev": true, + "license": "MIT", + "dependencies": { + "component-emitter": "^1.3.1", + "cookiejar": "^2.1.4", + "debug": "^4.3.7", + "fast-safe-stringify": "^2.1.1", + "form-data": "^4.0.4", + "formidable": "^3.5.4", + "methods": "^1.1.2", + "mime": "2.6.0", + "qs": "^6.11.2" + }, + "engines": { + "node": ">=14.18.0" + } + }, + "node_modules/superagent/node_modules/mime": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", + "dev": true, + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/supertest": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/supertest/-/supertest-7.1.4.tgz", + "integrity": "sha512-tjLPs7dVyqgItVFirHYqe2T+MfWc2VOBQ8QFKKbWTA3PU7liZR8zoSpAi/C1k1ilm9RsXIKYf197oap9wXGVYg==", + "dev": true, + "license": "MIT", + "dependencies": { + "methods": "^1.1.2", + "superagent": "^10.2.3" + }, + "engines": { + "node": ">=14.18.0" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tar": { + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.4.3.tgz", + "integrity": "sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==", + "dev": true, + "license": "ISC", + "dependencies": { + "@isaacs/fs-minipass": "^4.0.0", + "chownr": "^3.0.0", + "minipass": "^7.1.2", + "minizlib": "^3.0.1", + "mkdirp": "^3.0.1", + "yallist": "^5.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/tar/node_modules/mkdirp": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", + "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", + "dev": true, + "license": "MIT", + "bin": { + "mkdirp": "dist/cjs/src/bin.js" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/tar/node_modules/yallist": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", + "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", + "license": "MIT" + }, + "node_modules/thunky": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", + "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", + "license": "MIT" + }, + "node_modules/tinybench": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", + "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinyexec": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz", + "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinyglobby": { + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyglobby/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/tinyglobby/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/tinyrainbow": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.0.3.tgz", + "integrity": "sha512-PSkbLUoxOFRzJYjjxHJt9xro7D+iilgMX/C9lawzVuYiIdcihh9DXmVibBe8lmcFrRi/VzlPjBxbN7rH24q8/Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tldts": { + "version": "6.1.86", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.86.tgz", + "integrity": "sha512-WMi/OQ2axVTf/ykqCQgXiIct+mSQDFdH2fkwhPwgEwvJ1kSzZRiinb0zF2Xb8u4+OqPChmyI6MEu4EezNJz+FQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "tldts-core": "^6.1.86" + }, + "bin": { + "tldts": "bin/cli.js" + } + }, + "node_modules/tldts-core": { + "version": "6.1.86", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.86.tgz", + "integrity": "sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA==", + "dev": true, + "license": "MIT" + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/tough-cookie": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.1.2.tgz", + "integrity": "sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "tldts": "^6.1.32" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/ts-node": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/ts-node/node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/tweetnacl": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", + "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==", + "license": "Unlicense" + }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/type-is/node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/uglify-js": { + "version": "3.19.3", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", + "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==", + "dev": true, + "license": "BSD-2-Clause", + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/uid-safe": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", + "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==", + "dev": true, + "license": "MIT", + "dependencies": { + "random-bytes": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/uid2": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/uid2/-/uid2-0.0.4.tgz", + "integrity": "sha512-IevTus0SbGwQzYh3+fRsAMTVVPOoIVufzacXcHPmdlle1jUpq7BRL+mw3dgeLanvGZdwwbWhRV6XrcFNdBmjWA==", + "dev": true, + "license": "MIT" + }, + "node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/unicorn-magic": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.3.0.tgz", + "integrity": "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true, + "license": "MIT" + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/uuid": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-13.0.0.tgz", + "integrity": "sha512-XQegIaBTVUjSHliKqcnFqYypAd4S+WCYt5NIeRs6w/UAry7z8Y9j5ZwRRL4kzq9U3sD6v+85er9FvkEaBpji2w==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist-node/bin/uuid" + } + }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true, + "license": "MIT" + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/vite": { + "version": "7.2.4", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.2.4.tgz", + "integrity": "sha512-NL8jTlbo0Tn4dUEXEsUg8KeyG/Lkmc4Fnzb8JXN/Ykm9G4HNImjtABMJgkQoVjOBN/j2WAwDTRytdqJbZsah7w==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.25.0", + "fdir": "^6.5.0", + "picomatch": "^4.0.3", + "postcss": "^8.5.6", + "rollup": "^4.43.0", + "tinyglobby": "^0.2.15" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^20.19.0 || >=22.12.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "lightningcss": "^1.21.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/vite/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/vite/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/vitest": { + "version": "4.0.13", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.0.13.tgz", + "integrity": "sha512-QSD4I0fN6uZQfftryIXuqvqgBxTvJ3ZNkF6RWECd82YGAYAfhcppBLFXzXJHQAAhVFyYEuFTrq6h0hQqjB7jIQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/expect": "4.0.13", + "@vitest/mocker": "4.0.13", + "@vitest/pretty-format": "4.0.13", + "@vitest/runner": "4.0.13", + "@vitest/snapshot": "4.0.13", + "@vitest/spy": "4.0.13", + "@vitest/utils": "4.0.13", + "debug": "^4.4.3", + "es-module-lexer": "^1.7.0", + "expect-type": "^1.2.2", + "magic-string": "^0.30.21", + "pathe": "^2.0.3", + "picomatch": "^4.0.3", + "std-env": "^3.10.0", + "tinybench": "^2.9.0", + "tinyexec": "^0.3.2", + "tinyglobby": "^0.2.15", + "tinyrainbow": "^3.0.3", + "vite": "^6.0.0 || ^7.0.0", + "why-is-node-running": "^2.3.0" + }, + "bin": { + "vitest": "vitest.mjs" + }, + "engines": { + "node": "^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@opentelemetry/api": "^1.9.0", + "@types/debug": "^4.1.12", + "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", + "@vitest/browser-playwright": "4.0.13", + "@vitest/browser-preview": "4.0.13", + "@vitest/browser-webdriverio": "4.0.13", + "@vitest/ui": "4.0.13", + "happy-dom": "*", + "jsdom": "*" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@opentelemetry/api": { + "optional": true + }, + "@types/debug": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser-playwright": { + "optional": true + }, + "@vitest/browser-preview": { + "optional": true + }, + "@vitest/browser-webdriverio": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + } + } + }, + "node_modules/vitest/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", + "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", + "license": "MIT", + "dependencies": { + "is-bigint": "^1.1.0", + "is-boolean-object": "^1.2.1", + "is-number-object": "^1.1.1", + "is-string": "^1.1.1", + "is-symbol": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-collection": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", + "license": "MIT", + "dependencies": { + "is-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.19", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz", + "integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==", + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "for-each": "^0.3.5", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/why-is-node-running": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", + "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", + "dev": true, + "license": "MIT", + "dependencies": { + "siginfo": "^2.0.0", + "stackback": "0.0.2" + }, + "bin": { + "why-is-node-running": "cli.js" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/worker-timers": { + "version": "7.1.8", + "resolved": "https://registry.npmjs.org/worker-timers/-/worker-timers-7.1.8.tgz", + "integrity": "sha512-R54psRKYVLuzff7c1OTFcq/4Hue5Vlz4bFtNEIarpSiCYhpifHU3aIQI29S84o1j87ePCYqbmEJPqwBTf+3sfw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.24.5", + "tslib": "^2.6.2", + "worker-timers-broker": "^6.1.8", + "worker-timers-worker": "^7.0.71" + } + }, + "node_modules/worker-timers-broker": { + "version": "6.1.8", + "resolved": "https://registry.npmjs.org/worker-timers-broker/-/worker-timers-broker-6.1.8.tgz", + "integrity": "sha512-FUCJu9jlK3A8WqLTKXM9E6kAmI/dR1vAJ8dHYLMisLNB/n3GuaFIjJ7pn16ZcD1zCOf7P6H62lWIEBi+yz/zQQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.24.5", + "fast-unique-numbers": "^8.0.13", + "tslib": "^2.6.2", + "worker-timers-worker": "^7.0.71" + } + }, + "node_modules/worker-timers-worker": { + "version": "7.0.71", + "resolved": "https://registry.npmjs.org/worker-timers-worker/-/worker-timers-worker-7.0.71.tgz", + "integrity": "sha512-ks/5YKwZsto1c2vmljroppOKCivB/ma97g9y77MAAz2TBBjPPgpoOiS1qYQKIgvGTr2QYPT3XhJWIB6Rj2MVPQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.24.5", + "tslib": "^2.6.2" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/ws": { + "version": "7.5.10", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", + "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true } + } + }, + "node_modules/xml2js": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.6.2.tgz", + "integrity": "sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA==", + "license": "MIT", + "dependencies": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", + "license": "MIT", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==", + "dev": true, + "license": "ISC" + }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } } + } } diff --git a/package.json b/package.json index 231d9972..41fc4c9a 100644 --- a/package.json +++ b/package.json @@ -1,93 +1,85 @@ { - "name": "node-red-contrib-homekit-bridged", - "version": "2.0.0-dev.1", - "description": "Node-RED nodes to simulate Apple HomeKit devices.", - "main": "build/nodes/nrchkb.js", - "scripts": { - "build": "npm run clean && tsc", - "clean": "del-cli \"build/lib\" \"build/**/*.js\"", - "test": "vitest run", - "test:watch": "vitest", - "prettier": "prettier --write \"**/*.{js,ts}\"", - "eslint": "eslint \"src/**/*.ts\" --fix", - "prepare": "husky install" + "name": "node-red-contrib-homekit-bridged", + "version": "2.0.0-dev.1", + "description": "Node-RED nodes to simulate Apple HomeKit devices.", + "main": "build/nodes/nrchkb.js", + "scripts": { + "build": "npm run clean && tsc", + "clean": "del-cli \"build/lib\" \"build/**/*.js\"", + "test": "vitest run", + "test:watch": "vitest", + "format": "biome format --write", + "prepare": "husky install" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/NRCHKB/node-red-contrib-homekit-bridged.git" + }, + "keywords": [ + "homekit", + "node-red", + "NRCHKB", + "iot", + "home", + "hap-nodejs", + "homebridge" + ], + "node-red": { + "nodes": { + "nrchkb": "build/nodes/nrchkb.js", + "bridge": "build/nodes/bridge.js", + "standalone": "build/nodes/standalone.js", + "service": "build/nodes/service.js", + "service2": "build/nodes/service2.js", + "status": "build/nodes/status.js" }, - "repository": { - "type": "git", - "url": "git+https://github.com/NRCHKB/node-red-contrib-homekit-bridged.git" - }, - "keywords": [ - "homekit", - "node-red", - "NRCHKB", - "iot", - "home", - "hap-nodejs", - "homebridge" - ], - "node-red": { - "nodes": { - "nrchkb": "build/nodes/nrchkb.js", - "bridge": "build/nodes/bridge.js", - "standalone": "build/nodes/standalone.js", - "service": "build/nodes/service.js", - "service2": "build/nodes/service2.js", - "status": "build/nodes/status.js" - }, - "version": ">=1.3.7" - }, - "author": "Tadeusz Wyrzykowski (https://github.com/Shaquu)", - "license": "Apache-2.0", - "bugs": { - "url": "https://github.com/NRCHKB/node-red-contrib-homekit-bridged/issues" - }, - "homepage": "https://github.com/NRCHKB/node-red-contrib-homekit-bridged#readme", - "dependencies": { - "@homebridge/hap-nodejs": "2.0.2", - "@nrchkb/logger": "~3.1.1", - "node-persist": "^3.1.3", - "semver": "~7.7.3", - "uuid": "~13.0.0" - }, - "devDependencies": { - "@homebridge/ciao": "~1.3.4", - "@node-red/registry": "^4.1.1", - "@types/node": "^20", - "@types/node-persist": "^3.1.8", - "@types/node-red": "^1.3.5", - "@types/node-red-node-test-helper": "^0.3.5", - "@types/semver": "^7.7.1", - "@types/uuid": "^10.0.0", - "@typescript-eslint/eslint-plugin": "^7.16.0", - "@typescript-eslint/parser": "^7.16.0", - "babel-eslint": "^10.1.0", - "del-cli": "^7.0.0", - "eslint": "^8", - "eslint-config-prettier": "^9.1.0", - "eslint-plugin-prettier": "^5.5.4", - "eslint-plugin-simple-import-sort": "^12.1.1", - "husky": "^9.1.7", - "node-red": "^4.1.1", - "node-red-node-test-helper": "^0.3.5", - "prettier": "^3.6.2", - "ts-node": "^10.9.2", - "typescript": "^5.9.3", - "vitest": "^4.0.13" - }, - "vitest": { - "test": { - "environment": "node", - "testTimeout": 30000, - "include": [ - "src/**/*.test.ts" - ] - } - }, - "engines": { - "node": "^20 || ^22 || ^24" - }, - "files": [ - "/build", - "/examples" - ] + "version": ">=1.3.7" + }, + "author": "Tadeusz Wyrzykowski (https://github.com/Shaquu)", + "license": "Apache-2.0", + "bugs": { + "url": "https://github.com/NRCHKB/node-red-contrib-homekit-bridged/issues" + }, + "homepage": "https://github.com/NRCHKB/node-red-contrib-homekit-bridged#readme", + "dependencies": { + "@homebridge/hap-nodejs": "2.0.2", + "@nrchkb/logger": "~3.1.1", + "node-persist": "^3.1.3", + "semver": "~7.7.3", + "uuid": "~13.0.0" + }, + "devDependencies": { + "@biomejs/biome": "2.3.7", + "@homebridge/ciao": "~1.3.4", + "@node-red/registry": "^4.1.1", + "@types/node": "^20", + "@types/node-persist": "^3.1.8", + "@types/node-red": "^1.3.5", + "@types/node-red-node-test-helper": "^0.3.5", + "@types/semver": "^7.7.1", + "@types/uuid": "^10.0.0", + "del-cli": "^7.0.0", + "husky": "^9.1.7", + "node-red": "^4.1.1", + "node-red-node-test-helper": "^0.3.5", + "ts-node": "^10.9.2", + "typescript": "^5.9.3", + "vitest": "^4.0.13" + }, + "vitest": { + "test": { + "environment": "node", + "testTimeout": 30000, + "include": [ + "src/**/*.test.ts" + ] + } + }, + "engines": { + "node": "^20 || ^22 || ^24" + }, + "files": [ + "/build", + "/examples" + ] } diff --git a/src/lib/HAPHostNode.ts b/src/lib/HAPHostNode.ts index 57b3a746..a3e37418 100644 --- a/src/lib/HAPHostNode.ts +++ b/src/lib/HAPHostNode.ts @@ -1,11 +1,11 @@ import { - Accessory, - Bridge, - Categories, - Characteristic, - MDNSAdvertiser, - Service, - uuid, + Accessory, + Bridge, + Categories, + Characteristic, + MDNSAdvertiser, + Service, + uuid } from '@homebridge/hap-nodejs' import { logger } from '@nrchkb/logger' import { NodeAPI } from 'node-red' @@ -19,186 +19,177 @@ import HAPHostNodeType from './types/HAPHostNodeType' import HostType from './types/HostType' module.exports = (RED: NodeAPI, hostType: HostType) => { - const init = function (this: HAPHostNodeType, config: HAPHostConfigType) { - const self = this - const log = logger('NRCHKB', 'HAPHostNode', config.bridgeName, self) + const init = function (this: HAPHostNodeType, config: HAPHostConfigType) { + const self = this + const log = logger('NRCHKB', 'HAPHostNode', config.bridgeName, self) - self.hostType = hostType - RED.nodes.createNode(self, config) + self.hostType = hostType + RED.nodes.createNode(self, config) - self.config = config - self.name = config.bridgeName + self.config = config + self.name = config.bridgeName - if (!hostNameValidator(config.bridgeName)) { - log.error('Host name is incorrect', false) - return new NRCHKBError('Host name is incorrect') - } - - if (semver.parse(config.firmwareRev) == null) { - config.firmwareRev = new SemVer('0.0.0') - } - - self.accessoryCategory = (self.hostType == HostType.BRIDGE - ? HapCategories.BRIDGE - : self.config.accessoryCategory) as unknown as Categories + if (!hostNameValidator(config.bridgeName)) { + log.error('Host name is incorrect', false) + return new NRCHKBError('Host name is incorrect') + } - self.published = false + if (semver.parse(config.firmwareRev) == null) { + config.firmwareRev = new SemVer('0.0.0') + } - try { - self.bridgeUsername = macify(self.id) - } catch (error: any) { - log.error(error) - return error - } + self.accessoryCategory = (self.hostType == HostType.BRIDGE + ? HapCategories.BRIDGE + : self.config.accessoryCategory) as unknown as Categories - const hostUUID = uuid.generate(self.id) + self.published = false - const hostTypeName = - self.hostType == HostType.BRIDGE ? 'Bridge' : 'Standalone Accessory' + try { + self.bridgeUsername = macify(self.id) + } catch (error: any) { + log.error(error) + return error + } - log.debug(`Creating ${hostTypeName} with UUID ${hostUUID}`) + const hostUUID = uuid.generate(self.id) - if (self.hostType == HostType.BRIDGE) { - self.host = new Bridge(self.name, hostUUID) - } else { - self.host = new Accessory(self.name, hostUUID) - } + const hostTypeName = + self.hostType == HostType.BRIDGE ? 'Bridge' : 'Standalone Accessory' - self.publish = function () { - if (self.hostType == HostType.BRIDGE) { - log.debug( - `Publishing ${hostTypeName} with pin code ${self.config.pinCode} and ${self.host.bridgedAccessories.length} accessories` - ) - } else { - log.debug( - `Publishing ${hostTypeName} with pin code ${self.config.pinCode}` - ) - } - - if (self.config.port && self.config.port == 1880) { - log.error( - `Cannot publish on ${hostTypeName} port 1880 as it is reserved for node-red` - ) - self.published = false - return false - } - - // As HAP-Nodejs cannot understand new pin code format yet, we need to adjust new to old one - let oldPinCode = self.config.pinCode - - if ((oldPinCode.match(/-/g) || []).length == 1) { - oldPinCode = oldPinCode.replace(/-/g, '') - oldPinCode = `${oldPinCode.slice(0, 3)}-${oldPinCode.slice(3, 5)}-${oldPinCode.slice(5, 8)}` - } - - let bind - if (self.config.bind?.length && self.config.bindType) { - if (self.config.bindType == 'str') { - bind = self.config.bind - } else if (self.config.bindType == 'json') { - bind = JSON.parse(self.config.bind) - } - } - - self.host.publish( - { - username: self.bridgeUsername, - port: - self.config.port && !isNaN(self.config.port) - ? self.config.port - : 0, - pincode: oldPinCode, - category: self.accessoryCategory, - bind: bind, - advertiser: - self.config.advertiser ?? MDNSAdvertiser.BONJOUR, - }, - self.config.allowInsecureRequest - ) - - self.published = true - - return true - } + log.debug(`Creating ${hostTypeName} with UUID ${hostUUID}`) - self.on('close', async function (removed: any, done: () => any) { - if (removed) { - log.debug('This node has been deleted') - await self.host.destroy() - } else { - log.debug('This node is being restarted') - await self.host.unpublish() - } - - self.published = false - - done() - }) - - self.host.on('identify', function (paired: any, callback: () => any) { - if (paired) { - log.debug(`Identify called on paired ${hostTypeName}`) - } else { - log.debug(`Identify called on unpaired ${hostTypeName}`) - } - - callback() - }) - - // Service.AccessoryInformation created on Host creation - const accessoryInformationService = - self.host.getService(Service.AccessoryInformation) || - self.host.addService(Service.AccessoryInformation) - - accessoryInformationService - .setCharacteristic( - Characteristic.Manufacturer, - self.config.manufacturer - ) - .setCharacteristic( - Characteristic.SerialNumber, - self.config.serialNo - ) - .setCharacteristic(Characteristic.Model, self.config.model) - .setCharacteristic( - Characteristic.FirmwareRevision, - self.config.firmwareRev?.toString() - ) - .setCharacteristic( - Characteristic.HardwareRevision, - self.config.hardwareRev?.toString() - ) - .setCharacteristic( - Characteristic.SoftwareRevision, - self.config.softwareRev?.toString() - ) + if (self.hostType == HostType.BRIDGE) { + self.host = new Bridge(self.name, hostUUID) + } else { + self.host = new Accessory(self.name, hostUUID) } - const macify = (nodeId: string): string => { - if (nodeId) { - const noDecimalStr = nodeId.replace('.', '') - const paddedStr = noDecimalStr.padEnd(12, '0') - - const match = paddedStr.match(/.{1,2}/g) - - if (match) { - return match.join(':').substr(0, 17).toUpperCase() - } else { - throw new NRCHKBError( - `match failed in macify process for padded string ${paddedStr}` - ) - } - } else { - throw new NRCHKBError('nodeId cannot be empty in macify process') + self.publish = function () { + if (self.hostType == HostType.BRIDGE) { + log.debug( + `Publishing ${hostTypeName} with pin code ${self.config.pinCode} and ${self.host.bridgedAccessories.length} accessories` + ) + } else { + log.debug( + `Publishing ${hostTypeName} with pin code ${self.config.pinCode}` + ) + } + + if (self.config.port && self.config.port == 1880) { + log.error( + `Cannot publish on ${hostTypeName} port 1880 as it is reserved for node-red` + ) + self.published = false + return false + } + + // As HAP-Nodejs cannot understand new pin code format yet, we need to adjust new to old one + let oldPinCode = self.config.pinCode + + if ((oldPinCode.match(/-/g) || []).length == 1) { + oldPinCode = oldPinCode.replace(/-/g, '') + oldPinCode = `${oldPinCode.slice(0, 3)}-${oldPinCode.slice(3, 5)}-${oldPinCode.slice(5, 8)}` + } + + let bind + if (self.config.bind?.length && self.config.bindType) { + if (self.config.bindType == 'str') { + bind = self.config.bind + } else if (self.config.bindType == 'json') { + bind = JSON.parse(self.config.bind) } + } + + self.host.publish( + { + username: self.bridgeUsername, + port: + self.config.port && !isNaN(self.config.port) ? self.config.port : 0, + pincode: oldPinCode, + category: self.accessoryCategory, + bind: bind, + advertiser: self.config.advertiser ?? MDNSAdvertiser.BONJOUR + }, + self.config.allowInsecureRequest + ) + + self.published = true + + return true } - const hostNameValidator = function (hostName: string) { - return hostName ? /^[^.]{1,64}$/.test(hostName) : false + self.on('close', async function (removed: any, done: () => any) { + if (removed) { + log.debug('This node has been deleted') + await self.host.destroy() + } else { + log.debug('This node is being restarted') + await self.host.unpublish() + } + + self.published = false + + done() + }) + + self.host.on('identify', function (paired: any, callback: () => any) { + if (paired) { + log.debug(`Identify called on paired ${hostTypeName}`) + } else { + log.debug(`Identify called on unpaired ${hostTypeName}`) + } + + callback() + }) + + // Service.AccessoryInformation created on Host creation + const accessoryInformationService = + self.host.getService(Service.AccessoryInformation) || + self.host.addService(Service.AccessoryInformation) + + accessoryInformationService + .setCharacteristic(Characteristic.Manufacturer, self.config.manufacturer) + .setCharacteristic(Characteristic.SerialNumber, self.config.serialNo) + .setCharacteristic(Characteristic.Model, self.config.model) + .setCharacteristic( + Characteristic.FirmwareRevision, + self.config.firmwareRev?.toString() + ) + .setCharacteristic( + Characteristic.HardwareRevision, + self.config.hardwareRev?.toString() + ) + .setCharacteristic( + Characteristic.SoftwareRevision, + self.config.softwareRev?.toString() + ) + } + + const macify = (nodeId: string): string => { + if (nodeId) { + const noDecimalStr = nodeId.replace('.', '') + const paddedStr = noDecimalStr.padEnd(12, '0') + + const match = paddedStr.match(/.{1,2}/g) + + if (match) { + return match.join(':').substr(0, 17).toUpperCase() + } else { + throw new NRCHKBError( + `match failed in macify process for padded string ${paddedStr}` + ) + } + } else { + throw new NRCHKBError('nodeId cannot be empty in macify process') } + } - return { - init, - macify, - } + const hostNameValidator = function (hostName: string) { + return hostName ? /^[^.]{1,64}$/.test(hostName) : false + } + + return { + init, + macify + } } diff --git a/src/lib/HAPServiceNode.ts b/src/lib/HAPServiceNode.ts index 7d96f496..abab25d1 100644 --- a/src/lib/HAPServiceNode.ts +++ b/src/lib/HAPServiceNode.ts @@ -10,282 +10,280 @@ import HostType from './types/HostType' import { NodeStatusUtils } from './utils/NodeStatusUtils' module.exports = (RED: NodeAPI) => { - /** - * Config override when user created services in old NRCHKB version - */ - const nrchkbConfigCompatibilityOverride = function ( - this: HAPServiceNodeType - ) { - const self = this - - const log = logger('NRCHKB', 'HAPServiceNode', self.config.name, self) - - if (self.config.isParent === undefined) { - log.trace( - `nrchkbConfigCompatibilityOverride => self.config.isParent=${self.config.isParent} value changed to true` - ) - // Services created in pre linked services era where working in 1.2 but due to more typescript in 1.3+ it started to cause some errors - self.config.isParent = true - } - - if (self.config.hostType === undefined) { - // When moving from 1.2 to 1.3 hostType is not defined on homekit-service - log.trace( - `nrchkbConfigCompatibilityOverride => self.config.hostType=${self.config.hostType} value changed to HostType.BRIDGE` - ) - self.config.hostType = HostType.BRIDGE - } + /** + * Config override when user created services in old NRCHKB version + */ + const nrchkbConfigCompatibilityOverride = function ( + this: HAPServiceNodeType + ) { + const self = this + + const log = logger('NRCHKB', 'HAPServiceNode', self.config.name, self) + + if (self.config.isParent === undefined) { + log.trace( + `nrchkbConfigCompatibilityOverride => self.config.isParent=${self.config.isParent} value changed to true` + ) + // Services created in pre linked services era where working in 1.2 but due to more typescript in 1.3+ it started to cause some errors + self.config.isParent = true } - const preInit = function ( - this: HAPServiceNodeType, - config: HAPServiceConfigType - ) { - const self = this - self.nodeStatusUtils = new NodeStatusUtils(self) + if (self.config.hostType === undefined) { + // When moving from 1.2 to 1.3 hostType is not defined on homekit-service + log.trace( + `nrchkbConfigCompatibilityOverride => self.config.hostType=${self.config.hostType} value changed to HostType.BRIDGE` + ) + self.config.hostType = HostType.BRIDGE + } + } + + const preInit = function ( + this: HAPServiceNodeType, + config: HAPServiceConfigType + ) { + const self = this + self.nodeStatusUtils = new NodeStatusUtils(self) - self.config = config - self.name = self.config.name + self.config = config + self.name = self.config.name - const log = logger('NRCHKB', 'HAPServiceNode', self.config.name, self) + const log = logger('NRCHKB', 'HAPServiceNode', self.config.name, self) - self.RED = RED - self.publishTimers = {} + self.RED = RED + self.publishTimers = {} - nrchkbConfigCompatibilityOverride.call(self) - RED.nodes.createNode(self, self.config) + nrchkbConfigCompatibilityOverride.call(self) + RED.nodes.createNode(self, self.config) - const ServiceUtils = require('./utils/ServiceUtils')(self) + const ServiceUtils = require('./utils/ServiceUtils')(self) - new Promise((resolve) => { - if (self.config.waitForSetupMsg) { - log.debug( - 'Waiting for Setup message. It should be of format {"payload":{"nrchkb":{"setup":{}}}}' - ) + new Promise((resolve) => { + if (self.config.waitForSetupMsg) { + log.debug( + 'Waiting for Setup message. It should be of format {"payload":{"nrchkb":{"setup":{}}}}' + ) - self.setupDone = false + self.setupDone = false - self.nodeStatusUtils.setStatus({ - fill: 'blue', - shape: 'dot', - text: 'Waiting for Setup', - }) + self.nodeStatusUtils.setStatus({ + fill: 'blue', + shape: 'dot', + text: 'Waiting for Setup' + }) - self.handleWaitForSetup = (msg: Record) => - ServiceUtils.handleWaitForSetup(self.config, msg, resolve) - self.on('input', self.handleWaitForSetup) - } else { - resolve(self.config) - } + self.handleWaitForSetup = (msg: Record) => + ServiceUtils.handleWaitForSetup(self.config, msg, resolve) + self.on('input', self.handleWaitForSetup) + } else { + resolve(self.config) + } + }) + .then((newConfig) => { + init.call(self, newConfig) + }) + .catch((error: any) => { + log.error(`Error while starting Service due to ${error}`) + }) + } + + const init = function ( + this: HAPServiceNodeType, + config: HAPServiceConfigType + ) { + const self = this + self.config = config + + const log = logger('NRCHKB', 'HAPServiceNode', self.config.name, self) + + const ServiceUtils = require('./utils/ServiceUtils')(self) + + if (self.config.isParent) { + log.debug('Starting Parent Service') + configure.call(self) + self.configured = true + self.reachable = true + } else { + const serviceType = + config.serviceName === 'CameraControl' ? 'Camera' : 'Linked' + + ServiceUtils.waitForParent() + .then(() => { + log.debug(`Starting ${serviceType} Service`) + configure.call(self) + self.configured = true + }) + .catch((error: any) => { + log.error( + `Error while starting ${serviceType} Service due to ${error}` + ) }) - .then((newConfig) => { - init.call(self, newConfig) - }) - .catch((error: any) => { - log.error(`Error while starting Service due to ${error}`) - }) } + } + + const configure = function (this: HAPServiceNodeType) { + const self = this + + const log = logger('NRCHKB', 'HAPServiceNode', self.config.name, self) + + const Utils = require('./utils')(self) + const AccessoryUtils = Utils.AccessoryUtils + const BridgeUtils = Utils.BridgeUtils + const CharacteristicUtils = Utils.CharacteristicUtils + const ServiceUtils = Utils.ServiceUtils + + let parentNode: HAPServiceNodeType + + if (self.config.isParent) { + const hostId = + self.config.hostType == HostType.BRIDGE + ? self.config.bridge + : self.config.accessoryId + + self.hostNode = RED.nodes.getNode(hostId) as HAPHostNodeType + + if (!self.hostNode) { + const message = `Host node ${self.config.hostType == HostType.BRIDGE ? 'Bridge' : 'Standalone Accessory'} ${hostId} not found` + log.error(message, false) + throw new NRCHKBError(message) + } + + self.childNodes = [] + self.childNodes.push(self) + } else { + // Retrieve parent service node + parentNode = RED.nodes.getNode( + self.config.parentService + ) as HAPServiceNodeType + + if (!parentNode) { + log.error('Parent Node not assigned', false) + throw new NRCHKBError('Parent Node not assigned') + } + + self.parentNode = parentNode + self.parentService = self.parentNode.service + + if (!self.parentService) { + log.error('Parent Service not assigned', false) + throw new NRCHKBError('Parent Service not assigned') + } + + self.hostNode = self.parentNode.hostNode + self.parentNode.childNodes?.push(self) + + self.accessory = self.parentNode.accessory + } + + // Service node properties + self.name = self.config.name - const init = function ( - this: HAPServiceNodeType, - config: HAPServiceConfigType + // Find a unique identifier for the current service + if ( + self.hasOwnProperty('_flow') && + self.hasOwnProperty('_alias') && + self._flow?.hasOwnProperty('TYPE') && + self._flow.TYPE === 'subflow' ) { - const self = this - self.config = config - - const log = logger('NRCHKB', 'HAPServiceNode', self.config.name, self) - - const ServiceUtils = require('./utils/ServiceUtils')(self) - - if (self.config.isParent) { - log.debug('Starting Parent Service') - configure.call(self) - self.configured = true - self.reachable = true - } else { - const serviceType = - config.serviceName === 'CameraControl' ? 'Camera' : 'Linked' - - ServiceUtils.waitForParent() - .then(() => { - log.debug(`Starting ${serviceType} Service`) - configure.call(self) - self.configured = true - }) - .catch((error: any) => { - log.error( - `Error while starting ${serviceType} Service due to ${error}` - ) - }) - } + // For subflows, use the service node identifier from the subflow template + // plus the full path from the subflow node identifier to the subflow. + self.uniqueIdentifier = self._alias + '/' + self._flow.path + } else { + // For top level flows, use the node identifier + self.uniqueIdentifier = self.id } - const configure = function (this: HAPServiceNodeType) { - const self = this - - const log = logger('NRCHKB', 'HAPServiceNode', self.config.name, self) - - const Utils = require('./utils')(self) - const AccessoryUtils = Utils.AccessoryUtils - const BridgeUtils = Utils.BridgeUtils - const CharacteristicUtils = Utils.CharacteristicUtils - const ServiceUtils = Utils.ServiceUtils - - let parentNode: HAPServiceNodeType - - if (self.config.isParent) { - const hostId = - self.config.hostType == HostType.BRIDGE - ? self.config.bridge - : self.config.accessoryId - - self.hostNode = RED.nodes.getNode(hostId) as HAPHostNodeType - - if (!self.hostNode) { - const message = `Host node ${self.config.hostType == HostType.BRIDGE ? 'Bridge' : 'Standalone Accessory'} ${hostId} not found` - log.error(message, false) - throw new NRCHKBError(message) - } - - self.childNodes = [] - self.childNodes.push(self) - } else { - // Retrieve parent service node - parentNode = RED.nodes.getNode( - self.config.parentService - ) as HAPServiceNodeType - - if (!parentNode) { - log.error('Parent Node not assigned', false) - throw new NRCHKBError('Parent Node not assigned') - } - - self.parentNode = parentNode - self.parentService = self.parentNode.service - - if (!self.parentService) { - log.error('Parent Service not assigned', false) - throw new NRCHKBError('Parent Service not assigned') - } - - self.hostNode = self.parentNode.hostNode - self.parentNode.childNodes?.push(self) - - self.accessory = self.parentNode.accessory - } - - // Service node properties - self.name = self.config.name - - // Find a unique identifier for the current service - if ( - self.hasOwnProperty('_flow') && - self.hasOwnProperty('_alias') && - self._flow?.hasOwnProperty('TYPE') && - self._flow.TYPE === 'subflow' - ) { - // For subflows, use the service node identifier from the subflow template - // plus the full path from the subflow node identifier to the subflow. - self.uniqueIdentifier = self._alias + '/' + self._flow.path - } else { - // For top level flows, use the node identifier - self.uniqueIdentifier = self.id - } - - // Generate UUID from unique identifier - const subtypeUUID = uuid.generate(self.uniqueIdentifier) - - // Look for existing Accessory or create a new one - if (self.config.hostType == HostType.BRIDGE) { - if (self.config.isParent) { - // According to the HomeKit Accessory Protocol Specification the value - // of the fields Name, Manufacturer, Serial Number and Model must not - // change throughout the lifetime of an accessory. Because of that the - // accessory UUID will be generated based on that data to ensure that - // a new accessory will be created if any of those configuration values - // changes. - const accessoryUUID = uuid.generate( - 'A' + - self.uniqueIdentifier + - self.name + - self.config.manufacturer + - self.config.serialNo + - self.config.model - ) - - self.accessory = AccessoryUtils.getOrCreate( - self.hostNode.host, - { - name: self.name, - UUID: accessoryUUID, - manufacturer: self.config.manufacturer, - serialNo: self.config.serialNo, - model: self.config.model, - firmwareRev: self.config.firmwareRev, - hardwareRev: self.config.hardwareRev, - softwareRev: self.config.softwareRev, - }, - subtypeUUID // subtype of the primary service for identification - ) - - //Respond to identify - self.onIdentify = AccessoryUtils.onIdentify - self.accessory.on('identify', self.onIdentify) - } - } else { - // We are using Standalone Accessory mode so no need to create new Accessory as we have "host" already - log.debug('Binding Service accessory as Standalone Accessory') - self.accessory = self.hostNode.host - } - - // Look for existing Service or create a new one - self.service = ServiceUtils.getOrCreate( - self.accessory, - { - name: self.name, - UUID: subtypeUUID, - serviceName: self.config.serviceName, - config: self.config, - }, - self.parentService + // Generate UUID from unique identifier + const subtypeUUID = uuid.generate(self.uniqueIdentifier) + + // Look for existing Accessory or create a new one + if (self.config.hostType == HostType.BRIDGE) { + if (self.config.isParent) { + // According to the HomeKit Accessory Protocol Specification the value + // of the fields Name, Manufacturer, Serial Number and Model must not + // change throughout the lifetime of an accessory. Because of that the + // accessory UUID will be generated based on that data to ensure that + // a new accessory will be created if any of those configuration values + // changes. + const accessoryUUID = uuid.generate( + 'A' + + self.uniqueIdentifier + + self.name + + self.config.manufacturer + + self.config.serialNo + + self.config.model ) - self.characteristicProperties = CharacteristicUtils.load( - self.service, - self.config + self.accessory = AccessoryUtils.getOrCreate( + self.hostNode.host, + { + name: self.name, + UUID: accessoryUUID, + manufacturer: self.config.manufacturer, + serialNo: self.config.serialNo, + model: self.config.model, + firmwareRev: self.config.firmwareRev, + hardwareRev: self.config.hardwareRev, + softwareRev: self.config.softwareRev + }, + subtypeUUID // subtype of the primary service for identification ) - ServiceUtils.configureAdaptiveLightning() + //Respond to identify + self.onIdentify = AccessoryUtils.onIdentify + self.accessory.on('identify', self.onIdentify) + } + } else { + // We are using Standalone Accessory mode so no need to create new Accessory as we have "host" already + log.debug('Binding Service accessory as Standalone Accessory') + self.accessory = self.hostNode.host + } - if (self.config.isParent) { - BridgeUtils.delayedPublish(self) - } + // Look for existing Service or create a new one + self.service = ServiceUtils.getOrCreate( + self.accessory, + { + name: self.name, + UUID: subtypeUUID, + serviceName: self.config.serviceName, + config: self.config + }, + self.parentService + ) + + self.characteristicProperties = CharacteristicUtils.load( + self.service, + self.config + ) + + ServiceUtils.configureAdaptiveLightning() + + if (self.config.isParent) { + BridgeUtils.delayedPublish(self) + } - // The pinCode should be shown to the user until interaction with iOS - // client starts - self.nodeStatusUtils.setStatus({ - fill: 'yellow', - shape: 'ring', - text: self.hostNode.config.pinCode, - }) + // The pinCode should be shown to the user until interaction with iOS + // client starts + self.nodeStatusUtils.setStatus({ + fill: 'yellow', + shape: 'ring', + text: self.hostNode.config.pinCode + }) - // Emit message when value changes - // service.on("characteristic-change", ServiceUtils.onCharacteristicChange); + // Emit message when value changes + // service.on("characteristic-change", ServiceUtils.onCharacteristicChange); - // Subscribe to set and get on characteristics for that service and get - // list of all supported - self.supported = CharacteristicUtils.subscribeAndGetSupported( - self.service - ) + // Subscribe to set and get on characteristics for that service and get + // list of all supported + self.supported = CharacteristicUtils.subscribeAndGetSupported(self.service) - // Respond to inputs - self.on('input', ServiceUtils.onInput) + // Respond to inputs + self.on('input', ServiceUtils.onInput) - self.on('close', ServiceUtils.onClose) - } + self.on('close', ServiceUtils.onClose) + } - return { - preInit, - init, - } + return { + preInit, + init + } } diff --git a/src/lib/HAPServiceNode2.ts b/src/lib/HAPServiceNode2.ts index a8a77629..e858a7d6 100644 --- a/src/lib/HAPServiceNode2.ts +++ b/src/lib/HAPServiceNode2.ts @@ -10,284 +10,280 @@ import HostType from './types/HostType' import { NodeStatusUtils } from './utils/NodeStatusUtils' module.exports = (RED: NodeAPI) => { - /** - * Config override when user created services in old NRCHKB version - */ - const nrchkbConfigCompatibilityOverride = function ( - this: HAPService2NodeType - ) { - const self = this - - const log = logger('NRCHKB', 'HAPServiceNode2', self.config.name, self) - - if (self.config.isParent === undefined) { - log.trace( - `nrchkbConfigCompatibilityOverride => self.config.isParent=${self.config.isParent} value changed to true` - ) - // Services created in pre linked services era where working in 1.2 but due to more typescript in 1.3+ it started to cause some errors - self.config.isParent = true - } - - if (self.config.hostType === undefined) { - // When moving from 1.2 to 1.3 hostType is not defined on homekit-service - log.trace( - `nrchkbConfigCompatibilityOverride => self.config.hostType=${self.config.hostType} value changed to HostType.BRIDGE` - ) - self.config.hostType = HostType.BRIDGE - } + /** + * Config override when user created services in old NRCHKB version + */ + const nrchkbConfigCompatibilityOverride = function ( + this: HAPService2NodeType + ) { + const self = this + + const log = logger('NRCHKB', 'HAPServiceNode2', self.config.name, self) + + if (self.config.isParent === undefined) { + log.trace( + `nrchkbConfigCompatibilityOverride => self.config.isParent=${self.config.isParent} value changed to true` + ) + // Services created in pre linked services era where working in 1.2 but due to more typescript in 1.3+ it started to cause some errors + self.config.isParent = true } - const preInit = function ( - this: HAPService2NodeType, - config: HAPService2ConfigType - ) { - const self = this - self.nodeStatusUtils = new NodeStatusUtils(self) + if (self.config.hostType === undefined) { + // When moving from 1.2 to 1.3 hostType is not defined on homekit-service + log.trace( + `nrchkbConfigCompatibilityOverride => self.config.hostType=${self.config.hostType} value changed to HostType.BRIDGE` + ) + self.config.hostType = HostType.BRIDGE + } + } - self.config = config - self.name = self.config.name + const preInit = function ( + this: HAPService2NodeType, + config: HAPService2ConfigType + ) { + const self = this + self.nodeStatusUtils = new NodeStatusUtils(self) - const log = logger('NRCHKB', 'HAPServiceNode2', self.config.name, self) + self.config = config + self.name = self.config.name - self.RED = RED - self.publishTimers = {} + const log = logger('NRCHKB', 'HAPServiceNode2', self.config.name, self) - nrchkbConfigCompatibilityOverride.call(self) - RED.nodes.createNode(self, self.config) + self.RED = RED + self.publishTimers = {} - const ServiceUtils = require('./utils/ServiceUtils2')(self) + nrchkbConfigCompatibilityOverride.call(self) + RED.nodes.createNode(self, self.config) - new Promise((resolve) => { - if (self.config.waitForSetupMsg) { - log.debug( - 'Waiting for Setup message. It should be of format {"payload":{"nrchkb":{"setup":{}}}}' - ) + const ServiceUtils = require('./utils/ServiceUtils2')(self) - self.setupDone = false + new Promise((resolve) => { + if (self.config.waitForSetupMsg) { + log.debug( + 'Waiting for Setup message. It should be of format {"payload":{"nrchkb":{"setup":{}}}}' + ) - self.nodeStatusUtils.setStatus({ - fill: 'blue', - shape: 'dot', - text: 'Waiting for Setup', - }) + self.setupDone = false - self.handleWaitForSetup = (msg: Record) => - ServiceUtils.handleWaitForSetup(self.config, msg, resolve) - self.on('input', self.handleWaitForSetup) - } else { - resolve(self.config) - } + self.nodeStatusUtils.setStatus({ + fill: 'blue', + shape: 'dot', + text: 'Waiting for Setup' }) - .then((newConfig) => { - init.call(self, newConfig) - }) - .catch((error: any) => { - log.error(`Error while starting Service due to ${error}`) - }) - } - const init = function ( - this: HAPService2NodeType, - config: HAPService2ConfigType - ) { - const self = this - self.config = config - - const log = logger('NRCHKB', 'HAPServiceNode2', self.config.name, self) - - const ServiceUtils = require('./utils/ServiceUtils2')(self) - - if (self.config.isParent) { - log.debug('Starting Parent Service') - configure.call(self) - self.configured = true - self.reachable = true - } else { - const serviceType = - config.serviceName === 'CameraControl' ? 'Camera' : 'Linked' - - ServiceUtils.waitForParent() - .then(() => { - log.debug(`Starting ${serviceType} Service`) - configure.call(self) - self.configured = true - }) - .catch((error: any) => { - log.error( - `Error while starting ${serviceType} Service due to ${error}` - ) - }) - } + self.handleWaitForSetup = (msg: Record) => + ServiceUtils.handleWaitForSetup(self.config, msg, resolve) + self.on('input', self.handleWaitForSetup) + } else { + resolve(self.config) + } + }) + .then((newConfig) => { + init.call(self, newConfig) + }) + .catch((error: any) => { + log.error(`Error while starting Service due to ${error}`) + }) + } + + const init = function ( + this: HAPService2NodeType, + config: HAPService2ConfigType + ) { + const self = this + self.config = config + + const log = logger('NRCHKB', 'HAPServiceNode2', self.config.name, self) + + const ServiceUtils = require('./utils/ServiceUtils2')(self) + + if (self.config.isParent) { + log.debug('Starting Parent Service') + configure.call(self) + self.configured = true + self.reachable = true + } else { + const serviceType = + config.serviceName === 'CameraControl' ? 'Camera' : 'Linked' + + ServiceUtils.waitForParent() + .then(() => { + log.debug(`Starting ${serviceType} Service`) + configure.call(self) + self.configured = true + }) + .catch((error: any) => { + log.error( + `Error while starting ${serviceType} Service due to ${error}` + ) + }) } + } - const configure = function (this: HAPService2NodeType) { - const self = this + const configure = function (this: HAPService2NodeType) { + const self = this - const log = logger('NRCHKB', 'HAPServiceNode2', self.config.name, self) + const log = logger('NRCHKB', 'HAPServiceNode2', self.config.name, self) - const Utils = require('./utils')(self) - const AccessoryUtils = Utils.AccessoryUtils - const BridgeUtils = Utils.BridgeUtils - const CharacteristicUtils = require('./utils/CharacteristicUtils2')( - self - ) - const ServiceUtils = require('./utils/ServiceUtils2')(self) - - let parentNode: HAPService2NodeType - - if (self.config.isParent) { - const hostId = - self.config.hostType == HostType.BRIDGE - ? self.config.bridge - : self.config.accessoryId - - self.hostNode = RED.nodes.getNode(hostId) as HAPHostNodeType - - if (!self.hostNode) { - const message = `Host node ${self.config.hostType == HostType.BRIDGE ? 'Bridge' : 'Standalone Accessory'} ${hostId} not found` - log.error(message, false) - throw new NRCHKBError(message) - } - - self.childNodes = [] - self.childNodes.push(self) - } else { - // Retrieve parent service node - parentNode = RED.nodes.getNode( - self.config.parentService - ) as HAPService2NodeType - - if (!parentNode) { - log.error('Parent Node not assigned', false) - throw new NRCHKBError('Parent Node not assigned') - } - - self.parentNode = parentNode - self.parentService = self.parentNode.service - - if (!self.parentService) { - log.error('Parent Service not assigned', false) - throw new NRCHKBError('Parent Service not assigned') - } - - self.hostNode = self.parentNode.hostNode - self.parentNode.childNodes?.push(self) - - self.accessory = self.parentNode.accessory - } - - // Service node properties - self.name = self.config.name - - // Find a unique identifier for the current service - if ( - self.hasOwnProperty('_flow') && - self.hasOwnProperty('_alias') && - self._flow?.hasOwnProperty('TYPE') && - self._flow.TYPE === 'subflow' - ) { - // For subflows, use the service node identifier from the subflow template - // plus the full path from the subflow node identifier to the subflow. - self.uniqueIdentifier = self._alias + '/' + self._flow.path - } else { - // For top level flows, use the node identifier - self.uniqueIdentifier = self.id - } - - // Generate UUID from unique identifier - const subtypeUUID = uuid.generate(self.uniqueIdentifier) - - // Look for existing Accessory or create a new one - if (self.config.hostType == HostType.BRIDGE) { - if (self.config.isParent) { - // According to the HomeKit Accessory Protocol Specification the value - // of the fields Name, Manufacturer, Serial Number and Model must not - // change throughout the lifetime of an accessory. Because of that the - // accessory UUID will be generated based on that data to ensure that - // a new accessory will be created if any of those configuration values - // changes. - const accessoryUUID = uuid.generate( - 'A' + - self.uniqueIdentifier + - self.name + - self.config.manufacturer + - self.config.serialNo + - self.config.model - ) - - self.accessory = AccessoryUtils.getOrCreate( - self.hostNode.host, - { - name: self.name, - UUID: accessoryUUID, - manufacturer: self.config.manufacturer, - serialNo: self.config.serialNo, - model: self.config.model, - firmwareRev: self.config.firmwareRev, - hardwareRev: self.config.hardwareRev, - softwareRev: self.config.softwareRev, - }, - subtypeUUID // subtype of the primary service for identification - ) - - //Respond to identify - self.onIdentify = AccessoryUtils.onIdentify - self.accessory.on('identify', self.onIdentify) - } - } else { - // We are using Standalone Accessory mode so no need to create new Accessory as we have "host" already - log.debug('Binding Service accessory as Standalone Accessory') - self.accessory = self.hostNode.host - } - - // Look for existing Service or create a new one - self.service = ServiceUtils.getOrCreate( - self.accessory, - { - name: self.name, - UUID: subtypeUUID, - serviceName: self.config.serviceName, - config: self.config, - }, - self.parentService - ) + const Utils = require('./utils')(self) + const AccessoryUtils = Utils.AccessoryUtils + const BridgeUtils = Utils.BridgeUtils + const CharacteristicUtils = require('./utils/CharacteristicUtils2')(self) + const ServiceUtils = require('./utils/ServiceUtils2')(self) - self.characteristicProperties = CharacteristicUtils.load( - self.service, - self.config - ) + let parentNode: HAPService2NodeType - ServiceUtils.configureAdaptiveLightning() + if (self.config.isParent) { + const hostId = + self.config.hostType == HostType.BRIDGE + ? self.config.bridge + : self.config.accessoryId - if (self.config.isParent) { - BridgeUtils.delayedPublish(self) - } + self.hostNode = RED.nodes.getNode(hostId) as HAPHostNodeType - // The pinCode should be shown to the user until interaction with iOS - // client starts - self.nodeStatusUtils.setStatus({ - fill: 'yellow', - shape: 'ring', - text: self.hostNode.config.pinCode, - }) + if (!self.hostNode) { + const message = `Host node ${self.config.hostType == HostType.BRIDGE ? 'Bridge' : 'Standalone Accessory'} ${hostId} not found` + log.error(message, false) + throw new NRCHKBError(message) + } + + self.childNodes = [] + self.childNodes.push(self) + } else { + // Retrieve parent service node + parentNode = RED.nodes.getNode( + self.config.parentService + ) as HAPService2NodeType + + if (!parentNode) { + log.error('Parent Node not assigned', false) + throw new NRCHKBError('Parent Node not assigned') + } - // Emit message when value changes - // service.on("characteristic-change", ServiceUtils.onCharacteristicChange); + self.parentNode = parentNode + self.parentService = self.parentNode.service - // Subscribe to set and get on characteristics for that service and get - // list of all supported - self.supported = CharacteristicUtils.subscribeAndGetSupported( - self.service + if (!self.parentService) { + log.error('Parent Service not assigned', false) + throw new NRCHKBError('Parent Service not assigned') + } + + self.hostNode = self.parentNode.hostNode + self.parentNode.childNodes?.push(self) + + self.accessory = self.parentNode.accessory + } + + // Service node properties + self.name = self.config.name + + // Find a unique identifier for the current service + if ( + self.hasOwnProperty('_flow') && + self.hasOwnProperty('_alias') && + self._flow?.hasOwnProperty('TYPE') && + self._flow.TYPE === 'subflow' + ) { + // For subflows, use the service node identifier from the subflow template + // plus the full path from the subflow node identifier to the subflow. + self.uniqueIdentifier = self._alias + '/' + self._flow.path + } else { + // For top level flows, use the node identifier + self.uniqueIdentifier = self.id + } + + // Generate UUID from unique identifier + const subtypeUUID = uuid.generate(self.uniqueIdentifier) + + // Look for existing Accessory or create a new one + if (self.config.hostType == HostType.BRIDGE) { + if (self.config.isParent) { + // According to the HomeKit Accessory Protocol Specification the value + // of the fields Name, Manufacturer, Serial Number and Model must not + // change throughout the lifetime of an accessory. Because of that the + // accessory UUID will be generated based on that data to ensure that + // a new accessory will be created if any of those configuration values + // changes. + const accessoryUUID = uuid.generate( + 'A' + + self.uniqueIdentifier + + self.name + + self.config.manufacturer + + self.config.serialNo + + self.config.model ) - // Respond to inputs - self.on('input', ServiceUtils.onInput) + self.accessory = AccessoryUtils.getOrCreate( + self.hostNode.host, + { + name: self.name, + UUID: accessoryUUID, + manufacturer: self.config.manufacturer, + serialNo: self.config.serialNo, + model: self.config.model, + firmwareRev: self.config.firmwareRev, + hardwareRev: self.config.hardwareRev, + softwareRev: self.config.softwareRev + }, + subtypeUUID // subtype of the primary service for identification + ) - self.on('close', ServiceUtils.onClose) + //Respond to identify + self.onIdentify = AccessoryUtils.onIdentify + self.accessory.on('identify', self.onIdentify) + } + } else { + // We are using Standalone Accessory mode so no need to create new Accessory as we have "host" already + log.debug('Binding Service accessory as Standalone Accessory') + self.accessory = self.hostNode.host } - return { - preInit, - init, + // Look for existing Service or create a new one + self.service = ServiceUtils.getOrCreate( + self.accessory, + { + name: self.name, + UUID: subtypeUUID, + serviceName: self.config.serviceName, + config: self.config + }, + self.parentService + ) + + self.characteristicProperties = CharacteristicUtils.load( + self.service, + self.config + ) + + ServiceUtils.configureAdaptiveLightning() + + if (self.config.isParent) { + BridgeUtils.delayedPublish(self) } + + // The pinCode should be shown to the user until interaction with iOS + // client starts + self.nodeStatusUtils.setStatus({ + fill: 'yellow', + shape: 'ring', + text: self.hostNode.config.pinCode + }) + + // Emit message when value changes + // service.on("characteristic-change", ServiceUtils.onCharacteristicChange); + + // Subscribe to set and get on characteristics for that service and get + // list of all supported + self.supported = CharacteristicUtils.subscribeAndGetSupported(self.service) + + // Respond to inputs + self.on('input', ServiceUtils.onInput) + + self.on('close', ServiceUtils.onClose) + } + + return { + preInit, + init + } } diff --git a/src/lib/Storage.ts b/src/lib/Storage.ts index cb538254..2802330d 100644 --- a/src/lib/Storage.ts +++ b/src/lib/Storage.ts @@ -1,15 +1,15 @@ import { - CharacteristicEventTypes, - SerializedAccessory, - SerializedService, + CharacteristicEventTypes, + SerializedAccessory, + SerializedService } from '@homebridge/hap-nodejs' import { logger } from '@nrchkb/logger' import storage, { InitOptions } from 'node-persist' import path from 'path' import { - v4 as uuidv4, - validate as uuidValidate, - version as uuidVersion, + v4 as uuidv4, + validate as uuidValidate, + version as uuidVersion } from 'uuid' import NRCHKBError from './NRCHKBError' @@ -17,137 +17,133 @@ import { SerializedHostType } from './types/storage/SerializedHostType' import { StorageType } from './types/storage/StorageType' type EventCallback = { - event: CharacteristicEventTypes - callback: (value?: any) => void + event: CharacteristicEventTypes + callback: (value?: any) => void } export class Storage { - private static customStoragePath: string - private static storageInitialized = false + private static customStoragePath: string + private static storageInitialized = false - private static memoryStorage: { [key: string]: any } = {} + private static memoryStorage: { [key: string]: any } = {} - private static log = logger('NRCHKB', 'Storage') + private static log = logger('NRCHKB', 'Storage') - static storagePath(): string { - if (!Storage.storageInitialized) { - throw new NRCHKBError('Storage path was not initialized!') - } - - return Storage.customStoragePath - } - - static init(...storagePathSegments: string[]): Promise { - Storage.customStoragePath = path.resolve(...storagePathSegments) - Storage.storageInitialized = true - - Storage.log.trace('Initializing') - - return storage.init({ dir: Storage.storagePath() }) - } - - static save( - type: StorageType, - key: string | undefined, - value: unknown - ): Promise { - const itemName = key ? `${type}-${key}` : type - Storage.log.trace(`Saving ${itemName}:${value}`) - return storage.set(itemName, value) - } - - static saveCallback(eventCallback: EventCallback, ttl = 10000) { - const callbackID = uuidv4() - Storage.memoryStorage[callbackID] = eventCallback - - setTimeout(() => { - // HAP-NodeJS will complain about slow running get handlers after 3 seconds - // and terminate the request after 10 seconds. - if (callbackID in Storage.memoryStorage) { - Storage.log.debug(`Callback ${callbackID} timeout`) - eventCallback.callback() - delete Storage.memoryStorage[callbackID] - } - }, ttl) - - return callbackID - } - - static saveCustomCharacteristics( - value: unknown - ): Promise { - return Storage.save( - StorageType.CUSTOM_CHARACTERISTICS, - undefined, - value - ) - } - - static saveService( - key: string, - value: unknown - ): Promise { - return Storage.save(StorageType.SERVICE, key, value) + static storagePath(): string { + if (!Storage.storageInitialized) { + throw new NRCHKBError('Storage path was not initialized!') } - static saveAccessory( - key: string, - value: unknown - ): Promise { - return Storage.save(StorageType.ACCESSORY, key, value) + return Storage.customStoragePath + } + + static init(...storagePathSegments: string[]): Promise { + Storage.customStoragePath = path.resolve(...storagePathSegments) + Storage.storageInitialized = true + + Storage.log.trace('Initializing') + + return storage.init({ dir: Storage.storagePath() }) + } + + static save( + type: StorageType, + key: string | undefined, + value: unknown + ): Promise { + const itemName = key ? `${type}-${key}` : type + Storage.log.trace(`Saving ${itemName}:${value}`) + return storage.set(itemName, value) + } + + static saveCallback(eventCallback: EventCallback, ttl = 10000) { + const callbackID = uuidv4() + Storage.memoryStorage[callbackID] = eventCallback + + setTimeout(() => { + // HAP-NodeJS will complain about slow running get handlers after 3 seconds + // and terminate the request after 10 seconds. + if (callbackID in Storage.memoryStorage) { + Storage.log.debug(`Callback ${callbackID} timeout`) + eventCallback.callback() + delete Storage.memoryStorage[callbackID] + } + }, ttl) + + return callbackID + } + + static saveCustomCharacteristics( + value: unknown + ): Promise { + return Storage.save(StorageType.CUSTOM_CHARACTERISTICS, undefined, value) + } + + static saveService( + key: string, + value: unknown + ): Promise { + return Storage.save(StorageType.SERVICE, key, value) + } + + static saveAccessory( + key: string, + value: unknown + ): Promise { + return Storage.save(StorageType.ACCESSORY, key, value) + } + + static saveHost( + key: string, + serializedHost: SerializedHostType + ): Promise { + return Storage.save(StorageType.HOST, key, serializedHost) + } + + static load(type: StorageType, key?: string): Promise { + const itemName = key ? `${type}-${key}` : type + Storage.log.trace(`Loading ${itemName}`) + return storage.get(itemName) + } + + static loadCallback(key: string): EventCallback | undefined { + if (key in Storage.memoryStorage) { + Storage.log.trace(`Returning callback ${key}`) + const value = Storage.memoryStorage[key] + delete Storage.memoryStorage[key] + return value } - static saveHost( - key: string, - serializedHost: SerializedHostType - ): Promise { - return Storage.save(StorageType.HOST, key, serializedHost) - } - - static load(type: StorageType, key?: string): Promise { - const itemName = key ? `${type}-${key}` : type - Storage.log.trace(`Loading ${itemName}`) - return storage.get(itemName) - } - - static loadCallback(key: string): EventCallback | undefined { - if (key in Storage.memoryStorage) { - Storage.log.trace(`Returning callback ${key}`) - const value = Storage.memoryStorage[key] - delete Storage.memoryStorage[key] - return value + return undefined + } + + static loadCustomCharacteristics(): Promise { + return Storage.load(StorageType.CUSTOM_CHARACTERISTICS) + } + + static loadService(key: string): Promise { + return new Promise((resolve, reject) => { + Storage.load(StorageType.SERVICE, key).then((value) => { + if (value === undefined) { + reject('Service data not exists') + } else if ('primaryService' in value) { + resolve(value) + } else { + reject('Service data corrupted') } + }) + }) + } - return undefined - } + static loadAccessory(key: string): Promise { + return Storage.load(StorageType.ACCESSORY, key) + } - static loadCustomCharacteristics(): Promise { - return Storage.load(StorageType.CUSTOM_CHARACTERISTICS) - } + static loadHost(key: string): Promise { + return Storage.load(StorageType.HOST, key) + } - static loadService(key: string): Promise { - return new Promise((resolve, reject) => { - Storage.load(StorageType.SERVICE, key).then((value) => { - if (value === undefined) { - reject('Service data not exists') - } else if ('primaryService' in value) { - resolve(value) - } else { - reject('Service data corrupted') - } - }) - }) - } - - static loadAccessory(key: string): Promise { - return Storage.load(StorageType.ACCESSORY, key) - } - - static loadHost(key: string): Promise { - return Storage.load(StorageType.HOST, key) - } - - static uuid4Validate(uuid: string) { - return uuidValidate(uuid) && uuidVersion(uuid) === 4 - } + static uuid4Validate(uuid: string) { + return uuidValidate(uuid) && uuidVersion(uuid) === 4 + } } diff --git a/src/lib/api.ts b/src/lib/api.ts index 8cac507f..9e83ef96 100644 --- a/src/lib/api.ts +++ b/src/lib/api.ts @@ -1,8 +1,8 @@ import { - Characteristic, - Perms, - SerializedService, - Service, + Characteristic, + Perms, + SerializedService, + Service } from '@homebridge/hap-nodejs' import { logger } from '@nrchkb/logger' import express from 'express' @@ -18,408 +18,387 @@ import HAPServiceNodeType from './types/HAPServiceNodeType' const version = require('../../package.json').version.trim() module.exports = function (RED: NodeAPI) { - const log = logger('NRCHKB', 'API') + const log = logger('NRCHKB', 'API') - // Service API - const _initServiceAPI = () => { - log.debug('Initialize Service API') + // Service API + const _initServiceAPI = () => { + log.debug('Initialize Service API') - type ServiceData = { - [key: string]: Partial & { - nrchkbDisabledText?: string - } - } - - // Service API response data - const serviceData: ServiceData = { - BatteryService: { - nrchkbDisabledText: - 'BatteryService (deprecated, replaced by Battery)', - }, - BridgeConfiguration: { - nrchkbDisabledText: 'BridgeConfiguration (deprecated, unused)', - }, - BridgingState: { - nrchkbDisabledText: 'BridgingState (deprecated, unused)', - }, - CameraControl: { - //TODO: hmm, what is the replacement? - nrchkbDisabledText: 'CameraControl (deprecated, replaced by)', - }, - CameraEventRecordingManagement: { - nrchkbDisabledText: - 'CameraEventRecordingManagement (deprecated, replaced by CameraRecordingManagement)', - }, - Relay: { - nrchkbDisabledText: - 'Relay (deprecated, replaced by CloudRelay)', - }, - Slat: { - nrchkbDisabledText: 'Slat (deprecated, replaced by Slats)', - }, - TimeInformation: { - nrchkbDisabledText: 'TimeInformation (deprecated, unused)', - }, - TunneledBTLEAccessoryService: { - nrchkbDisabledText: - 'TunneledBTLEAccessoryService (deprecated, replaced by Tunnel)', - }, - } - - Object.values(Service) - .filter((service) => service.prototype instanceof Service) - .map((service) => { - const newService = Service.serialize(new service()) - newService.displayName = service.name - return newService - }) - .forEach((serialized) => { - serviceData[serialized.displayName] = { - ...serviceData?.[serialized.displayName], - ...serialized, - } - }) - - // Retrieve Service Types - RED.httpAdmin.get( - '/nrchkb/service/types', - RED.auth.needsPermission('nrchkb.read'), - (_req: express.Request, res: express.Response) => { - res.setHeader('Content-Type', 'application/json') - res.json(serviceData) - } - ) + type ServiceData = { + [key: string]: Partial & { + nrchkbDisabledText?: string + } } - const stringifyVersion = (version: string) => { - const releaseVersionRegex = /(\d+)\.(\d+)\.(\d+)/ - const devVersionRegex = /(\d+)\.(\d+)\.(\d+)-dev\.(\d+)/ - - const releaseVersionFound = releaseVersionRegex.test(version) - const devVersionFound = devVersionRegex.test(version) - - let xyzVersion = '0.0.0' - - if (devVersionFound) { - try { - const match = devVersionRegex.exec(version) + // Service API response data + const serviceData: ServiceData = { + BatteryService: { + nrchkbDisabledText: 'BatteryService (deprecated, replaced by Battery)' + }, + BridgeConfiguration: { + nrchkbDisabledText: 'BridgeConfiguration (deprecated, unused)' + }, + BridgingState: { + nrchkbDisabledText: 'BridgingState (deprecated, unused)' + }, + CameraControl: { + //TODO: hmm, what is the replacement? + nrchkbDisabledText: 'CameraControl (deprecated, replaced by)' + }, + CameraEventRecordingManagement: { + nrchkbDisabledText: + 'CameraEventRecordingManagement (deprecated, replaced by CameraRecordingManagement)' + }, + Relay: { + nrchkbDisabledText: 'Relay (deprecated, replaced by CloudRelay)' + }, + Slat: { + nrchkbDisabledText: 'Slat (deprecated, replaced by Slats)' + }, + TimeInformation: { + nrchkbDisabledText: 'TimeInformation (deprecated, unused)' + }, + TunneledBTLEAccessoryService: { + nrchkbDisabledText: + 'TunneledBTLEAccessoryService (deprecated, replaced by Tunnel)' + } + } - if (match) { - xyzVersion = `0.${match[1]}${match[2]}${match[3]}.${match[4]}` - } else { - log.debug('Could not match dev version') - } - } catch (e) { - console.error(e) - } - } else if (releaseVersionFound) { - try { - const match = releaseVersionRegex.exec(version) - - if (match) { - xyzVersion = match[0] - } else { - log.debug('Could not match release version') - } - } catch (e) { - console.error(e) - } + Object.values(Service) + .filter((service) => service.prototype instanceof Service) + .map((service) => { + const newService = Service.serialize(new service()) + newService.displayName = service.name + return newService + }) + .forEach((serialized) => { + serviceData[serialized.displayName] = { + ...serviceData?.[serialized.displayName], + ...serialized + } + }) + + // Retrieve Service Types + RED.httpAdmin.get( + '/nrchkb/service/types', + RED.auth.needsPermission('nrchkb.read'), + (_req: express.Request, res: express.Response) => { + res.setHeader('Content-Type', 'application/json') + res.json(serviceData) + } + ) + } + + const stringifyVersion = (version: string) => { + const releaseVersionRegex = /(\d+)\.(\d+)\.(\d+)/ + const devVersionRegex = /(\d+)\.(\d+)\.(\d+)-dev\.(\d+)/ + + const releaseVersionFound = releaseVersionRegex.test(version) + const devVersionFound = devVersionRegex.test(version) + + let xyzVersion = '0.0.0' + + if (devVersionFound) { + try { + const match = devVersionRegex.exec(version) + + if (match) { + xyzVersion = `0.${match[1]}${match[2]}${match[3]}.${match[4]}` } else { - log.debug('Bad version format') - xyzVersion = '0.0.0' + log.debug('Could not match dev version') } - - return xyzVersion + } catch (e) { + console.error(e) + } + } else if (releaseVersionFound) { + try { + const match = releaseVersionRegex.exec(version) + + if (match) { + xyzVersion = match[0] + } else { + log.debug('Could not match release version') + } + } catch (e) { + console.error(e) + } + } else { + log.debug('Bad version format') + xyzVersion = '0.0.0' } - // NRCHKB Info API - const _initNRCHKBInfoAPI = () => { - log.debug('Initialize NRCHKB Info API') + return xyzVersion + } - log.debug(`Running version: ${version}`) + // NRCHKB Info API + const _initNRCHKBInfoAPI = () => { + log.debug('Initialize NRCHKB Info API') - const xyzVersion = stringifyVersion(version) + log.debug(`Running version: ${version}`) - log.debug(`Evaluated as: ${xyzVersion}`) + const xyzVersion = stringifyVersion(version) - const experimental = process.env.NRCHKB_EXPERIMENTAL === 'true' + log.debug(`Evaluated as: ${xyzVersion}`) - log.debug(`Running experimental: ${experimental}`) + const experimental = process.env.NRCHKB_EXPERIMENTAL === 'true' - // Retrieve NRCHKB version - RED.httpAdmin.get( - '/nrchkb/info', - RED.auth.needsPermission('nrchkb.read'), - (_req: express.Request, res: express.Response) => { - res.setHeader('Content-Type', 'application/json') - res.json({ - version: xyzVersion, - experimental, - }) - } - ) - } + log.debug(`Running experimental: ${experimental}`) - // NRCHKB Custom Characteristics API - const _initNRCHKBCustomCharacteristicsAPI = async () => { - const getCustomCharacteristics = async () => { - try { - const value = await Storage.loadCustomCharacteristics() - - log.trace('loadCustomCharacteristics()') - log.trace(value) - - if (Array.isArray(value)) { - return value - } else { - log.debug( - 'customCharacteristics is not Array, returning empty value' - ) - return EveCharacteristics - } - } catch (error) { - log.error( - `Failed to get customCharacteristics in nrchkbStorage due to ${error}` - ) - return EveCharacteristics - } - } - - const characteristicNameToKey = (name: string) => { - return name.replace(' ', '') - } + // Retrieve NRCHKB version + RED.httpAdmin.get( + '/nrchkb/info', + RED.auth.needsPermission('nrchkb.read'), + (_req: express.Request, res: express.Response) => { + res.setHeader('Content-Type', 'application/json') + res.json({ + version: xyzVersion, + experimental + }) + } + ) + } - const toNumber = (value: any, optional = undefined) => { - const num = Number(value) - if (isNaN(num)) { - return optional - } else return num - } - - const refreshCustomCharacteristics = ( - customCharacteristics: CustomCharacteristicType[] - ) => { - log.debug('Refreshing Custom Characteristics') - - const customCharacteristicKeys: string[] = [] - - customCharacteristics.forEach(({ name, UUID, ...props }) => { - if (!!UUID && !!name) { - const key = characteristicNameToKey(name) - - log.debug( - `Adding Custom Characteristic ${name} using key ${key}` - ) - - if (customCharacteristicKeys.includes(key)) { - log.error( - `Cannot add ${name}. Another Custom Characteristic already defined using key ${key}` - ) - return - } - - const validatedProps = props - if (validatedProps.validValues?.length === 0) { - validatedProps.validValues = undefined - } - if ( - !validatedProps.validValueRanges?.[0] || - !validatedProps.validValueRanges?.[1] - ) { - validatedProps.validValueRanges = undefined - } - if (validatedProps.adminOnlyAccess?.length === 0) { - validatedProps.adminOnlyAccess = undefined - } - if (validatedProps.minValue) { - validatedProps.minValue = toNumber( - validatedProps.minValue - ) - } - if (validatedProps.maxValue) { - validatedProps.maxValue = toNumber( - validatedProps.maxValue - ) - } - if (validatedProps.minStep) { - validatedProps.minStep = toNumber( - validatedProps.minStep - ) - } - - class CustomCharacteristic extends Characteristic { - static readonly UUID: string = UUID! - - constructor() { - super(name!, CustomCharacteristic.UUID, { - ...validatedProps, - perms: validatedProps.perms ?? [ - Perms.PAIRED_READ, - Perms.PAIRED_WRITE, - Perms.NOTIFY, - ], - }) - - this.value = this.getDefaultValue() - } - } - - Object.defineProperty(CustomCharacteristic, 'name', { - value: key, - configurable: true, - }) - Object.defineProperty(Characteristic, key, { - value: CustomCharacteristic, - configurable: true, - }) - - customCharacteristicKeys.push(key) - } - }) + // NRCHKB Custom Characteristics API + const _initNRCHKBCustomCharacteristicsAPI = async () => { + const getCustomCharacteristics = async () => { + try { + const value = await Storage.loadCustomCharacteristics() - new Promise((resolve) => { - const isRedInitialized = () => { - try { - RED.nodes.eachNode(() => { - return - }) - resolve(true) - } catch (_) { - log.debug('Waiting for RED to be initialized') - setTimeout(isRedInitialized, 1000) - } - } + log.trace('loadCustomCharacteristics()') + log.trace(value) - isRedInitialized() - }).then(() => { - RED.nodes.eachNode((node) => { - if ( - node.type === 'homekit-service' || - node.type === 'homekit-service2' - ) { - const serviceNodeConfig = node as HAPServiceConfigType - - const serviceNode = RED.nodes.getNode( - serviceNodeConfig.id - ) as HAPServiceNodeType - - if ( - serviceNode && - serviceNode.characteristicProperties && - serviceNode.service - ) { - for (const key in serviceNode.characteristicProperties) { - if (customCharacteristicKeys.includes(key)) { - const characteristic = serviceNode.service - // @ts-ignore - .getCharacteristic(Characteristic[key]) - .setProps( - serviceNode - .characteristicProperties[key] - ) - serviceNode.supported.push(key) - - characteristic.on( - 'get', - serviceNode.onCharacteristicGet - ) - characteristic.on( - 'set', - serviceNode.onCharacteristicSet - ) - characteristic.on( - 'change', - serviceNode.onCharacteristicChange - ) - } - } - } - } - }) - }) + if (Array.isArray(value)) { + return value + } else { + log.debug('customCharacteristics is not Array, returning empty value') + return EveCharacteristics } - - log.debug('Initialize NRCHKBCustomCharacteristicsAPI') - - getCustomCharacteristics().then((value) => - refreshCustomCharacteristics(value) + } catch (error) { + log.error( + `Failed to get customCharacteristics in nrchkbStorage due to ${error}` ) + return EveCharacteristics + } + } - // Retrieve NRCHKB version - RED.httpAdmin.get( - '/nrchkb/config', - RED.auth.needsPermission('nrchkb.read'), - async (_req: express.Request, res: express.Response) => { - res.setHeader('Content-Type', 'application/json') - res.json({ - customCharacteristics: await getCustomCharacteristics(), - }) - } - ) + const characteristicNameToKey = (name: string) => { + return name.replace(' ', '') + } - // Change NRCHKB version - RED.httpAdmin.post( - '/nrchkb/config', - RED.auth.needsPermission('nrchkb.write'), - async (req: express.Request, res: express.Response) => { - const customCharacteristics: CustomCharacteristicType[] = - req.body.customCharacteristics || EveCharacteristics - - Storage.saveCustomCharacteristics(customCharacteristics) - .then(() => { - res.sendStatus(200) - refreshCustomCharacteristics(customCharacteristics) - }) - .catch((error) => { - log.error(error) - res.sendStatus(500) - }) - } - ) + const toNumber = (value: any, optional = undefined) => { + const num = Number(value) + if (isNaN(num)) { + return optional + } else return num } - // Accessory API - const _initAccessoryAPI = function () { - log.debug('Initialize Accessory API') - - // Accessory Categories API response data - const accessoryCategoriesData: { - [key: number]: string - } = {} - - // Prepare Accessory data once - Object.keys(HapCategories) - .sort() - .filter((x) => parseInt(x) >= 0) - .forEach((key) => { - const keyNumber = key as unknown as number - accessoryCategoriesData[keyNumber] = HapCategories[keyNumber] + const refreshCustomCharacteristics = ( + customCharacteristics: CustomCharacteristicType[] + ) => { + log.debug('Refreshing Custom Characteristics') + + const customCharacteristicKeys: string[] = [] + + customCharacteristics.forEach(({ name, UUID, ...props }) => { + if (!!UUID && !!name) { + const key = characteristicNameToKey(name) + + log.debug(`Adding Custom Characteristic ${name} using key ${key}`) + + if (customCharacteristicKeys.includes(key)) { + log.error( + `Cannot add ${name}. Another Custom Characteristic already defined using key ${key}` + ) + return + } + + const validatedProps = props + if (validatedProps.validValues?.length === 0) { + validatedProps.validValues = undefined + } + if ( + !validatedProps.validValueRanges?.[0] || + !validatedProps.validValueRanges?.[1] + ) { + validatedProps.validValueRanges = undefined + } + if (validatedProps.adminOnlyAccess?.length === 0) { + validatedProps.adminOnlyAccess = undefined + } + if (validatedProps.minValue) { + validatedProps.minValue = toNumber(validatedProps.minValue) + } + if (validatedProps.maxValue) { + validatedProps.maxValue = toNumber(validatedProps.maxValue) + } + if (validatedProps.minStep) { + validatedProps.minStep = toNumber(validatedProps.minStep) + } + + class CustomCharacteristic extends Characteristic { + static readonly UUID: string = UUID! + + constructor() { + super(name!, CustomCharacteristic.UUID, { + ...validatedProps, + perms: validatedProps.perms ?? [ + Perms.PAIRED_READ, + Perms.PAIRED_WRITE, + Perms.NOTIFY + ] + }) + + this.value = this.getDefaultValue() + } + } + + Object.defineProperty(CustomCharacteristic, 'name', { + value: key, + configurable: true + }) + Object.defineProperty(Characteristic, key, { + value: CustomCharacteristic, + configurable: true + }) + + customCharacteristicKeys.push(key) + } + }) + + new Promise((resolve) => { + const isRedInitialized = () => { + try { + RED.nodes.eachNode(() => { + return }) + resolve(true) + } catch (_) { + log.debug('Waiting for RED to be initialized') + setTimeout(isRedInitialized, 1000) + } + } - // Retrieve Accessory Types - RED.httpAdmin.get( - '/nrchkb/accessory/categories', - RED.auth.needsPermission('nrchkb.read'), - (_req: express.Request, res: express.Response) => { - res.setHeader('Content-Type', 'application/json') - res.json(accessoryCategoriesData) + isRedInitialized() + }).then(() => { + RED.nodes.eachNode((node) => { + if ( + node.type === 'homekit-service' || + node.type === 'homekit-service2' + ) { + const serviceNodeConfig = node as HAPServiceConfigType + + const serviceNode = RED.nodes.getNode( + serviceNodeConfig.id + ) as HAPServiceNodeType + + if ( + serviceNode && + serviceNode.characteristicProperties && + serviceNode.service + ) { + for (const key in serviceNode.characteristicProperties) { + if (customCharacteristicKeys.includes(key)) { + const characteristic = serviceNode.service + // @ts-ignore + .getCharacteristic(Characteristic[key]) + .setProps(serviceNode.characteristicProperties[key]) + serviceNode.supported.push(key) + + characteristic.on('get', serviceNode.onCharacteristicGet) + characteristic.on('set', serviceNode.onCharacteristicSet) + characteristic.on( + 'change', + serviceNode.onCharacteristicChange + ) + } + } } - ) + } + }) + }) } - const init = () => { - _initServiceAPI() - _initNRCHKBInfoAPI() - _initAccessoryAPI() - - // Experimental feature - if (process.env.NRCHKB_EXPERIMENTAL === 'true') { - _initNRCHKBCustomCharacteristicsAPI().then() - } + log.debug('Initialize NRCHKBCustomCharacteristicsAPI') + + getCustomCharacteristics().then((value) => + refreshCustomCharacteristics(value) + ) + + // Retrieve NRCHKB version + RED.httpAdmin.get( + '/nrchkb/config', + RED.auth.needsPermission('nrchkb.read'), + async (_req: express.Request, res: express.Response) => { + res.setHeader('Content-Type', 'application/json') + res.json({ + customCharacteristics: await getCustomCharacteristics() + }) + } + ) + + // Change NRCHKB version + RED.httpAdmin.post( + '/nrchkb/config', + RED.auth.needsPermission('nrchkb.write'), + async (req: express.Request, res: express.Response) => { + const customCharacteristics: CustomCharacteristicType[] = + req.body.customCharacteristics || EveCharacteristics + + Storage.saveCustomCharacteristics(customCharacteristics) + .then(() => { + res.sendStatus(200) + refreshCustomCharacteristics(customCharacteristics) + }) + .catch((error) => { + log.error(error) + res.sendStatus(500) + }) + } + ) + } + + // Accessory API + const _initAccessoryAPI = function () { + log.debug('Initialize Accessory API') + + // Accessory Categories API response data + const accessoryCategoriesData: { + [key: number]: string + } = {} + + // Prepare Accessory data once + Object.keys(HapCategories) + .sort() + .filter((x) => parseInt(x) >= 0) + .forEach((key) => { + const keyNumber = key as unknown as number + accessoryCategoriesData[keyNumber] = HapCategories[keyNumber] + }) + + // Retrieve Accessory Types + RED.httpAdmin.get( + '/nrchkb/accessory/categories', + RED.auth.needsPermission('nrchkb.read'), + (_req: express.Request, res: express.Response) => { + res.setHeader('Content-Type', 'application/json') + res.json(accessoryCategoriesData) + } + ) + } + + const init = () => { + _initServiceAPI() + _initNRCHKBInfoAPI() + _initAccessoryAPI() + + // Experimental feature + if (process.env.NRCHKB_EXPERIMENTAL === 'true') { + _initNRCHKBCustomCharacteristicsAPI().then() } + } - return { - init, - stringifyVersion, - } + return { + init, + stringifyVersion + } } diff --git a/src/lib/hap/HAPCharacteristic.ts b/src/lib/hap/HAPCharacteristic.ts index 02bd0101..4101a734 100644 --- a/src/lib/hap/HAPCharacteristic.ts +++ b/src/lib/hap/HAPCharacteristic.ts @@ -1,17 +1,17 @@ import { Characteristic } from '@homebridge/hap-nodejs' import { - EveS2R1, - EveS2R2, - EveS2W1, - EveS2W2, + EveS2R1, + EveS2R2, + EveS2W1, + EveS2W2 } from './eve-app/EveCharacteristics' class HAPCharacteristic extends Characteristic { - static EveS2R1: typeof EveS2R1 - static EveS2R2: typeof EveS2R2 - static EveS2W1: typeof EveS2W1 - static EveS2W2: typeof EveS2W2 + static EveS2R1: typeof EveS2R1 + static EveS2R2: typeof EveS2R2 + static EveS2W1: typeof EveS2W1 + static EveS2W2: typeof EveS2W2 } export default HAPCharacteristic diff --git a/src/lib/hap/HAPService.ts b/src/lib/hap/HAPService.ts index 3500384b..7c84ddad 100644 --- a/src/lib/hap/HAPService.ts +++ b/src/lib/hap/HAPService.ts @@ -3,7 +3,7 @@ import { Service } from '@homebridge/hap-nodejs' import { EveHistoryData } from './eve-app/EveServices' class HAPService extends Service { - static EveHistoryData: typeof EveHistoryData + static EveHistoryData: typeof EveHistoryData } export default HAPService diff --git a/src/lib/hap/eve-app/EveCharacteristics.ts b/src/lib/hap/eve-app/EveCharacteristics.ts index ceaf94a7..acabbe97 100644 --- a/src/lib/hap/eve-app/EveCharacteristics.ts +++ b/src/lib/hap/eve-app/EveCharacteristics.ts @@ -11,90 +11,89 @@ import HAPCharacteristic from '../HAPCharacteristic' */ const EveCharacteristics: CustomCharacteristicType[] = [ - { - UUID: 'E863F10A-079E-48FF-8F27-9C2605A29F52', - name: 'Eve-Volt', - format: Formats.FLOAT, - perms: [Perms.PAIRED_READ], - description: 'Volt (V) value. Used by Eve.app.', - }, - { - UUID: 'E863F126-079E-48FF-8F27-9C2605A29F52', - name: 'Eve-Ampere', - format: Formats.FLOAT, - perms: [Perms.PAIRED_READ], - description: 'Ampere (A) value. Used by Eve.app.', - }, - { - UUID: 'E863F10D-079E-48FF-8F27-9C2605A29F52', - name: 'Eve-Watt', - format: Formats.FLOAT, - perms: [Perms.PAIRED_READ], - description: - 'Watt (W) value. Used by Eve.app, reported as "Consumption".', - }, - { - UUID: 'E863F10C-079E-48FF-8F27-9C2605A29F52', - name: 'Eve-Kilowatt-hour', - format: Formats.FLOAT, - perms: [Perms.PAIRED_READ], - description: - 'Kilowatt-hour (kWh) value. Used by Eve.app, reported as Total Consumption.', - }, - { - UUID: 'E863F110-079E-48FF-8F27-9C2605A29F52', - name: 'Eve-Volt-Ampere', - format: Formats.UINT16, - perms: [Perms.PAIRED_READ], - description: 'Volt-Ampere (VA) value. Used by Eve.app.', - }, + { + UUID: 'E863F10A-079E-48FF-8F27-9C2605A29F52', + name: 'Eve-Volt', + format: Formats.FLOAT, + perms: [Perms.PAIRED_READ], + description: 'Volt (V) value. Used by Eve.app.' + }, + { + UUID: 'E863F126-079E-48FF-8F27-9C2605A29F52', + name: 'Eve-Ampere', + format: Formats.FLOAT, + perms: [Perms.PAIRED_READ], + description: 'Ampere (A) value. Used by Eve.app.' + }, + { + UUID: 'E863F10D-079E-48FF-8F27-9C2605A29F52', + name: 'Eve-Watt', + format: Formats.FLOAT, + perms: [Perms.PAIRED_READ], + description: 'Watt (W) value. Used by Eve.app, reported as "Consumption".' + }, + { + UUID: 'E863F10C-079E-48FF-8F27-9C2605A29F52', + name: 'Eve-Kilowatt-hour', + format: Formats.FLOAT, + perms: [Perms.PAIRED_READ], + description: + 'Kilowatt-hour (kWh) value. Used by Eve.app, reported as Total Consumption.' + }, + { + UUID: 'E863F110-079E-48FF-8F27-9C2605A29F52', + name: 'Eve-Volt-Ampere', + format: Formats.UINT16, + perms: [Perms.PAIRED_READ], + description: 'Volt-Ampere (VA) value. Used by Eve.app.' + } ] export class EveS2R1 extends HAPCharacteristic { - public static readonly UUID: string = 'E863F116-079E-48FF-8F27-9C2605A29F52' + public static readonly UUID: string = 'E863F116-079E-48FF-8F27-9C2605A29F52' - constructor() { - super('Eve-S2R1', EveS2R1.UUID, { - format: Formats.DATA, - perms: [Perms.PAIRED_READ, Perms.NOTIFY, Perms.HIDDEN], - }) - } + constructor() { + super('Eve-S2R1', EveS2R1.UUID, { + format: Formats.DATA, + perms: [Perms.PAIRED_READ, Perms.NOTIFY, Perms.HIDDEN] + }) + } } HAPCharacteristic.EveS2R1 = EveS2R1 export class EveS2R2 extends HAPCharacteristic { - public static readonly UUID: string = 'E863F117-079E-48FF-8F27-9C2605A29F52' + public static readonly UUID: string = 'E863F117-079E-48FF-8F27-9C2605A29F52' - constructor() { - super('Eve-S2R2', EveS2R2.UUID, { - format: Formats.DATA, - perms: [Perms.PAIRED_READ, Perms.NOTIFY, Perms.HIDDEN], - }) - } + constructor() { + super('Eve-S2R2', EveS2R2.UUID, { + format: Formats.DATA, + perms: [Perms.PAIRED_READ, Perms.NOTIFY, Perms.HIDDEN] + }) + } } HAPCharacteristic.EveS2R2 = EveS2R2 export class EveS2W1 extends HAPCharacteristic { - public static readonly UUID: string = 'E863F11C-079E-48FF-8F27-9C2605A29F52' + public static readonly UUID: string = 'E863F11C-079E-48FF-8F27-9C2605A29F52' - constructor() { - super('Eve-S2W1', EveS2W1.UUID, { - format: Formats.DATA, - perms: [Perms.PAIRED_WRITE, Perms.HIDDEN], - }) - } + constructor() { + super('Eve-S2W1', EveS2W1.UUID, { + format: Formats.DATA, + perms: [Perms.PAIRED_WRITE, Perms.HIDDEN] + }) + } } HAPCharacteristic.EveS2W1 = EveS2W1 export class EveS2W2 extends HAPCharacteristic { - public static readonly UUID: string = 'E863F121-079E-48FF-8F27-9C2605A29F52' + public static readonly UUID: string = 'E863F121-079E-48FF-8F27-9C2605A29F52' - constructor() { - super('Eve-S2W2', EveS2W2.UUID, { - format: Formats.DATA, - perms: [Perms.PAIRED_WRITE, Perms.HIDDEN], - }) - } + constructor() { + super('Eve-S2W2', EveS2W2.UUID, { + format: Formats.DATA, + perms: [Perms.PAIRED_WRITE, Perms.HIDDEN] + }) + } } HAPCharacteristic.EveS2W2 = EveS2W2 diff --git a/src/lib/hap/eve-app/EveServices.ts b/src/lib/hap/eve-app/EveServices.ts index 3e638ec1..602aea2d 100644 --- a/src/lib/hap/eve-app/EveServices.ts +++ b/src/lib/hap/eve-app/EveServices.ts @@ -6,18 +6,18 @@ import HAPService from '../HAPService' */ export class EveHistoryData extends HAPService { - // Custom service for meta and/or historical information. Characteristics for logging: E863F11C, E863F121, E863F116, E863F117. Used by Eve.app. - public static readonly UUID: string = 'E863F007-079E-48FF-8F27-9C2605A29F52' + // Custom service for meta and/or historical information. Characteristics for logging: E863F11C, E863F121, E863F116, E863F117. Used by Eve.app. + public static readonly UUID: string = 'E863F007-079E-48FF-8F27-9C2605A29F52' - constructor() { - super('EveHistoryData', EveHistoryData.UUID) + constructor() { + super('EveHistoryData', EveHistoryData.UUID) - // Required Characteristics - this.addCharacteristic(HAPCharacteristic.EveS2R1) - this.addCharacteristic(HAPCharacteristic.EveS2R2) - this.addCharacteristic(HAPCharacteristic.EveS2W1) - this.addCharacteristic(HAPCharacteristic.EveS2W2) - } + // Required Characteristics + this.addCharacteristic(HAPCharacteristic.EveS2R1) + this.addCharacteristic(HAPCharacteristic.EveS2R2) + this.addCharacteristic(HAPCharacteristic.EveS2W1) + this.addCharacteristic(HAPCharacteristic.EveS2W2) + } } HAPService.EveHistoryData = EveHistoryData diff --git a/src/lib/types/AccessoryInformationType.ts b/src/lib/types/AccessoryInformationType.ts index c739b654..12f7c6d0 100644 --- a/src/lib/types/AccessoryInformationType.ts +++ b/src/lib/types/AccessoryInformationType.ts @@ -1,12 +1,12 @@ type AccessoryInformationType = { - UUID: string - name: string - manufacturer: string - serialNo: string - model: string - firmwareRev: string - hardwareRev?: string - softwareRev?: string + UUID: string + name: string + manufacturer: string + serialNo: string + model: string + firmwareRev: string + hardwareRev?: string + softwareRev?: string } export default AccessoryInformationType diff --git a/src/lib/types/CameraConfigType.ts b/src/lib/types/CameraConfigType.ts index ce639a7b..eb12260b 100644 --- a/src/lib/types/CameraConfigType.ts +++ b/src/lib/types/CameraConfigType.ts @@ -1,25 +1,25 @@ type CameraConfigType = { - cameraConfigVideoProcessor: string - cameraConfigSource: string - cameraConfigStillImageSource?: string - cameraConfigMaxStreams: number - cameraConfigMaxWidth: number - cameraConfigMaxHeight: number - cameraConfigMaxFPS: number - cameraConfigMaxBitrate: number - cameraConfigVideoCodec: string - cameraConfigAudioCodec: string - cameraConfigAudio: string - cameraConfigPacketSize: number - cameraConfigVerticalFlip: boolean - cameraConfigHorizontalFlip: boolean - cameraConfigMapVideo: string - cameraConfigMapAudio: string - cameraConfigVideoFilter: string - cameraConfigAdditionalCommandLine: string - cameraConfigDebug: boolean - cameraConfigSnapshotOutput: string - cameraConfigInterfaceName: string + cameraConfigVideoProcessor: string + cameraConfigSource: string + cameraConfigStillImageSource?: string + cameraConfigMaxStreams: number + cameraConfigMaxWidth: number + cameraConfigMaxHeight: number + cameraConfigMaxFPS: number + cameraConfigMaxBitrate: number + cameraConfigVideoCodec: string + cameraConfigAudioCodec: string + cameraConfigAudio: string + cameraConfigPacketSize: number + cameraConfigVerticalFlip: boolean + cameraConfigHorizontalFlip: boolean + cameraConfigMapVideo: string + cameraConfigMapAudio: string + cameraConfigVideoFilter: string + cameraConfigAdditionalCommandLine: string + cameraConfigDebug: boolean + cameraConfigSnapshotOutput: string + cameraConfigInterfaceName: string } export default CameraConfigType diff --git a/src/lib/types/CustomCharacteristicType.ts b/src/lib/types/CustomCharacteristicType.ts index 7a70d020..a5171108 100644 --- a/src/lib/types/CustomCharacteristicType.ts +++ b/src/lib/types/CustomCharacteristicType.ts @@ -1,8 +1,8 @@ import { CharacteristicProps } from '@homebridge/hap-nodejs' type CustomCharacteristicType = CharacteristicProps & { - UUID?: string - name?: string + UUID?: string + name?: string } export default CustomCharacteristicType diff --git a/src/lib/types/HAPHostConfigType.ts b/src/lib/types/HAPHostConfigType.ts index 606696da..4be5fc89 100644 --- a/src/lib/types/HAPHostConfigType.ts +++ b/src/lib/types/HAPHostConfigType.ts @@ -5,21 +5,21 @@ import { SemVer } from 'semver' import HapCategories from './hap-nodejs/HapCategories' type HAPHostConfigType = NodeDef & { - bridgeName: string - pinCode: string - port?: number - allowInsecureRequest: boolean - manufacturer: string - model: string - serialNo: string - firmwareRev: SemVer - hardwareRev: SemVer - softwareRev: SemVer - bind?: string - bindType?: 'json' | 'str' - allowMessagePassthrough: boolean - accessoryCategory: HapCategories - advertiser: MDNSAdvertiser + bridgeName: string + pinCode: string + port?: number + allowInsecureRequest: boolean + manufacturer: string + model: string + serialNo: string + firmwareRev: SemVer + hardwareRev: SemVer + softwareRev: SemVer + bind?: string + bindType?: 'json' | 'str' + allowMessagePassthrough: boolean + accessoryCategory: HapCategories + advertiser: MDNSAdvertiser } export default HAPHostConfigType diff --git a/src/lib/types/HAPHostNodeType.ts b/src/lib/types/HAPHostNodeType.ts index 0bc12592..d34c2b4f 100644 --- a/src/lib/types/HAPHostNodeType.ts +++ b/src/lib/types/HAPHostNodeType.ts @@ -5,13 +5,13 @@ import HostType from './HostType' import NodeType from './NodeType' type HAPHostNodeType = NodeType & { - config: HAPHostConfigType - accessoryCategory: Categories - published: boolean - bridgeUsername: string - publish: () => boolean - hostType: HostType - host: Accessory + config: HAPHostConfigType + accessoryCategory: Categories + published: boolean + bridgeUsername: string + publish: () => boolean + hostType: HostType + host: Accessory } export default HAPHostNodeType diff --git a/src/lib/types/HAPService2ConfigType.ts b/src/lib/types/HAPService2ConfigType.ts index 6b20a500..59212fd2 100644 --- a/src/lib/types/HAPService2ConfigType.ts +++ b/src/lib/types/HAPService2ConfigType.ts @@ -3,8 +3,8 @@ import { NodeDef } from 'node-red' import HAPServiceConfigType from './HAPServiceConfigType' type HAPService2ConfigType = NodeDef & - HAPServiceConfigType & { - useEventCallback: boolean - } + HAPServiceConfigType & { + useEventCallback: boolean + } export default HAPService2ConfigType diff --git a/src/lib/types/HAPService2NodeType.ts b/src/lib/types/HAPService2NodeType.ts index 07ce84c7..b270f115 100644 --- a/src/lib/types/HAPService2NodeType.ts +++ b/src/lib/types/HAPService2NodeType.ts @@ -3,8 +3,8 @@ import HAPServiceNodeType from './HAPServiceNodeType' import NodeType from './NodeType' type HAPService2NodeType = NodeType & - HAPServiceNodeType & { - config: HAPService2ConfigType - } + HAPServiceNodeType & { + config: HAPService2ConfigType + } export default HAPService2NodeType diff --git a/src/lib/types/HAPServiceConfigType.ts b/src/lib/types/HAPServiceConfigType.ts index e8f9540b..2c18c47e 100644 --- a/src/lib/types/HAPServiceConfigType.ts +++ b/src/lib/types/HAPServiceConfigType.ts @@ -4,29 +4,29 @@ import { NodeDef } from 'node-red' import CameraConfigType from './CameraConfigType' type HAPServiceConfigType = NodeDef & { - isParent: boolean - // hostType is number but browser js is passing it as string which may cause same comparison issues - // values are BRIDGE = 0, STANDALONE = 1 - hostType: number - bridge: string - accessoryId: string - parentService: string - name: string - serviceName: string - topic: string - filter: boolean - manufacturer: string - model: string - serialNo: string - firmwareRev?: string - hardwareRev?: string - softwareRev?: string - characteristicProperties: string - waitForSetupMsg: boolean - // If Service is a LightBulb, you can set AdaptiveLightingControllerMode.ts Lightning Mode - adaptiveLightingOptionsEnable?: boolean - adaptiveLightingOptionsMode?: AdaptiveLightingControllerMode - adaptiveLightingOptionsCustomTemperatureAdjustment?: number + isParent: boolean + // hostType is number but browser js is passing it as string which may cause same comparison issues + // values are BRIDGE = 0, STANDALONE = 1 + hostType: number + bridge: string + accessoryId: string + parentService: string + name: string + serviceName: string + topic: string + filter: boolean + manufacturer: string + model: string + serialNo: string + firmwareRev?: string + hardwareRev?: string + softwareRev?: string + characteristicProperties: string + waitForSetupMsg: boolean + // If Service is a LightBulb, you can set AdaptiveLightingControllerMode.ts Lightning Mode + adaptiveLightingOptionsEnable?: boolean + adaptiveLightingOptionsMode?: AdaptiveLightingControllerMode + adaptiveLightingOptionsCustomTemperatureAdjustment?: number } & CameraConfigType export default HAPServiceConfigType diff --git a/src/lib/types/HAPServiceNodeType.ts b/src/lib/types/HAPServiceNodeType.ts index 92f01c86..12f5fa27 100644 --- a/src/lib/types/HAPServiceNodeType.ts +++ b/src/lib/types/HAPServiceNodeType.ts @@ -1,13 +1,13 @@ import { - Accessory, - AdaptiveLightingController, - Characteristic, - CharacteristicChange, - CharacteristicGetCallback, - CharacteristicProps, - CharacteristicSetCallback, - CharacteristicValue, - Service, + Accessory, + AdaptiveLightingController, + Characteristic, + CharacteristicChange, + CharacteristicGetCallback, + CharacteristicProps, + CharacteristicSetCallback, + CharacteristicValue, + Service } from '@homebridge/hap-nodejs' import { CharacteristicContext } from '@homebridge/hap-nodejs/dist/lib/Characteristic' import { HAPConnection } from '@homebridge/hap-nodejs/dist/lib/util/eventedhttp' @@ -21,44 +21,44 @@ import NodeType from './NodeType' import PublishTimersType from './PublishTimersType' type HAPServiceNodeType = NodeType & { - config: HAPServiceConfigType - RED: NodeAPI - setupDone: boolean - configured: boolean - handleWaitForSetup: (msg: any) => any - onIdentify: (paired: boolean, callback: () => any) => void - hostNode: HAPHostNodeType - childNodes?: (HAPService2NodeType | HAPServiceNodeType)[] - service: Service - parentService: Service - parentNode?: HAPService2NodeType | HAPServiceNodeType - accessory: Accessory - characteristicProperties: { [key: string]: CharacteristicProps } - supported: string[] - publishTimers: PublishTimersType - topic_in: string - onCharacteristicGet: ( - this: Characteristic, - callback: CharacteristicGetCallback, - context: CharacteristicContext, - connection?: HAPConnection - ) => void - onCharacteristicSet: ( - this: Characteristic, - value: CharacteristicValue, - callback: CharacteristicSetCallback, - context: CharacteristicContext, - connection?: HAPConnection - ) => void - onCharacteristicChange: ( - this: Characteristic, - change: CharacteristicChange - ) => void - uniqueIdentifier: string - // Is Accessory reachable? On Linked Service it will be undefined. If is not true then NO_RESPONSE - reachable?: boolean - nodeStatusUtils: NodeStatusUtils - adaptiveLightingController?: AdaptiveLightingController + config: HAPServiceConfigType + RED: NodeAPI + setupDone: boolean + configured: boolean + handleWaitForSetup: (msg: any) => any + onIdentify: (paired: boolean, callback: () => any) => void + hostNode: HAPHostNodeType + childNodes?: (HAPService2NodeType | HAPServiceNodeType)[] + service: Service + parentService: Service + parentNode?: HAPService2NodeType | HAPServiceNodeType + accessory: Accessory + characteristicProperties: { [key: string]: CharacteristicProps } + supported: string[] + publishTimers: PublishTimersType + topic_in: string + onCharacteristicGet: ( + this: Characteristic, + callback: CharacteristicGetCallback, + context: CharacteristicContext, + connection?: HAPConnection + ) => void + onCharacteristicSet: ( + this: Characteristic, + value: CharacteristicValue, + callback: CharacteristicSetCallback, + context: CharacteristicContext, + connection?: HAPConnection + ) => void + onCharacteristicChange: ( + this: Characteristic, + change: CharacteristicChange + ) => void + uniqueIdentifier: string + // Is Accessory reachable? On Linked Service it will be undefined. If is not true then NO_RESPONSE + reachable?: boolean + nodeStatusUtils: NodeStatusUtils + adaptiveLightingController?: AdaptiveLightingController } export default HAPServiceNodeType diff --git a/src/lib/types/HAPStatusConfigType.ts b/src/lib/types/HAPStatusConfigType.ts index e24e2795..a67cfd93 100644 --- a/src/lib/types/HAPStatusConfigType.ts +++ b/src/lib/types/HAPStatusConfigType.ts @@ -1,7 +1,7 @@ import { NodeDef } from 'node-red' type HAPStatusConfigType = NodeDef & { - serviceNodeId: string + serviceNodeId: string } export default HAPStatusConfigType diff --git a/src/lib/types/HAPStatusNodeType.ts b/src/lib/types/HAPStatusNodeType.ts index 187af0cd..108fc373 100644 --- a/src/lib/types/HAPStatusNodeType.ts +++ b/src/lib/types/HAPStatusNodeType.ts @@ -6,10 +6,10 @@ import HAPStatusConfigType from './HAPStatusConfigType' import NodeType from './NodeType' type HAPStatusNodeType = NodeType & { - config: HAPStatusConfigType - RED: NodeAPI - serviceNode?: HAPServiceNodeType - nodeStatusUtils: NodeStatusUtils + config: HAPStatusConfigType + RED: NodeAPI + serviceNode?: HAPServiceNodeType + nodeStatusUtils: NodeStatusUtils } export default HAPStatusNodeType diff --git a/src/lib/types/HostType.ts b/src/lib/types/HostType.ts index 12ace0ca..b27bcdbb 100644 --- a/src/lib/types/HostType.ts +++ b/src/lib/types/HostType.ts @@ -1,6 +1,6 @@ enum HostType { - BRIDGE = 0, - STANDALONE = 1, + BRIDGE = 0, + STANDALONE = 1 } export default HostType diff --git a/src/lib/types/PublishTimersType.ts b/src/lib/types/PublishTimersType.ts index de5fe20e..8d6612a3 100644 --- a/src/lib/types/PublishTimersType.ts +++ b/src/lib/types/PublishTimersType.ts @@ -1,5 +1,5 @@ type PublishTimersType = { - [key: string]: NodeJS.Timeout + [key: string]: NodeJS.Timeout } export default PublishTimersType diff --git a/src/lib/types/hap-nodejs/HapAdaptiveLightingControllerMode.ts b/src/lib/types/hap-nodejs/HapAdaptiveLightingControllerMode.ts index f04a6202..94cb07f8 100644 --- a/src/lib/types/hap-nodejs/HapAdaptiveLightingControllerMode.ts +++ b/src/lib/types/hap-nodejs/HapAdaptiveLightingControllerMode.ts @@ -1,13 +1,13 @@ enum HapAdaptiveLightingControllerMode { - /** - * In automatic mode pretty much everything from setup to transition scheduling is done by the controller. - */ - AUTOMATIC = 1, - /** - * In manual mode setup is done by the controller but the actual transition must be done by the user. - * This is useful for lights which natively support transitions. - */ - MANUAL = 2, + /** + * In automatic mode pretty much everything from setup to transition scheduling is done by the controller. + */ + AUTOMATIC = 1, + /** + * In manual mode setup is done by the controller but the actual transition must be done by the user. + * This is useful for lights which natively support transitions. + */ + MANUAL = 2 } export default HapAdaptiveLightingControllerMode diff --git a/src/lib/types/hap-nodejs/HapCategories.ts b/src/lib/types/hap-nodejs/HapCategories.ts index 1f5b5f1d..8077f826 100644 --- a/src/lib/types/hap-nodejs/HapCategories.ts +++ b/src/lib/types/hap-nodejs/HapCategories.ts @@ -1,46 +1,44 @@ // hap-nodejs declared this as const enum which makes it difficult to iterate key-value // Known category values. Category is a hint to iOS clients about what "type" of Accessory this represents, for UI only. enum HapCategories { - OTHER = 1, - BRIDGE = 2, - FAN = 3, - GARAGE_DOOR_OPENER = 4, - LIGHTBULB = 5, - DOOR_LOCK = 6, - OUTLET = 7, - SWITCH = 8, - THERMOSTAT = 9, - SENSOR = 10, - ALARM_SYSTEM = 11, - // eslint-disable-next-line @typescript-eslint/no-duplicate-enum-values - SECURITY_SYSTEM = 11, //Added to conform to HAP naming - DOOR = 12, - WINDOW = 13, - WINDOW_COVERING = 14, - PROGRAMMABLE_SWITCH = 15, - RANGE_EXTENDER = 16, - CAMERA = 17, - // eslint-disable-next-line @typescript-eslint/no-duplicate-enum-values - IP_CAMERA = 17, //Added to conform to HAP naming - VIDEO_DOORBELL = 18, - AIR_PURIFIER = 19, - AIR_HEATER = 20, - AIR_CONDITIONER = 21, - AIR_HUMIDIFIER = 22, - AIR_DEHUMIDIFIER = 23, - APPLE_TV = 24, - HOMEPOD = 25, - SPEAKER = 26, - AIRPORT = 27, - SPRINKLER = 28, - FAUCET = 29, - SHOWER_HEAD = 30, - TELEVISION = 31, - TARGET_CONTROLLER = 32, // Remote Control - ROUTER = 33, - AUDIO_RECEIVER = 34, - TV_SET_TOP_BOX = 35, - TV_STREAMING_STICK = 36, + OTHER = 1, + BRIDGE = 2, + FAN = 3, + GARAGE_DOOR_OPENER = 4, + LIGHTBULB = 5, + DOOR_LOCK = 6, + OUTLET = 7, + SWITCH = 8, + THERMOSTAT = 9, + SENSOR = 10, + ALARM_SYSTEM = 11, + SECURITY_SYSTEM = 11, //Added to conform to HAP naming + DOOR = 12, + WINDOW = 13, + WINDOW_COVERING = 14, + PROGRAMMABLE_SWITCH = 15, + RANGE_EXTENDER = 16, + CAMERA = 17, + IP_CAMERA = 17, //Added to conform to HAP naming + VIDEO_DOORBELL = 18, + AIR_PURIFIER = 19, + AIR_HEATER = 20, + AIR_CONDITIONER = 21, + AIR_HUMIDIFIER = 22, + AIR_DEHUMIDIFIER = 23, + APPLE_TV = 24, + HOMEPOD = 25, + SPEAKER = 26, + AIRPORT = 27, + SPRINKLER = 28, + FAUCET = 29, + SHOWER_HEAD = 30, + TELEVISION = 31, + TARGET_CONTROLLER = 32, // Remote Control + ROUTER = 33, + AUDIO_RECEIVER = 34, + TV_SET_TOP_BOX = 35, + TV_STREAMING_STICK = 36 } export default HapCategories diff --git a/src/lib/types/storage/SerializedHostType.ts b/src/lib/types/storage/SerializedHostType.ts index 1a8544bd..cea820a0 100644 --- a/src/lib/types/storage/SerializedHostType.ts +++ b/src/lib/types/storage/SerializedHostType.ts @@ -1,7 +1,7 @@ import { SerializedAccessory } from '@homebridge/hap-nodejs' type SerializedHostType = { - _isBridge: boolean + _isBridge: boolean } & SerializedAccessory export { SerializedHostType } diff --git a/src/lib/types/storage/StorageType.ts b/src/lib/types/storage/StorageType.ts index d06dd4b2..60e06e58 100644 --- a/src/lib/types/storage/StorageType.ts +++ b/src/lib/types/storage/StorageType.ts @@ -1,9 +1,9 @@ enum StorageType { - SERVICE = 'service', // For Future Use - ACCESSORY = 'accessory', // For Future Use - HOST = 'host', // For Future Use - CUSTOM_CHARACTERISTICS = 'customCharacteristics', - OTHER = 'other', // For Future Use + SERVICE = 'service', // For Future Use + ACCESSORY = 'accessory', // For Future Use + HOST = 'host', // For Future Use + CUSTOM_CHARACTERISTICS = 'customCharacteristics', + OTHER = 'other' // For Future Use } export { StorageType } diff --git a/src/lib/utils/AccessoryUtils.ts b/src/lib/utils/AccessoryUtils.ts index 45cbbdbe..1b089435 100644 --- a/src/lib/utils/AccessoryUtils.ts +++ b/src/lib/utils/AccessoryUtils.ts @@ -5,218 +5,205 @@ import AccessoryInformationType from '../types/AccessoryInformationType' import HAPServiceNodeType from '../types/HAPServiceNodeType' module.exports = function (node: HAPServiceNodeType) { - const HapNodeJS = require('@homebridge/hap-nodejs') - const Accessory = HapNodeJS.Accessory - const Service = HapNodeJS.Service - const Characteristic = HapNodeJS.Characteristic - - const log = logger('NRCHKB', 'AccessoryUtils', node.config.name, node) - - const getOrCreate = function ( - host: Accessory, - accessoryInformation: AccessoryInformationType, - subtypeUUID: string - ) { - let accessory: Accessory | undefined - const services: Service[] = [] - - // create accessory object + const HapNodeJS = require('@homebridge/hap-nodejs') + const Accessory = HapNodeJS.Accessory + const Service = HapNodeJS.Service + const Characteristic = HapNodeJS.Characteristic + + const log = logger('NRCHKB', 'AccessoryUtils', node.config.name, node) + + const getOrCreate = function ( + host: Accessory, + accessoryInformation: AccessoryInformationType, + subtypeUUID: string + ) { + let accessory: Accessory | undefined + const services: Service[] = [] + + // create accessory object + log.debug(`Looking for accessory with service subtype ${subtypeUUID} ...`) + + // Try to find an accessory which contains a service with the same + // subtype. Since the UUID of the accessory might have changed the + // subtype will be used instead. + accessory = host.bridgedAccessories.find((a) => { + const service = a.services.find((s) => { + return s.subtype === subtypeUUID + }) + + return service !== undefined + }) + + if (accessory) { + // An accessory was found + const accessoryInformationService = + accessory.getService(Service.AccessoryInformation) || + accessory.addService(Service.AccessoryInformation) + + if ( + accessoryInformationService.getCharacteristic( + Characteristic.Manufacturer + ).value !== accessoryInformation.manufacturer || + accessoryInformationService.getCharacteristic(Characteristic.Model) + .value !== accessoryInformation.model || + accessoryInformationService.getCharacteristic(Characteristic.Name) + .value !== accessoryInformation.name || + accessoryInformationService.getCharacteristic( + Characteristic.SerialNumber + ).value !== accessoryInformation.serialNo + ) { log.debug( - `Looking for accessory with service subtype ${subtypeUUID} ...` + '... Manufacturer, Model, Name or Serial Number changed! Replacing it.' ) - // Try to find an accessory which contains a service with the same - // subtype. Since the UUID of the accessory might have changed the - // subtype will be used instead. - accessory = host.bridgedAccessories.find((a) => { - const service = a.services.find((s) => { - return s.subtype === subtypeUUID - }) - - return service !== undefined - }) - - if (accessory) { - // An accessory was found - const accessoryInformationService = - accessory.getService(Service.AccessoryInformation) || - accessory.addService(Service.AccessoryInformation) - - if ( - accessoryInformationService.getCharacteristic( - Characteristic.Manufacturer - ).value !== accessoryInformation.manufacturer || - accessoryInformationService.getCharacteristic( - Characteristic.Model - ).value !== accessoryInformation.model || - accessoryInformationService.getCharacteristic( - Characteristic.Name - ).value !== accessoryInformation.name || - accessoryInformationService.getCharacteristic( - Characteristic.SerialNumber - ).value !== accessoryInformation.serialNo - ) { - log.debug( - '... Manufacturer, Model, Name or Serial Number changed! Replacing it.' - ) - - // Removing services from accessory and storing them for later - accessory.services - .filter( - (service) => - service.UUID !== Service.AccessoryInformation.UUID - ) - .forEach((service) => { - accessory?.removeService(service) - services.push(service) - }) - - // Remove old Accessory - host.removeBridgedAccessory(accessory, false) - accessory.destroy() - accessory = undefined - } else { - log.debug('... found it! Updating it.') - } - } else { - log.debug( - `... didn't find it. Adding new accessory with name ${accessoryInformation.name} and UUID ${accessoryInformation.UUID}` - ) - } - - let accessoryInformationService: Service | undefined - - if (!accessory) { - // A new accessory will be created. - accessory = new Accessory( - accessoryInformation.name, - accessoryInformation.UUID - ) - - // If the accessory is getting replaced then all of the old - // services (except AccessoryInformation) will be transferred to - // the new accessory. - services.forEach((service) => { - accessory?.addService(service) - }) - - accessoryInformationService = - accessory?.getService(Service.AccessoryInformation) || - accessory?.addService(Service.AccessoryInformation) - - // Setting manufacturer data. According to the HomekitADK specs this - // data must persist throughout the lifetime of the accessory and - // may not be changed. - accessoryInformationService - ?.setCharacteristic( - Characteristic.Name, - accessoryInformation.name - ) - .setCharacteristic( - Characteristic.Manufacturer, - accessoryInformation.manufacturer - ) - .setCharacteristic( - Characteristic.SerialNumber, - accessoryInformation.serialNo - ) - .setCharacteristic( - Characteristic.Model, - accessoryInformation.model - ) - - const revisionRegex = /\d+\.\d+\.\d+/ - - if ( - accessoryInformation.firmwareRev && - accessoryInformation.firmwareRev.match(revisionRegex) - ) { - accessoryInformationService?.setCharacteristic( - Characteristic.FirmwareRevision, - accessoryInformation.firmwareRev - ) - } - - if ( - accessoryInformation.hardwareRev && - accessoryInformation.hardwareRev.match(revisionRegex) - ) { - accessoryInformationService?.setCharacteristic( - Characteristic.HardwareRevision, - accessoryInformation.hardwareRev - ) - } - - if ( - accessoryInformation.softwareRev && - accessoryInformation.softwareRev.match(revisionRegex) - ) { - accessoryInformationService?.setCharacteristic( - Characteristic.SoftwareRevision, - accessoryInformation.softwareRev - ) - } - - // Adding new accessory to the bridge. - host.addBridgedAccessories([accessory!]) - } else { - accessoryInformationService = - accessory?.getService(Service.AccessoryInformation) || - accessory?.addService(Service.AccessoryInformation) - } + // Removing services from accessory and storing them for later + accessory.services + .filter( + (service) => service.UUID !== Service.AccessoryInformation.UUID + ) + .forEach((service) => { + accessory?.removeService(service) + services.push(service) + }) + + // Remove old Accessory + host.removeBridgedAccessory(accessory, false) + accessory.destroy() + accessory = undefined + } else { + log.debug('... found it! Updating it.') + } + } else { + log.debug( + `... didn't find it. Adding new accessory with name ${accessoryInformation.name} and UUID ${accessoryInformation.UUID}` + ) + } + + let accessoryInformationService: Service | undefined + + if (!accessory) { + // A new accessory will be created. + accessory = new Accessory( + accessoryInformation.name, + accessoryInformation.UUID + ) + + // If the accessory is getting replaced then all of the old + // services (except AccessoryInformation) will be transferred to + // the new accessory. + services.forEach((service) => { + accessory?.addService(service) + }) + + accessoryInformationService = + accessory?.getService(Service.AccessoryInformation) || + accessory?.addService(Service.AccessoryInformation) + + // Setting manufacturer data. According to the HomekitADK specs this + // data must persist throughout the lifetime of the accessory and + // may not be changed. + accessoryInformationService + ?.setCharacteristic(Characteristic.Name, accessoryInformation.name) + .setCharacteristic( + Characteristic.Manufacturer, + accessoryInformation.manufacturer + ) + .setCharacteristic( + Characteristic.SerialNumber, + accessoryInformation.serialNo + ) + .setCharacteristic(Characteristic.Model, accessoryInformation.model) + + const revisionRegex = /\d+\.\d+\.\d+/ + if ( + accessoryInformation.firmwareRev && + accessoryInformation.firmwareRev.match(revisionRegex) + ) { accessoryInformationService?.setCharacteristic( - Characteristic.Identify, - true + Characteristic.FirmwareRevision, + accessoryInformation.firmwareRev ) + } - log.debug( - `Bridge now has ${host.bridgedAccessories.length} accessories.` + if ( + accessoryInformation.hardwareRev && + accessoryInformation.hardwareRev.match(revisionRegex) + ) { + accessoryInformationService?.setCharacteristic( + Characteristic.HardwareRevision, + accessoryInformation.hardwareRev ) + } - return accessory + if ( + accessoryInformation.softwareRev && + accessoryInformation.softwareRev.match(revisionRegex) + ) { + accessoryInformationService?.setCharacteristic( + Characteristic.SoftwareRevision, + accessoryInformation.softwareRev + ) + } + + // Adding new accessory to the bridge. + host.addBridgedAccessories([accessory!]) + } else { + accessoryInformationService = + accessory?.getService(Service.AccessoryInformation) || + accessory?.addService(Service.AccessoryInformation) } - const onIdentify = function (paired: boolean, callback: () => any) { - if (paired) { - log.debug( - `Identify called on paired Accessory ${node.accessory.displayName}` - ) - } else { - log.debug( - `Identify called on unpaired Accessory ${node.accessory.displayName}` - ) - } - - const nodes = node.childNodes ?? [] - - for (let i = 0, len = nodes.length; i < len; i++) { - const topic = nodes[i].config.topic - ? nodes[i].config.topic - : nodes[i].topic_in - const msg = { - payload: { Identify: 1 }, - name: nodes[i].name, - topic: topic, - } - - const statusId = nodes[i].nodeStatusUtils.setStatus({ - fill: 'yellow', - shape: 'dot', - text: 'Identify : 1', - }) - - setTimeout(function () { - nodes[i].nodeStatusUtils.clearStatus(statusId) - }, 3000) - - nodes[i].send([msg, msg]) - } - callback() + accessoryInformationService?.setCharacteristic( + Characteristic.Identify, + true + ) + + log.debug(`Bridge now has ${host.bridgedAccessories.length} accessories.`) + + return accessory + } + + const onIdentify = function (paired: boolean, callback: () => any) { + if (paired) { + log.debug( + `Identify called on paired Accessory ${node.accessory.displayName}` + ) + } else { + log.debug( + `Identify called on unpaired Accessory ${node.accessory.displayName}` + ) } - return { - getOrCreate, - onIdentify, + const nodes = node.childNodes ?? [] + + for (let i = 0, len = nodes.length; i < len; i++) { + const topic = nodes[i].config.topic + ? nodes[i].config.topic + : nodes[i].topic_in + const msg = { + payload: { Identify: 1 }, + name: nodes[i].name, + topic: topic + } + + const statusId = nodes[i].nodeStatusUtils.setStatus({ + fill: 'yellow', + shape: 'dot', + text: 'Identify : 1' + }) + + setTimeout(function () { + nodes[i].nodeStatusUtils.clearStatus(statusId) + }, 3000) + + nodes[i].send([msg, msg]) } + callback() + } + + return { + getOrCreate, + onIdentify + } } diff --git a/src/lib/utils/BridgeUtils.ts b/src/lib/utils/BridgeUtils.ts index c40e5ed2..70405c15 100644 --- a/src/lib/utils/BridgeUtils.ts +++ b/src/lib/utils/BridgeUtils.ts @@ -4,49 +4,49 @@ import HAPServiceNodeType from '../types/HAPServiceNodeType' import HostType from '../types/HostType' module.exports = function () { - // Publish accessory after the service has been added - // BUT ONLY after 5 seconds with no new service have passed - // otherwise, our bridge would get published too early during startup and - // services being added after that point would be seen as "new" in iOS, - // removing all parameters set (Rooms, Groups, Scenes...) - const delayedPublish = function (node: HAPServiceNodeType) { - const log = logger('NRCHKB', 'BridgeUtils', node.config.name, node) - - if (!node.hostNode.published) { - if (node.publishTimers[node.hostNode.id] !== undefined) { - clearTimeout(node.publishTimers[node.hostNode.id]) + // Publish accessory after the service has been added + // BUT ONLY after 5 seconds with no new service have passed + // otherwise, our bridge would get published too early during startup and + // services being added after that point would be seen as "new" in iOS, + // removing all parameters set (Rooms, Groups, Scenes...) + const delayedPublish = function (node: HAPServiceNodeType) { + const log = logger('NRCHKB', 'BridgeUtils', node.config.name, node) + + if (!node.hostNode.published) { + if (node.publishTimers[node.hostNode.id] !== undefined) { + clearTimeout(node.publishTimers[node.hostNode.id]) + } + + const hostTypeName = + node.hostNode.hostType == HostType.BRIDGE + ? 'Bridge' + : 'Standalone Accessory' + + node.publishTimers[node.hostNode.id] = setTimeout(function () { + try { + if (!node.hostNode.published) { + const published = node.hostNode.publish() + + if (published) { + log.debug(`${hostTypeName} published`) + } else { + log.error(`${hostTypeName} not published`) } - - const hostTypeName = - node.hostNode.hostType == HostType.BRIDGE - ? 'Bridge' - : 'Standalone Accessory' - - node.publishTimers[node.hostNode.id] = setTimeout(function () { - try { - if (!node.hostNode.published) { - const published = node.hostNode.publish() - - if (published) { - log.debug(`${hostTypeName} published`) - } else { - log.error(`${hostTypeName} not published`) - } - } - } catch (error) { - log.error(`${hostTypeName} publish failed due to ${error}`) - - node.nodeStatusUtils.setStatus({ - fill: 'red', - shape: 'ring', - text: 'Error while publishing ' + hostTypeName, - }) - } - }, 5000) + } + } catch (error) { + log.error(`${hostTypeName} publish failed due to ${error}`) + + node.nodeStatusUtils.setStatus({ + fill: 'red', + shape: 'ring', + text: 'Error while publishing ' + hostTypeName + }) } + }, 5000) } + } - return { - delayedPublish: delayedPublish, - } + return { + delayedPublish: delayedPublish + } } diff --git a/src/lib/utils/CharacteristicUtils.ts b/src/lib/utils/CharacteristicUtils.ts index 978e3f57..c7c494ae 100644 --- a/src/lib/utils/CharacteristicUtils.ts +++ b/src/lib/utils/CharacteristicUtils.ts @@ -1,7 +1,7 @@ import { - Characteristic, - CharacteristicProps, - Service, + Characteristic, + CharacteristicProps, + Service } from '@homebridge/hap-nodejs' import { logger } from '@nrchkb/logger' @@ -9,97 +9,90 @@ import HAPServiceConfigType from '../types/HAPServiceConfigType' import HAPServiceNodeType from '../types/HAPServiceNodeType' module.exports = function (node: HAPServiceNodeType) { - const log = logger('NRCHKB', 'CharacteristicUtils', node.config.name, node) - const ServiceUtils = require('./ServiceUtils')(node) - - const load = function ( - service: Service, - config: HAPServiceConfigType - ): { [key: string]: CharacteristicProps } { - let characteristicProperties: { - [key: string]: CharacteristicProps - } = {} - - if ( - config.characteristicProperties && - config.characteristicProperties.length > 0 - ) { - characteristicProperties = JSON.parse( - config.characteristicProperties.replace( - /\${(.*?)}/g, - (_, envName) => - node.RED.util.evaluateNodeProperty( - envName, - 'env', - node, - {} - ) - ) - ) - - log.trace('Evaluating value:') - log.trace(config.characteristicProperties) - log.trace('Evaluated as:') - log.trace(JSON.stringify(characteristicProperties)) - - // Configure custom characteristic properties - for (const key in characteristicProperties) { - if (!characteristicProperties.hasOwnProperty(key)) continue - - const characteristic = service.getCharacteristic( - // @ts-ignore - Characteristic[key] - ) - - if (characteristic && characteristicProperties[key]) { - log.debug(`Found Characteristic Properties for ${key}`) - characteristic.setProps(characteristicProperties[key]) - } - } - } - - return characteristicProperties - } - - const subscribeAndGetSupported = function (service: Service) { - const supported: string[] = [] - - const allCharacteristics = service.characteristics.concat( - service.optionalCharacteristics - ) - - // Listen to characteristic events and store the listener functions - // to be able to remove them later - node.onCharacteristicGet = ServiceUtils.onCharacteristicGet - node.onCharacteristicSet = ServiceUtils.onCharacteristicSet( - service.characteristics - ) - node.onCharacteristicChange = ServiceUtils.onCharacteristicChange( - service.characteristics + const log = logger('NRCHKB', 'CharacteristicUtils', node.config.name, node) + const ServiceUtils = require('./ServiceUtils')(node) + + const load = function ( + service: Service, + config: HAPServiceConfigType + ): { [key: string]: CharacteristicProps } { + let characteristicProperties: { + [key: string]: CharacteristicProps + } = {} + + if ( + config.characteristicProperties && + config.characteristicProperties.length > 0 + ) { + characteristicProperties = JSON.parse( + config.characteristicProperties.replace(/\${(.*?)}/g, (_, envName) => + node.RED.util.evaluateNodeProperty(envName, 'env', node, {}) ) + ) - allCharacteristics.map((characteristic) => { - const cKey = characteristic.constructor.name - - supported.push(cKey) + log.trace('Evaluating value:') + log.trace(config.characteristicProperties) + log.trace('Evaluated as:') + log.trace(JSON.stringify(characteristicProperties)) - characteristic.on('get', node.onCharacteristicGet) - characteristic.on('set', node.onCharacteristicSet) - characteristic.on('change', node.onCharacteristicChange) + // Configure custom characteristic properties + for (const key in characteristicProperties) { + if (!characteristicProperties.hasOwnProperty(key)) continue - //TODO: Remove when persist table is here - //Allow for negative temperatures - if (characteristic.displayName === 'Current Temperature') { - characteristic.props.minValue = -100 - } - }) + const characteristic = service.getCharacteristic( + // @ts-ignore + Characteristic[key] + ) - // Removing accidental duplicate values - return [...new Set(supported)] + if (characteristic && characteristicProperties[key]) { + log.debug(`Found Characteristic Properties for ${key}`) + characteristic.setProps(characteristicProperties[key]) + } + } } - return { - load: load, - subscribeAndGetSupported: subscribeAndGetSupported, - } + return characteristicProperties + } + + const subscribeAndGetSupported = function (service: Service) { + const supported: string[] = [] + + const allCharacteristics = service.characteristics.concat( + service.optionalCharacteristics + ) + + // Listen to characteristic events and store the listener functions + // to be able to remove them later + node.onCharacteristicGet = ServiceUtils.onCharacteristicGet + node.onCharacteristicSet = ServiceUtils.onCharacteristicSet( + service.characteristics + ) + node.onCharacteristicChange = ServiceUtils.onCharacteristicChange( + service.characteristics + ) + + allCharacteristics.map((characteristic) => { + const cKey = characteristic.constructor.name + + supported.push(cKey) + + characteristic.on('get', node.onCharacteristicGet) + characteristic.on('set', node.onCharacteristicSet) + characteristic.on('change', node.onCharacteristicChange) + + //TODO: Remove when persist table is here + //Allow for negative temperatures + if (characteristic.displayName === 'Current Temperature') { + characteristic.props.minValue = -100 + } + }) + + // Removing accidental duplicate values + return [...new Set(supported)] + } + + return { + load: load, + subscribeAndGetSupported: subscribeAndGetSupported + } } diff --git a/src/lib/utils/CharacteristicUtils2.ts b/src/lib/utils/CharacteristicUtils2.ts index e412c1a3..b01e7f78 100644 --- a/src/lib/utils/CharacteristicUtils2.ts +++ b/src/lib/utils/CharacteristicUtils2.ts @@ -1,7 +1,7 @@ import { - Characteristic, - CharacteristicProps, - Service, + Characteristic, + CharacteristicProps, + Service } from '@homebridge/hap-nodejs' import { logger } from '@nrchkb/logger' @@ -9,99 +9,92 @@ import HAPService2ConfigType from '../types/HAPService2ConfigType' import HAPService2NodeType from '../types/HAPService2NodeType' module.exports = function (node: HAPService2NodeType) { - const log = logger('NRCHKB', 'CharacteristicUtils', node.config.name, node) - const ServiceUtils = require('./ServiceUtils2')(node) - - const load = function ( - service: Service, - config: HAPService2ConfigType - ): { [key: string]: CharacteristicProps } { - let characteristicProperties: { - [key: string]: CharacteristicProps - } = {} - - if ( - config.characteristicProperties && - config.characteristicProperties.length > 0 - ) { - characteristicProperties = JSON.parse( - config.characteristicProperties.replace( - /\${(.*?)}/g, - (_, envName) => - node.RED.util.evaluateNodeProperty( - envName, - 'env', - node, - {} - ) - ) - ) - - log.trace('Evaluating value:') - log.trace(config.characteristicProperties) - log.trace('Evaluated as:') - log.trace(JSON.stringify(characteristicProperties)) - - // Configure custom characteristic properties - for (const key in characteristicProperties) { - if (!characteristicProperties.hasOwnProperty(key)) continue - - const characteristic = service.getCharacteristic( - // @ts-ignore - Characteristic[key] - ) - - if (characteristic && characteristicProperties[key]) { - log.debug(`Found Characteristic Properties for ${key}`) - characteristic.setProps(characteristicProperties[key]) - } - } - } - - return characteristicProperties - } - - const subscribeAndGetSupported = function (service: Service) { - const supported: string[] = [] - - const allCharacteristics = service.characteristics.concat( - service.optionalCharacteristics + const log = logger('NRCHKB', 'CharacteristicUtils', node.config.name, node) + const ServiceUtils = require('./ServiceUtils2')(node) + + const load = function ( + service: Service, + config: HAPService2ConfigType + ): { [key: string]: CharacteristicProps } { + let characteristicProperties: { + [key: string]: CharacteristicProps + } = {} + + if ( + config.characteristicProperties && + config.characteristicProperties.length > 0 + ) { + characteristicProperties = JSON.parse( + config.characteristicProperties.replace(/\${(.*?)}/g, (_, envName) => + node.RED.util.evaluateNodeProperty(envName, 'env', node, {}) ) + ) - // Listen to characteristic events and store the listener functions - // to be able to remove them later - node.onCharacteristicGet = ServiceUtils.onCharacteristicGet( - service.characteristics - ) - node.onCharacteristicSet = ServiceUtils.onCharacteristicSet( - service.characteristics - ) - node.onCharacteristicChange = ServiceUtils.onCharacteristicChange( - service.characteristics - ) - - allCharacteristics.map((characteristic) => { - const cKey = characteristic.constructor.name - - supported.push(cKey) + log.trace('Evaluating value:') + log.trace(config.characteristicProperties) + log.trace('Evaluated as:') + log.trace(JSON.stringify(characteristicProperties)) - characteristic.on('get', node.onCharacteristicGet) - characteristic.on('set', node.onCharacteristicSet) - characteristic.on('change', node.onCharacteristicChange) + // Configure custom characteristic properties + for (const key in characteristicProperties) { + if (!characteristicProperties.hasOwnProperty(key)) continue - //TODO: Remove when persist table is here - //Allow for negative temperatures - if (characteristic.displayName === 'Current Temperature') { - characteristic.props.minValue = -100 - } - }) + const characteristic = service.getCharacteristic( + // @ts-ignore + Characteristic[key] + ) - // Removing accidental duplicate values - return [...new Set(supported)] + if (characteristic && characteristicProperties[key]) { + log.debug(`Found Characteristic Properties for ${key}`) + characteristic.setProps(characteristicProperties[key]) + } + } } - return { - load: load, - subscribeAndGetSupported: subscribeAndGetSupported, - } + return characteristicProperties + } + + const subscribeAndGetSupported = function (service: Service) { + const supported: string[] = [] + + const allCharacteristics = service.characteristics.concat( + service.optionalCharacteristics + ) + + // Listen to characteristic events and store the listener functions + // to be able to remove them later + node.onCharacteristicGet = ServiceUtils.onCharacteristicGet( + service.characteristics + ) + node.onCharacteristicSet = ServiceUtils.onCharacteristicSet( + service.characteristics + ) + node.onCharacteristicChange = ServiceUtils.onCharacteristicChange( + service.characteristics + ) + + allCharacteristics.map((characteristic) => { + const cKey = characteristic.constructor.name + + supported.push(cKey) + + characteristic.on('get', node.onCharacteristicGet) + characteristic.on('set', node.onCharacteristicSet) + characteristic.on('change', node.onCharacteristicChange) + + //TODO: Remove when persist table is here + //Allow for negative temperatures + if (characteristic.displayName === 'Current Temperature') { + characteristic.props.minValue = -100 + } + }) + + // Removing accidental duplicate values + return [...new Set(supported)] + } + + return { + load: load, + subscribeAndGetSupported: subscribeAndGetSupported + } } diff --git a/src/lib/utils/NodeStatusUtils.ts b/src/lib/utils/NodeStatusUtils.ts index 44d77ce8..269a109f 100644 --- a/src/lib/utils/NodeStatusUtils.ts +++ b/src/lib/utils/NodeStatusUtils.ts @@ -10,7 +10,7 @@ type StatusType = 'NO_RESPONSE' | 'MSG' const DEFAULT_STATUS_TYPE: StatusType = 'MSG' type NodeStatusWithType = NodeStatus & { - type?: StatusType + type?: StatusType } type Status = string | NodeStatusWithType @@ -18,67 +18,67 @@ type Status = string | NodeStatusWithType * Utils for setting and clearing status of a node in Node-RED flow Editor */ export class NodeStatusUtils { - protected lastStatusId?: number - protected lastStatusType?: StatusType + protected lastStatusId?: number + protected lastStatusType?: StatusType - constructor(private node: Pick) {} + constructor(private node: Pick) {} - /** - * Set the status - * @param status - status to be displayed - * @param timeout - if provided will clear the status after the timeout - */ - setStatus(status: Status, timeout?: number): number { - this.node.status(status) + /** + * Set the status + * @param status - status to be displayed + * @param timeout - if provided will clear the status after the timeout + */ + setStatus(status: Status, timeout?: number): number { + this.node.status(status) - const newStatusId = new Date().getTime() - this.lastStatusId = newStatusId + const newStatusId = new Date().getTime() + this.lastStatusId = newStatusId - if (typeof status !== 'string') { - this.lastStatusType = status.type ?? DEFAULT_STATUS_TYPE - } else { - this.lastStatusType = DEFAULT_STATUS_TYPE - } - - if (timeout) { - this.clearStatus(newStatusId, timeout) - } + if (typeof status !== 'string') { + this.lastStatusType = status.type ?? DEFAULT_STATUS_TYPE + } else { + this.lastStatusType = DEFAULT_STATUS_TYPE + } - return newStatusId + if (timeout) { + this.clearStatus(newStatusId, timeout) } - /** - * Clear the status by type, only if last status type is the same as the type provided - * @param type - type of status to be cleared - */ - clearStatusByType(type: StatusType): void { - if (this.lastStatusType === type) { - this.clearStatus() - } + return newStatusId + } + + /** + * Clear the status by type, only if last status type is the same as the type provided + * @param type - type of status to be cleared + */ + clearStatusByType(type: StatusType): void { + if (this.lastStatusType === type) { + this.clearStatus() } + } - /** - * Clear the status - * @param statusId - if provided will clear the status only if the statusId is the same as the last statusId - * @param timeout - if provided will clear the status after the timeout - */ - clearStatus(statusId?: number, timeout?: number): void { - if (statusId !== undefined) { - if (statusId === this.lastStatusId) { - if (timeout) { - setTimeout( - function (nodeStatusUtil: NodeStatusUtils) { - nodeStatusUtil.clearStatus(statusId) - }, - timeout, - this - ) - } else { - this.setStatus('') - } - } + /** + * Clear the status + * @param statusId - if provided will clear the status only if the statusId is the same as the last statusId + * @param timeout - if provided will clear the status after the timeout + */ + clearStatus(statusId?: number, timeout?: number): void { + if (statusId !== undefined) { + if (statusId === this.lastStatusId) { + if (timeout) { + setTimeout( + function (nodeStatusUtil: NodeStatusUtils) { + nodeStatusUtil.clearStatus(statusId) + }, + timeout, + this + ) } else { - this.setStatus('') + this.setStatus('') } + } + } else { + this.setStatus('') } + } } diff --git a/src/lib/utils/ServiceUtils.ts b/src/lib/utils/ServiceUtils.ts index bf7833bd..1d19a2f8 100644 --- a/src/lib/utils/ServiceUtils.ts +++ b/src/lib/utils/ServiceUtils.ts @@ -1,19 +1,19 @@ import * as util from 'node:util' import { - Accessory, - ActiveAdaptiveLightingTransition, - AdaptiveLightingController, - AdaptiveLightingControllerMode, - AdaptiveLightingOptions, - Characteristic, - CharacteristicChange, - CharacteristicGetCallback, - CharacteristicSetCallback, - CharacteristicValue, - HAPStatus, - HapStatusError, - Service, + Accessory, + ActiveAdaptiveLightingTransition, + AdaptiveLightingController, + AdaptiveLightingControllerMode, + AdaptiveLightingOptions, + Characteristic, + CharacteristicChange, + CharacteristicGetCallback, + CharacteristicSetCallback, + CharacteristicValue, + HAPStatus, + HapStatusError, + Service } from '@homebridge/hap-nodejs' import { HAPConnection } from '@homebridge/hap-nodejs/dist/lib/util/eventedhttp' import { logger } from '@nrchkb/logger' @@ -23,549 +23,530 @@ import HAPServiceConfigType from '../types/HAPServiceConfigType' import HAPServiceNodeType from '../types/HAPServiceNodeType' module.exports = function (node: HAPServiceNodeType) { - const log = logger('NRCHKB', 'ServiceUtils', node.config.name, node) + const log = logger('NRCHKB', 'ServiceUtils', node.config.name, node) - const HapNodeJS = require('@homebridge/hap-nodejs') - const Service = HapNodeJS.Service - const Characteristic = HapNodeJS.Characteristic + const HapNodeJS = require('@homebridge/hap-nodejs') + const Service = HapNodeJS.Service + const Characteristic = HapNodeJS.Characteristic - const NO_RESPONSE_MSG = 'NO_RESPONSE' + const NO_RESPONSE_MSG = 'NO_RESPONSE' - const prepareHapData = (context?: any, connection?: HAPConnection) => { - const hap: { [key: string]: any } = {} + const prepareHapData = (context?: any, connection?: HAPConnection) => { + const hap: { [key: string]: any } = {} - if (connection) { - hap.session = { - sessionID: connection.sessionID, - username: connection.username, - remoteAddress: connection.remoteAddress, - localAddress: connection.localAddress, - httpPort: connection.remotePort, - } + if (connection) { + hap.session = { + sessionID: connection.sessionID, + username: connection.username, + remoteAddress: connection.remoteAddress, + localAddress: connection.localAddress, + httpPort: connection.remotePort + } - hap.context = {} - } + hap.context = {} + } - if (context) { - hap.context = context - } + if (context) { + hap.context = context + } + + return hap + } + + const onCharacteristicGet = function ( + this: Characteristic, + callback: CharacteristicGetCallback, + context: any, + connection?: HAPConnection + ) { + log.debug( + `onCharacteristicGet with status: ${this.statusCode}, value: ${ + this.value + }, reachability is ${ + (node.parentNode ?? node).reachable + } with context ${util.inspect( + context + )} on connection ${connection?.sessionID}` + ) + + if (callback) { + try { + callback( + (node.parentNode ?? node).reachable + ? null + : new HapStatusError(HAPStatus.SERVICE_COMMUNICATION_FAILURE), + this.value + ) + } catch (_) {} + } + } + + const onValueChange = function ( + this: Characteristic, + allCharacteristics: Characteristic[], + outputNumber: number, + { oldValue, newValue, context }: any, + connection?: HAPConnection + ) { + const topic = node.config.topic ? node.config.topic : node.topic_in + const msg: { + payload: { [key: string]: any } + hap: any + name?: string + topic: string + } = { payload: {}, hap: {}, name: node.name, topic: topic } + const key = this.constructor.name + + msg.payload[key] = newValue + + msg.hap = prepareHapData(context, connection) + msg.hap.allChars = allCharacteristics.reduce<{ [key: string]: any }>( + (allChars, singleChar) => { + const cKey = singleChar.constructor.name + allChars[cKey] = singleChar.value + return allChars + }, + {} + ) + + if (oldValue !== undefined) { + msg.hap.oldValue = oldValue + } + + msg.hap.reachable = node.reachable ?? node.parentNode?.reachable + + if (msg.hap.reachable === false) { + ;[node, ...(node.childNodes ?? [])].forEach((n) => + n.nodeStatusUtils.setStatus({ + fill: 'red', + shape: 'ring', + text: 'Not reachable', + type: 'NO_RESPONSE' + }) + ) + } else { + msg.hap.newValue = newValue + + node.nodeStatusUtils.setStatus( + { + fill: 'yellow', + shape: 'dot', + text: key + ': ' + newValue + }, + 3000 + ) - return hap + node.childNodes?.forEach((n) => + n.nodeStatusUtils.clearStatusByType('NO_RESPONSE') + ) + node.parentNode?.nodeStatusUtils.clearStatusByType('NO_RESPONSE') } - const onCharacteristicGet = function ( - this: Characteristic, - callback: CharacteristicGetCallback, - context: any, - connection?: HAPConnection + log.debug(`${node.name} received ${key} : ${newValue}`) + + if (connection || context || node.hostNode.config.allowMessagePassthrough) { + if (outputNumber === 0) { + node.send(msg) + } else if (outputNumber === 1) { + node.send([null, msg]) + } + } + } + + const onCharacteristicSet = (allCharacteristics: Characteristic[]) => + function ( + this: Characteristic, + newValue: CharacteristicValue, + callback: CharacteristicSetCallback, + context: any, + connection?: HAPConnection ) { - log.debug( - `onCharacteristicGet with status: ${this.statusCode}, value: ${ - this.value - }, reachability is ${ - (node.parentNode ?? node).reachable - } with context ${util.inspect( - context + log.debug( + `onCharacteristicSet with status: ${this.statusCode}, value: ${ + this.value + }, reachability is ${(node.parentNode ?? node).reachable} + with context ${util.inspect( + context )} on connection ${connection?.sessionID}` - ) + ) + try { if (callback) { - try { - callback( - (node.parentNode ?? node).reachable - ? null - : new HapStatusError( - HAPStatus.SERVICE_COMMUNICATION_FAILURE - ), - this.value - ) - } catch (_) {} + callback( + (node.parentNode ?? node).reachable + ? null + : new HapStatusError(HAPStatus.SERVICE_COMMUNICATION_FAILURE) + ) } + } catch (_) {} + + onValueChange.call( + this, + allCharacteristics, + 1, + { + newValue, + context + }, + connection + ) } - const onValueChange = function ( - this: Characteristic, - allCharacteristics: Characteristic[], - outputNumber: number, - { oldValue, newValue, context }: any, - connection?: HAPConnection - ) { - const topic = node.config.topic ? node.config.topic : node.topic_in - const msg: { - payload: { [key: string]: any } - hap: any - name?: string - topic: string - } = { payload: {}, hap: {}, name: node.name, topic: topic } - const key = this.constructor.name - - msg.payload[key] = newValue - - msg.hap = prepareHapData(context, connection) - msg.hap.allChars = allCharacteristics.reduce<{ [key: string]: any }>( - (allChars, singleChar) => { - const cKey = singleChar.constructor.name - allChars[cKey] = singleChar.value - return allChars - }, - {} + const onCharacteristicChange = (allCharacteristics: Characteristic[]) => + function (this: Characteristic, change: CharacteristicChange) { + const { oldValue, newValue, context, originator, reason } = change + + log.debug( + `onCharacteristicChange with reason: ${reason}, oldValue: ${oldValue}, newValue: ${newValue}, reachability is ${ + (node.parentNode ?? node).reachable + } + with context ${util.inspect( + context + )} on connection ${originator?.sessionID}` + ) + + if (oldValue != newValue) { + onValueChange.call( + this, + allCharacteristics, + 0, + { + oldValue, + newValue, + context + }, + originator ) + } + } - if (oldValue !== undefined) { - msg.hap.oldValue = oldValue - } + const onInput = function (msg: Record) { + if (msg.payload) { + // payload must be an object + const type = typeof msg.payload + + if (type !== 'object') { + log.error(`Invalid payload type: ${type}`) + return + } + } else { + log.error('Invalid message (payload missing)') + return + } - msg.hap.reachable = node.reachable ?? node.parentNode?.reachable - - if (msg.hap.reachable === false) { - ;[node, ...(node.childNodes ?? [])].forEach((n) => - n.nodeStatusUtils.setStatus({ - fill: 'red', - shape: 'ring', - text: 'Not reachable', - type: 'NO_RESPONSE', - }) - ) - } else { - msg.hap.newValue = newValue - - node.nodeStatusUtils.setStatus( - { - fill: 'yellow', - shape: 'dot', - text: key + ': ' + newValue, - }, - 3000 - ) - - node.childNodes?.forEach((n) => - n.nodeStatusUtils.clearStatusByType('NO_RESPONSE') - ) - node.parentNode?.nodeStatusUtils.clearStatusByType('NO_RESPONSE') - } + const topic = node.config.topic ?? node.name + if (node.config.filter && msg.topic !== topic) { + log.debug( + "msg.topic doesn't match configured value and filter is enabled. Dropping message." + ) + return + } - log.debug(`${node.name} received ${key} : ${newValue}`) + let context: any = null + if (msg.payload.Context) { + context = msg.payload.Context + delete msg.payload.Context + } + + node.topic_in = msg.topic ?? '' + Object.keys(msg.payload).map((key: string) => { + if (node.supported.indexOf(key) < 0) { if ( - connection || - context || - node.hostNode.config.allowMessagePassthrough + key === 'AdaptiveLightingController' && + node.adaptiveLightingController ) { - if (outputNumber === 0) { - node.send(msg) - } else if (outputNumber === 1) { - node.send([null, msg]) - } - } - } + const value = msg.payload?.[key] + const event = value?.event - const onCharacteristicSet = (allCharacteristics: Characteristic[]) => - function ( - this: Characteristic, - newValue: CharacteristicValue, - callback: CharacteristicSetCallback, - context: any, - connection?: HAPConnection - ) { - log.debug( - `onCharacteristicSet with status: ${this.statusCode}, value: ${ - this.value - }, reachability is ${(node.parentNode ?? node).reachable} - with context ${util.inspect( - context - )} on connection ${connection?.sessionID}` - ) - - try { - if (callback) { - callback( - (node.parentNode ?? node).reachable - ? null - : new HapStatusError( - HAPStatus.SERVICE_COMMUNICATION_FAILURE - ) - ) - } - } catch (_) {} - - onValueChange.call( - this, - allCharacteristics, - 1, - { - newValue, - context, - }, - connection - ) + if (event === 'disable') { + node.adaptiveLightingController?.disableAdaptiveLighting() + } + } else { + log.error( + `Instead of '${key}' try one of these characteristics: '${node.supported.join( + "', '" + )}'` + ) } + } else { + const value = msg.payload?.[key] - const onCharacteristicChange = (allCharacteristics: Characteristic[]) => - function (this: Characteristic, change: CharacteristicChange) { - const { oldValue, newValue, context, originator, reason } = change + const parentNode = node.parentNode ?? node + parentNode.reachable = value !== NO_RESPONSE_MSG - log.debug( - `onCharacteristicChange with reason: ${reason}, oldValue: ${oldValue}, newValue: ${newValue}, reachability is ${ - (node.parentNode ?? node).reachable - } - with context ${util.inspect( - context - )} on connection ${originator?.sessionID}` - ) - - if (oldValue != newValue) { - onValueChange.call( - this, - allCharacteristics, - 0, - { - oldValue, - newValue, - context, - }, - originator - ) - } - } - - const onInput = function (msg: Record) { - if (msg.payload) { - // payload must be an object - const type = typeof msg.payload + const characteristic = node.service.getCharacteristic( + Characteristic[key] + ) - if (type !== 'object') { - log.error(`Invalid payload type: ${type}`) - return - } + if (context !== null) { + characteristic.setValue(value, context) } else { - log.error('Invalid message (payload missing)') - return - } - - const topic = node.config.topic ?? node.name - if (node.config.filter && msg.topic !== topic) { - log.debug( - "msg.topic doesn't match configured value and filter is enabled. Dropping message." - ) - return + characteristic.setValue(value) } + } + }) + } + + const onClose = function (removed: boolean, done: () => void) { + const characteristics = node.service.characteristics.concat( + node.service.optionalCharacteristics + ) + + characteristics.forEach(function (characteristic) { + // cleanup all node specific listeners + characteristic.removeListener('get', node.onCharacteristicGet) + characteristic.removeListener('set', node.onCharacteristicSet) + characteristic.removeListener('change', node.onCharacteristicChange) + }) + + if (node.config.isParent) { + // remove identify listener to prevent errors with undefined values + node.accessory.removeListener('identify', node.onIdentify) + } - let context: any = null - if (msg.payload.Context) { - context = msg.payload.Context - delete msg.payload.Context - } + if (removed) { + // This node has been deleted + if (node.config.isParent) { + // remove accessory from bridge + node.hostNode.host.removeBridgedAccessories([node.accessory]) + node.accessory.destroy() + } else { + // only remove the service if it is not a parent + node.accessory.removeService(node.service) + node.parentService.removeLinkedService(node.service) + } + } - node.topic_in = msg.topic ?? '' - - Object.keys(msg.payload).map((key: string) => { - if (node.supported.indexOf(key) < 0) { - if ( - key === 'AdaptiveLightingController' && - node.adaptiveLightingController - ) { - const value = msg.payload?.[key] - const event = value?.event - - if (event === 'disable') { - node.adaptiveLightingController?.disableAdaptiveLighting() - } - } else { - log.error( - `Instead of '${key}' try one of these characteristics: '${node.supported.join( - "', '" - )}'` - ) - } - } else { - const value = msg.payload?.[key] - - const parentNode = node.parentNode ?? node - parentNode.reachable = value !== NO_RESPONSE_MSG - - const characteristic = node.service.getCharacteristic( - Characteristic[key] - ) - - if (context !== null) { - characteristic.setValue(value, context) - } else { - characteristic.setValue(value) - } - } - }) + done() + } + + const getOrCreate = function ( + accessory: Accessory, + serviceInformation: { + name: string + UUID: string + serviceName: string + config: HAPServiceConfigType + }, + parentService: Service + ) { + const newService = new Service[serviceInformation.serviceName]( + serviceInformation.name, + serviceInformation.UUID + ) + log.debug(`Looking for service with UUID ${serviceInformation.UUID} ...`) + + // search for a service with the same subtype + let service: Service | undefined = accessory.services.find((service) => { + return newService.subtype === service.subtype + }) + + if (service && newService.UUID !== service.UUID) { + // if the UUID and therefore the type changed, the whole service + // will be replaced + log.debug('... service type changed! Removing the old service.') + accessory.removeService(service) + service = undefined } - const onClose = function (removed: boolean, done: () => void) { - const characteristics = node.service.characteristics.concat( - node.service.optionalCharacteristics - ) + if (!service) { + // if no matching service was found or the type changed, then a new + // service will be added + log.debug( + `... didn't find it. Adding new ${serviceInformation.serviceName} service.` + ) + + if (serviceInformation.serviceName === 'CameraControl') { + configureCameraSource(accessory, newService, serviceInformation.config) + service = newService + } else { + service = accessory.addService(newService) + } + } else { + // if a service with the same UUID and subtype was found it will + // be updated and used + log.debug('... found it! Updating it.') + service + .getCharacteristic(Characteristic.Name) + .setValue(serviceInformation.name) + } - characteristics.forEach(function (characteristic) { - // cleanup all node specific listeners - characteristic.removeListener('get', node.onCharacteristicGet) - characteristic.removeListener('set', node.onCharacteristicSet) - characteristic.removeListener('change', node.onCharacteristicChange) - }) + if (parentService) { + if (serviceInformation.serviceName === 'CameraControl') { + //We don't add or link it since configureCameraSource do this already. + log.debug('... and adding service to accessory.') + } else if (service) { + log.debug('... and linking service to parent.') + parentService.addLinkedService(service) + } + } - if (node.config.isParent) { - // remove identify listener to prevent errors with undefined values - node.accessory.removeListener('identify', node.onIdentify) - } + return service + } - if (removed) { - // This node has been deleted - if (node.config.isParent) { - // remove accessory from bridge - node.hostNode.host.removeBridgedAccessories([node.accessory]) - node.accessory.destroy() - } else { - // only remove the service if it is not a parent - node.accessory.removeService(node.service) - node.parentService.removeLinkedService(node.service) - } - } + const configureCameraSource = function ( + _accessory: Accessory, + _service: Service, + config: HAPServiceConfigType + ) { + if (config.cameraConfigSource) { + log.debug('Configuring Camera Source') - done() + if (!config.cameraConfigVideoProcessor) { + log.error( + 'Missing configuration for CameraControl: videoProcessor cannot be empty!' + ) + } else { + // Use of deprecated method to be replaced with new Camera API + // TODO: https://github.com/homebridge/HAP-NodeJS/blob/latest/src/accessories/Camera_accessory.ts + // accessory.configureCameraSource( + // new CameraSource(service, config, node) + // ) + } + } else { + log.error('Missing configuration for CameraControl.') } + } - const getOrCreate = function ( - accessory: Accessory, - serviceInformation: { - name: string - UUID: string - serviceName: string - config: HAPServiceConfigType - }, - parentService: Service - ) { - const newService = new Service[serviceInformation.serviceName]( - serviceInformation.name, - serviceInformation.UUID - ) - log.debug( - `Looking for service with UUID ${serviceInformation.UUID} ...` - ) + const waitForParent = () => { + log.debug('Waiting for Parent Service') - // search for a service with the same subtype - let service: Service | undefined = accessory.services.find( - (service) => { - return newService.subtype === service.subtype - } - ) + return new Promise((resolve) => { + node.nodeStatusUtils.setStatus({ + fill: 'blue', + shape: 'dot', + text: 'Waiting for Parent Service' + }) - if (service && newService.UUID !== service.UUID) { - // if the UUID and therefore the type changed, the whole service - // will be replaced - log.debug('... service type changed! Removing the old service.') - accessory.removeService(service) - service = undefined - } + const checkAndWait = () => { + const parentNode: HAPServiceNodeType = node.RED.nodes.getNode( + node.config.parentService + ) as HAPServiceNodeType - if (!service) { - // if no matching service was found or the type changed, then a new - // service will be added - log.debug( - `... didn't find it. Adding new ${serviceInformation.serviceName} service.` - ) - - if (serviceInformation.serviceName === 'CameraControl') { - configureCameraSource( - accessory, - newService, - serviceInformation.config - ) - service = newService - } else { - service = accessory.addService(newService) - } + if (parentNode && parentNode.configured) { + resolve(parentNode) } else { - // if a service with the same UUID and subtype was found it will - // be updated and used - log.debug('... found it! Updating it.') - service - .getCharacteristic(Characteristic.Name) - .setValue(serviceInformation.name) - } - - if (parentService) { - if (serviceInformation.serviceName === 'CameraControl') { - //We don't add or link it since configureCameraSource do this already. - log.debug('... and adding service to accessory.') - } else if (service) { - log.debug('... and linking service to parent.') - parentService.addLinkedService(service) - } + setTimeout(checkAndWait, 1000) } - - return service + } + checkAndWait() + }).catch((error) => { + log.error(`Waiting for Parent Service failed due to: ${error}`) + throw new NRCHKBError(error) + }) + } + + const handleWaitForSetup = ( + config: HAPServiceConfigType, + msg: Record, + resolve: (newConfig: HAPServiceConfigType) => void + ) => { + if (node.setupDone) { + return } - const configureCameraSource = function ( - _accessory: Accessory, - _service: Service, - config: HAPServiceConfigType + if ( + msg.hasOwnProperty('payload') && + msg.payload.hasOwnProperty('nrchkb') && + msg.payload.nrchkb.hasOwnProperty('setup') ) { - if (config.cameraConfigSource) { - log.debug('Configuring Camera Source') - - if (!config.cameraConfigVideoProcessor) { - log.error( - 'Missing configuration for CameraControl: videoProcessor cannot be empty!' - ) - } else { - // Use of deprecated method to be replaced with new Camera API - // TODO: https://github.com/homebridge/HAP-NodeJS/blob/latest/src/accessories/Camera_accessory.ts - // accessory.configureCameraSource( - // new CameraSource(service, config, node) - // ) - } - } else { - log.error('Missing configuration for CameraControl.') - } - } + node.setupDone = true - const waitForParent = () => { - log.debug('Waiting for Parent Service') - - return new Promise((resolve) => { - node.nodeStatusUtils.setStatus({ - fill: 'blue', - shape: 'dot', - text: 'Waiting for Parent Service', - }) - - const checkAndWait = () => { - const parentNode: HAPServiceNodeType = node.RED.nodes.getNode( - node.config.parentService - ) as HAPServiceNodeType - - if (parentNode && parentNode.configured) { - resolve(parentNode) - } else { - setTimeout(checkAndWait, 1000) - } - } - checkAndWait() - }).catch((error) => { - log.error(`Waiting for Parent Service failed due to: ${error}`) - throw new NRCHKBError(error) - }) - } + const newConfig = { + ...config, + ...msg.payload.nrchkb.setup + } - const handleWaitForSetup = ( - config: HAPServiceConfigType, - msg: Record, - resolve: (newConfig: HAPServiceConfigType) => void - ) => { - if (node.setupDone) { - return - } + node.removeListener('input', node.handleWaitForSetup) - if ( - msg.hasOwnProperty('payload') && - msg.payload.hasOwnProperty('nrchkb') && - msg.payload.nrchkb.hasOwnProperty('setup') - ) { - node.setupDone = true + resolve(newConfig) + } else { + log.error( + 'Invalid message (required {"payload":{"nrchkb":{"setup":{}}}})' + ) + } + } - const newConfig = { - ...config, - ...msg.payload.nrchkb.setup, - } + const configureAdaptiveLightning = () => { + if ( + node.service.UUID === Service.Lightbulb.UUID && + node.config.adaptiveLightingOptionsEnable + ) { + try { + node.service.getCharacteristic(Characteristic.Brightness) + node.service.getCharacteristic(Characteristic.ColorTemperature) + + const options: AdaptiveLightingOptions = { + controllerMode: node.config.adaptiveLightingOptionsMode + ? +node.config.adaptiveLightingOptionsMode + : AdaptiveLightingControllerMode.AUTOMATIC, + customTemperatureAdjustment: node.config + .adaptiveLightingOptionsCustomTemperatureAdjustment + ? +node.config.adaptiveLightingOptionsCustomTemperatureAdjustment + : undefined + } - node.removeListener('input', node.handleWaitForSetup) + log.trace(`Configuring Adaptive Lighting with options: ${options}`) - resolve(newConfig) - } else { - log.error( - 'Invalid message (required {"payload":{"nrchkb":{"setup":{}}}})' - ) - } - } + const adaptiveLightingController = new AdaptiveLightingController( + node.service, + options + ) - const configureAdaptiveLightning = () => { - if ( - node.service.UUID === Service.Lightbulb.UUID && - node.config.adaptiveLightingOptionsEnable - ) { - try { - node.service.getCharacteristic(Characteristic.Brightness) - node.service.getCharacteristic(Characteristic.ColorTemperature) - - const options: AdaptiveLightingOptions = { - controllerMode: node.config.adaptiveLightingOptionsMode - ? +node.config.adaptiveLightingOptionsMode - : AdaptiveLightingControllerMode.AUTOMATIC, - customTemperatureAdjustment: node.config - .adaptiveLightingOptionsCustomTemperatureAdjustment - ? +node.config - .adaptiveLightingOptionsCustomTemperatureAdjustment - : undefined, - } - - log.trace( - `Configuring Adaptive Lighting with options: ${options}` - ) - - const adaptiveLightingController = - new AdaptiveLightingController(node.service, options) - - adaptiveLightingController.on('update', () => { - const activeAdaptiveLightingTransition: Partial = - { - transitionStartMillis: - adaptiveLightingController.getAdaptiveLightingStartTimeOfTransition(), - timeMillisOffset: - adaptiveLightingController.getAdaptiveLightingTimeOffset(), - transitionCurve: - adaptiveLightingController.getAdaptiveLightingTransitionCurve(), - brightnessAdjustmentRange: - adaptiveLightingController.getAdaptiveLightingBrightnessMultiplierRange(), - updateInterval: - adaptiveLightingController.getAdaptiveLightingUpdateInterval(), - notifyIntervalThreshold: - adaptiveLightingController.getAdaptiveLightingNotifyIntervalThreshold(), - } - node.send({ - payload: { - AdaptiveLightingController: { - event: 'update', - data: activeAdaptiveLightingTransition, - }, - }, - }) - }) - adaptiveLightingController.on('disable', () => { - node.send({ - payload: { - AdaptiveLightingController: { - event: 'disable', - }, - }, - }) - }) - - node.accessory.configureController(adaptiveLightingController) - - node.adaptiveLightingController = adaptiveLightingController - } catch (error) { - log.error( - `Failed to configure Adaptive Lightning due to ${error}` - ) + adaptiveLightingController.on('update', () => { + const activeAdaptiveLightingTransition: Partial = + { + transitionStartMillis: + adaptiveLightingController.getAdaptiveLightingStartTimeOfTransition(), + timeMillisOffset: + adaptiveLightingController.getAdaptiveLightingTimeOffset(), + transitionCurve: + adaptiveLightingController.getAdaptiveLightingTransitionCurve(), + brightnessAdjustmentRange: + adaptiveLightingController.getAdaptiveLightingBrightnessMultiplierRange(), + updateInterval: + adaptiveLightingController.getAdaptiveLightingUpdateInterval(), + notifyIntervalThreshold: + adaptiveLightingController.getAdaptiveLightingNotifyIntervalThreshold() } - } - } + node.send({ + payload: { + AdaptiveLightingController: { + event: 'update', + data: activeAdaptiveLightingTransition + } + } + }) + }) + adaptiveLightingController.on('disable', () => { + node.send({ + payload: { + AdaptiveLightingController: { + event: 'disable' + } + } + }) + }) + + node.accessory.configureController(adaptiveLightingController) - return { - getOrCreate, - onCharacteristicGet, - onCharacteristicSet, - onCharacteristicChange, - onInput, - onClose, - waitForParent, - handleWaitForSetup, - configureAdaptiveLightning, + node.adaptiveLightingController = adaptiveLightingController + } catch (error) { + log.error(`Failed to configure Adaptive Lightning due to ${error}`) + } } + } + + return { + getOrCreate, + onCharacteristicGet, + onCharacteristicSet, + onCharacteristicChange, + onInput, + onClose, + waitForParent, + handleWaitForSetup, + configureAdaptiveLightning + } } diff --git a/src/lib/utils/ServiceUtils2.ts b/src/lib/utils/ServiceUtils2.ts index 23d53255..cbc0ac5f 100644 --- a/src/lib/utils/ServiceUtils2.ts +++ b/src/lib/utils/ServiceUtils2.ts @@ -1,18 +1,18 @@ import { - Accessory, - Characteristic, - CharacteristicChange, - CharacteristicEventTypes, - CharacteristicGetCallback, - CharacteristicSetCallback, - CharacteristicValue, - HAPStatus, - HapStatusError, - Service, + Accessory, + Characteristic, + CharacteristicChange, + CharacteristicEventTypes, + CharacteristicGetCallback, + CharacteristicSetCallback, + CharacteristicValue, + HAPStatus, + HapStatusError, + Service } from '@homebridge/hap-nodejs' import { - HAPConnection, - HAPUsername, + HAPConnection, + HAPUsername } from '@homebridge/hap-nodejs/dist/lib/util/eventedhttp' import { SessionIdentifier } from '@homebridge/hap-nodejs/dist/types' import { logger } from '@nrchkb/logger' @@ -23,524 +23,504 @@ import HAPService2ConfigType from '../types/HAPService2ConfigType' import HAPService2NodeType from '../types/HAPService2NodeType' module.exports = function (node: HAPService2NodeType) { - const log = logger('NRCHKB', 'ServiceUtils2', node.config.name, node) + const log = logger('NRCHKB', 'ServiceUtils2', node.config.name, node) + + const ServiceUtilsLegacy = require('./ServiceUtils')(node) + + const HapNodeJS = require('@homebridge/hap-nodejs') + const Service = HapNodeJS.Service + const Characteristic = HapNodeJS.Characteristic + + const NO_RESPONSE_MSG = 'NO_RESPONSE' + + type HAPServiceNodeEvent = { + name: CharacteristicEventTypes // Event type + context?: { + callbackID?: string // ID used to update Characteristic value with get event + key?: string // Characteristic key + reason?: string + } & Record // Additional event data provided by event caller + } + + type HAPServiceMessage = { + payload?: { [key: string]: any } + hap?: { + oldValue?: any + newValue?: any + reachable?: boolean + event?: HAPServiceNodeEvent + session?: { + sessionID?: SessionIdentifier + username?: HAPUsername + remoteAddress?: string + localAddress?: string + httpPort?: number + } + allChars: { [key: string]: any } + } + name?: string + topic?: string + } + + const output = function ( + this: Characteristic, + allCharacteristics: Characteristic[], + event: CharacteristicEventTypes | HAPServiceNodeEvent, + { oldValue, newValue }: any, + connection?: HAPConnection + ) { + const eventObject = typeof event === 'object' ? event : { name: event } + + log.debug( + `${eventObject.name} event, oldValue: ${oldValue}, newValue: ${newValue}, connection ${connection?.sessionID}` + ) + + const msg: HAPServiceMessage = { + name: node.name, + topic: node.config.topic ? node.config.topic : node.topic_in + } + msg.payload = {} + msg.hap = { + event: eventObject, + allChars: allCharacteristics.reduce<{ [key: string]: any }>( + (allChars, singleChar) => { + const cKey = singleChar.constructor.name + allChars[cKey] = singleChar.value + return allChars + }, + {} + ), + oldValue + } - const ServiceUtilsLegacy = require('./ServiceUtils')(node) + const key = this.constructor.name - const HapNodeJS = require('@homebridge/hap-nodejs') - const Service = HapNodeJS.Service - const Characteristic = HapNodeJS.Characteristic + msg.hap.reachable = node.reachable ?? node.parentNode?.reachable - const NO_RESPONSE_MSG = 'NO_RESPONSE' + if (msg.hap.reachable === false) { + ;[node, ...(node.childNodes ?? [])].forEach((n) => + n.nodeStatusUtils.setStatus({ + fill: 'red', + shape: 'ring', + text: 'Not reachable', + type: 'NO_RESPONSE' + }) + ) + } else { + msg.hap.newValue = newValue + + node.nodeStatusUtils.setStatus( + { + fill: 'yellow', + shape: 'dot', + text: `[${eventObject.name}] ${key}${ + newValue != undefined ? `: ${newValue}` : '' + }` + }, + 3000 + ) - type HAPServiceNodeEvent = { - name: CharacteristicEventTypes // Event type - context?: { - callbackID?: string // ID used to update Characteristic value with get event - key?: string // Characteristic key - reason?: string - } & Record // Additional event data provided by event caller + node.childNodes?.forEach((n) => + n.nodeStatusUtils.clearStatusByType('NO_RESPONSE') + ) + node.parentNode?.nodeStatusUtils.clearStatusByType('NO_RESPONSE') } - type HAPServiceMessage = { - payload?: { [key: string]: any } - hap?: { - oldValue?: any - newValue?: any - reachable?: boolean - event?: HAPServiceNodeEvent - session?: { - sessionID?: SessionIdentifier - username?: HAPUsername - remoteAddress?: string - localAddress?: string - httpPort?: number - } - allChars: { [key: string]: any } - } - name?: string - topic?: string + msg.payload[key] = newValue + + if (connection) { + msg.hap.session = { + sessionID: connection.sessionID, + username: connection.username, + remoteAddress: connection.remoteAddress, + localAddress: connection.localAddress, + httpPort: connection.remotePort + } } - const output = function ( - this: Characteristic, - allCharacteristics: Characteristic[], - event: CharacteristicEventTypes | HAPServiceNodeEvent, - { oldValue, newValue }: any, - connection?: HAPConnection + log.debug(`${node.name} received ${eventObject.name} ${key}: ${newValue}`) + + if (connection || node.hostNode.config.allowMessagePassthrough) { + node.send(msg) + } + } + + const onCharacteristicGet = (allCharacteristics: Characteristic[]) => + function ( + this: Characteristic, + callback: CharacteristicGetCallback, + _context: any, + connection?: HAPConnection ) { - const eventObject = typeof event === 'object' ? event : { name: event } + const characteristic = this + const oldValue = characteristic.value + + const delayedCallback = (value?: any) => { + const newValue = value ?? characteristic.value + if (callback) { + try { + callback( + (node.parentNode ?? node).reachable + ? null + : new HapStatusError(HAPStatus.SERVICE_COMMUNICATION_FAILURE), + newValue + ) + } catch (_) {} + } - log.debug( - `${eventObject.name} event, oldValue: ${oldValue}, newValue: ${newValue}, connection ${connection?.sessionID}` + output.call( + characteristic, + allCharacteristics, + { + name: CharacteristicEventTypes.GET, + context: { key: this.displayName } + }, + { oldValue, newValue }, + connection ) + } - const msg: HAPServiceMessage = { - name: node.name, - topic: node.config.topic ? node.config.topic : node.topic_in, - } - msg.payload = {} - msg.hap = { - event: eventObject, - allChars: allCharacteristics.reduce<{ [key: string]: any }>( - (allChars, singleChar) => { - const cKey = singleChar.constructor.name - allChars[cKey] = singleChar.value - return allChars - }, - {} - ), - oldValue, - } - - const key = this.constructor.name + if (node.config.useEventCallback) { + const callbackID = Storage.saveCallback({ + event: CharacteristicEventTypes.GET, + callback: delayedCallback + }) - msg.hap.reachable = node.reachable ?? node.parentNode?.reachable + log.debug( + `Registered callback ${callbackID} for Characteristic ${characteristic.displayName}` + ) - if (msg.hap.reachable === false) { - ;[node, ...(node.childNodes ?? [])].forEach((n) => - n.nodeStatusUtils.setStatus({ - fill: 'red', - shape: 'ring', - text: 'Not reachable', - type: 'NO_RESPONSE', - }) - ) - } else { - msg.hap.newValue = newValue - - node.nodeStatusUtils.setStatus( - { - fill: 'yellow', - shape: 'dot', - text: `[${eventObject.name}] ${key}${ - newValue != undefined ? `: ${newValue}` : '' - }`, - }, - 3000 - ) + output.call( + this, + allCharacteristics, + { + name: CharacteristicEventTypes.GET, + context: { callbackID, key: this.displayName } + }, + { oldValue }, + connection + ) + } else { + delayedCallback() + } + } - node.childNodes?.forEach((n) => - n.nodeStatusUtils.clearStatusByType('NO_RESPONSE') - ) - node.parentNode?.nodeStatusUtils.clearStatusByType('NO_RESPONSE') + const onCharacteristicSet = (allCharacteristics: Characteristic[]) => + function ( + this: Characteristic, + newValue: CharacteristicValue, + callback: CharacteristicSetCallback, + _context: any, + connection?: HAPConnection + ) { + try { + if (callback) { + callback( + (node.parentNode ?? node).reachable + ? null + : new HapStatusError(HAPStatus.SERVICE_COMMUNICATION_FAILURE) + ) } + } catch (_) {} + + output.call( + this, + allCharacteristics, + { + name: CharacteristicEventTypes.SET, + context: { key: this.displayName } + }, + { newValue }, + connection + ) + } - msg.payload[key] = newValue + const onCharacteristicChange = (allCharacteristics: Characteristic[]) => + function (this: Characteristic, change: CharacteristicChange) { + const { oldValue, newValue, context, originator, reason } = change + + if (oldValue != newValue) { + output.call( + this, + allCharacteristics, + { + name: CharacteristicEventTypes.CHANGE, + context: { reason, key: this.displayName } + }, + { oldValue, newValue, context }, + originator + ) + } + } - if (connection) { - msg.hap.session = { - sessionID: connection.sessionID, - username: connection.username, - remoteAddress: connection.remoteAddress, - localAddress: connection.localAddress, - httpPort: connection.remotePort, - } - } + const onInput = function (msg: HAPServiceMessage) { + if (msg.payload) { + // payload must be an object + const type = typeof msg.payload + + if (type !== 'object') { + log.error(`Invalid payload type: ${type}`) + return + } + } else { + log.error('Invalid message (payload missing)') + return + } - log.debug( - `${node.name} received ${eventObject.name} ${key}: ${newValue}` - ) + const topic = node.config.topic ?? node.name + if (node.config.filter && msg.topic !== topic) { + log.debug( + "msg.topic doesn't match configured value and filter is enabled. Dropping message." + ) + return + } - if (connection || node.hostNode.config.allowMessagePassthrough) { - node.send(msg) - } + let context: any = null + if (msg.payload.Context) { + context = msg.payload.Context + delete msg.payload.Context } - const onCharacteristicGet = (allCharacteristics: Characteristic[]) => - function ( - this: Characteristic, - callback: CharacteristicGetCallback, - _context: any, - connection?: HAPConnection + node.topic_in = msg.topic ?? '' + + Object.keys(msg.payload).map((key: string) => { + if (node.supported.indexOf(key) < 0) { + if (node.config.useEventCallback && Storage.uuid4Validate(key)) { + const callbackID = key + const callbackValue = msg.payload?.[key] + const eventCallback = Storage.loadCallback(callbackID) + + if (eventCallback) { + log.debug(`Calling ${eventCallback.event} callback ${callbackID}`) + eventCallback.callback(callbackValue) + } else { + log.error(`Callback ${callbackID} timeout`) + } + } else if ( + key === 'AdaptiveLightingController' && + node.adaptiveLightingController ) { - const characteristic = this - const oldValue = characteristic.value - - const delayedCallback = (value?: any) => { - const newValue = value ?? characteristic.value - if (callback) { - try { - callback( - (node.parentNode ?? node).reachable - ? null - : new HapStatusError( - HAPStatus.SERVICE_COMMUNICATION_FAILURE - ), - newValue - ) - } catch (_) {} - } - - output.call( - characteristic, - allCharacteristics, - { - name: CharacteristicEventTypes.GET, - context: { key: this.displayName }, - }, - { oldValue, newValue }, - connection - ) - } - - if (node.config.useEventCallback) { - const callbackID = Storage.saveCallback({ - event: CharacteristicEventTypes.GET, - callback: delayedCallback, - }) - - log.debug( - `Registered callback ${callbackID} for Characteristic ${characteristic.displayName}` - ) - - output.call( - this, - allCharacteristics, - { - name: CharacteristicEventTypes.GET, - context: { callbackID, key: this.displayName }, - }, - { oldValue }, - connection - ) - } else { - delayedCallback() - } - } + const value = msg.payload?.[key] + const event = value?.event - const onCharacteristicSet = (allCharacteristics: Characteristic[]) => - function ( - this: Characteristic, - newValue: CharacteristicValue, - callback: CharacteristicSetCallback, - _context: any, - connection?: HAPConnection - ) { - try { - if (callback) { - callback( - (node.parentNode ?? node).reachable - ? null - : new HapStatusError( - HAPStatus.SERVICE_COMMUNICATION_FAILURE - ) - ) - } - } catch (_) {} - - output.call( - this, - allCharacteristics, - { - name: CharacteristicEventTypes.SET, - context: { key: this.displayName }, - }, - { newValue }, - connection - ) + if (event === 'disable') { + node.adaptiveLightingController?.disableAdaptiveLighting() + } + } else { + log.error( + `Instead of '${key}' try one of these characteristics: '${node.supported.join( + "', '" + )}'` + ) } + } else { + const value = msg.payload?.[key] - const onCharacteristicChange = (allCharacteristics: Characteristic[]) => - function (this: Characteristic, change: CharacteristicChange) { - const { oldValue, newValue, context, originator, reason } = change - - if (oldValue != newValue) { - output.call( - this, - allCharacteristics, - { - name: CharacteristicEventTypes.CHANGE, - context: { reason, key: this.displayName }, - }, - { oldValue, newValue, context }, - originator - ) - } - } + const parentNode = node.parentNode ?? node + parentNode.reachable = value !== NO_RESPONSE_MSG - const onInput = function (msg: HAPServiceMessage) { - if (msg.payload) { - // payload must be an object - const type = typeof msg.payload + const characteristic = node.service.getCharacteristic( + Characteristic[key] + ) - if (type !== 'object') { - log.error(`Invalid payload type: ${type}`) - return - } + if (context !== null) { + characteristic.setValue(value, context) } else { - log.error('Invalid message (payload missing)') - return + characteristic.setValue(value) } + } + }) + } + + const onClose = function (removed: boolean, done: () => void) { + const characteristics = node.service.characteristics.concat( + node.service.optionalCharacteristics + ) + + characteristics.forEach(function (characteristic) { + // cleanup all node specific listeners + characteristic.removeListener('get', node.onCharacteristicGet) + characteristic.removeListener('set', node.onCharacteristicSet) + characteristic.removeListener('change', node.onCharacteristicChange) + }) + + if (node.config.isParent) { + // remove identify listener to prevent errors with undefined values + node.accessory.removeListener('identify', node.onIdentify) + } - const topic = node.config.topic ?? node.name - if (node.config.filter && msg.topic !== topic) { - log.debug( - "msg.topic doesn't match configured value and filter is enabled. Dropping message." - ) - return - } + if (removed) { + // This node has been deleted + if (node.config.isParent) { + // remove accessory from bridge + node.hostNode.host.removeBridgedAccessories([node.accessory]) + node.accessory.destroy() + } else { + // only remove the service if it is not a parent + node.accessory.removeService(node.service) + node.parentService.removeLinkedService(node.service) + } + } - let context: any = null - if (msg.payload.Context) { - context = msg.payload.Context - delete msg.payload.Context - } + done() + } + + const getOrCreate = function ( + accessory: Accessory, + serviceInformation: { + name: string + UUID: string + serviceName: string + config: HAPService2ConfigType + }, + parentService: Service + ) { + const newService = new Service[serviceInformation.serviceName]( + serviceInformation.name, + serviceInformation.UUID + ) + log.debug(`Looking for service with UUID ${serviceInformation.UUID} ...`) + + // search for a service with the same subtype + let service: Service | undefined = accessory.services.find((service) => { + return newService.subtype === service.subtype + }) + + if (service && newService.UUID !== service.UUID) { + // if the UUID and therefore the type changed, the whole service + // will be replaced + log.debug('... service type changed! Removing the old service.') + accessory.removeService(service) + service = undefined + } - node.topic_in = msg.topic ?? '' - - Object.keys(msg.payload).map((key: string) => { - if (node.supported.indexOf(key) < 0) { - if ( - node.config.useEventCallback && - Storage.uuid4Validate(key) - ) { - const callbackID = key - const callbackValue = msg.payload?.[key] - const eventCallback = Storage.loadCallback(callbackID) - - if (eventCallback) { - log.debug( - `Calling ${eventCallback.event} callback ${callbackID}` - ) - eventCallback.callback(callbackValue) - } else { - log.error(`Callback ${callbackID} timeout`) - } - } else if ( - key === 'AdaptiveLightingController' && - node.adaptiveLightingController - ) { - const value = msg.payload?.[key] - const event = value?.event - - if (event === 'disable') { - node.adaptiveLightingController?.disableAdaptiveLighting() - } - } else { - log.error( - `Instead of '${key}' try one of these characteristics: '${node.supported.join( - "', '" - )}'` - ) - } - } else { - const value = msg.payload?.[key] - - const parentNode = node.parentNode ?? node - parentNode.reachable = value !== NO_RESPONSE_MSG - - const characteristic = node.service.getCharacteristic( - Characteristic[key] - ) - - if (context !== null) { - characteristic.setValue(value, context) - } else { - characteristic.setValue(value) - } - } - }) + if (!service) { + // if no matching service was found or the type changed, then a new + // service will be added + log.debug( + `... didn't find it. Adding new ${serviceInformation.serviceName} service.` + ) + + if (serviceInformation.serviceName === 'CameraControl') { + configureCameraSource(accessory, newService, serviceInformation.config) + service = newService + } else { + service = accessory.addService(newService) + } + } else { + // if a service with the same UUID and subtype was found it will + // be updated and used + log.debug('... found it! Updating it.') + service + .getCharacteristic(Characteristic.Name) + .setValue(serviceInformation.name) } - const onClose = function (removed: boolean, done: () => void) { - const characteristics = node.service.characteristics.concat( - node.service.optionalCharacteristics - ) + if (parentService) { + if (serviceInformation.serviceName === 'CameraControl') { + //We don't add or link it since configureCameraSource do this already. + log.debug('... and adding service to accessory.') + } else if (service) { + log.debug('... and linking service to parent.') + parentService.addLinkedService(service) + } + } - characteristics.forEach(function (characteristic) { - // cleanup all node specific listeners - characteristic.removeListener('get', node.onCharacteristicGet) - characteristic.removeListener('set', node.onCharacteristicSet) - characteristic.removeListener('change', node.onCharacteristicChange) - }) + return service + } - if (node.config.isParent) { - // remove identify listener to prevent errors with undefined values - node.accessory.removeListener('identify', node.onIdentify) - } + const configureCameraSource = function ( + _accessory: Accessory, + _service: Service, + config: HAPService2ConfigType + ) { + if (config.cameraConfigSource) { + log.debug('Configuring Camera Source') - if (removed) { - // This node has been deleted - if (node.config.isParent) { - // remove accessory from bridge - node.hostNode.host.removeBridgedAccessories([node.accessory]) - node.accessory.destroy() - } else { - // only remove the service if it is not a parent - node.accessory.removeService(node.service) - node.parentService.removeLinkedService(node.service) - } - } - - done() + if (!config.cameraConfigVideoProcessor) { + log.error( + 'Missing configuration for CameraControl: videoProcessor cannot be empty!' + ) + } else { + // Use of deprecated method to be replaced with new Camera API + // TODO: https://github.com/homebridge/HAP-NodeJS/blob/latest/src/accessories/Camera_accessory.ts + // accessory.configureCameraSource( + // new CameraSource(service, config, node) + // ) + } + } else { + log.error('Missing configuration for CameraControl.') } + } - const getOrCreate = function ( - accessory: Accessory, - serviceInformation: { - name: string - UUID: string - serviceName: string - config: HAPService2ConfigType - }, - parentService: Service - ) { - const newService = new Service[serviceInformation.serviceName]( - serviceInformation.name, - serviceInformation.UUID - ) - log.debug( - `Looking for service with UUID ${serviceInformation.UUID} ...` - ) + const waitForParent = () => { + log.debug('Waiting for Parent Service') - // search for a service with the same subtype - let service: Service | undefined = accessory.services.find( - (service) => { - return newService.subtype === service.subtype - } - ) + return new Promise((resolve) => { + node.nodeStatusUtils.setStatus({ + fill: 'blue', + shape: 'dot', + text: 'Waiting for Parent Service' + }) - if (service && newService.UUID !== service.UUID) { - // if the UUID and therefore the type changed, the whole service - // will be replaced - log.debug('... service type changed! Removing the old service.') - accessory.removeService(service) - service = undefined - } + const checkAndWait = () => { + const parentNode: HAPService2NodeType = node.RED.nodes.getNode( + node.config.parentService + ) as HAPService2NodeType - if (!service) { - // if no matching service was found or the type changed, then a new - // service will be added - log.debug( - `... didn't find it. Adding new ${serviceInformation.serviceName} service.` - ) - - if (serviceInformation.serviceName === 'CameraControl') { - configureCameraSource( - accessory, - newService, - serviceInformation.config - ) - service = newService - } else { - service = accessory.addService(newService) - } + if (parentNode && parentNode.configured) { + resolve(parentNode) } else { - // if a service with the same UUID and subtype was found it will - // be updated and used - log.debug('... found it! Updating it.') - service - .getCharacteristic(Characteristic.Name) - .setValue(serviceInformation.name) + setTimeout(checkAndWait, 1000) } - - if (parentService) { - if (serviceInformation.serviceName === 'CameraControl') { - //We don't add or link it since configureCameraSource do this already. - log.debug('... and adding service to accessory.') - } else if (service) { - log.debug('... and linking service to parent.') - parentService.addLinkedService(service) - } - } - - return service + } + checkAndWait() + }).catch((error) => { + log.error(`Waiting for Parent Service failed due to: ${error}`) + throw new NRCHKBError(error) + }) + } + + const handleWaitForSetup = ( + config: HAPService2ConfigType, + msg: Record, + resolve: (newConfig: HAPService2ConfigType) => void + ) => { + if (node.setupDone) { + return } - const configureCameraSource = function ( - _accessory: Accessory, - _service: Service, - config: HAPService2ConfigType + if ( + msg.hasOwnProperty('payload') && + msg.payload.hasOwnProperty('nrchkb') && + msg.payload.nrchkb.hasOwnProperty('setup') ) { - if (config.cameraConfigSource) { - log.debug('Configuring Camera Source') - - if (!config.cameraConfigVideoProcessor) { - log.error( - 'Missing configuration for CameraControl: videoProcessor cannot be empty!' - ) - } else { - // Use of deprecated method to be replaced with new Camera API - // TODO: https://github.com/homebridge/HAP-NodeJS/blob/latest/src/accessories/Camera_accessory.ts - // accessory.configureCameraSource( - // new CameraSource(service, config, node) - // ) - } - } else { - log.error('Missing configuration for CameraControl.') - } - } - - const waitForParent = () => { - log.debug('Waiting for Parent Service') - - return new Promise((resolve) => { - node.nodeStatusUtils.setStatus({ - fill: 'blue', - shape: 'dot', - text: 'Waiting for Parent Service', - }) - - const checkAndWait = () => { - const parentNode: HAPService2NodeType = node.RED.nodes.getNode( - node.config.parentService - ) as HAPService2NodeType - - if (parentNode && parentNode.configured) { - resolve(parentNode) - } else { - setTimeout(checkAndWait, 1000) - } - } - checkAndWait() - }).catch((error) => { - log.error(`Waiting for Parent Service failed due to: ${error}`) - throw new NRCHKBError(error) - }) - } - - const handleWaitForSetup = ( - config: HAPService2ConfigType, - msg: Record, - resolve: (newConfig: HAPService2ConfigType) => void - ) => { - if (node.setupDone) { - return - } - - if ( - msg.hasOwnProperty('payload') && - msg.payload.hasOwnProperty('nrchkb') && - msg.payload.nrchkb.hasOwnProperty('setup') - ) { - node.setupDone = true + node.setupDone = true - const newConfig = { - ...config, - ...msg.payload.nrchkb.setup, - } + const newConfig = { + ...config, + ...msg.payload.nrchkb.setup + } - node.removeListener('input', node.handleWaitForSetup) - - resolve(newConfig) - } else { - log.error( - 'Invalid message (required {"payload":{"nrchkb":{"setup":{}}}})' - ) - } - } + node.removeListener('input', node.handleWaitForSetup) - return { - getOrCreate, - onCharacteristicGet, - onCharacteristicSet, - onCharacteristicChange, - onInput, - onClose, - waitForParent, - handleWaitForSetup, - configureAdaptiveLightning: - ServiceUtilsLegacy.configureAdaptiveLightning, + resolve(newConfig) + } else { + log.error( + 'Invalid message (required {"payload":{"nrchkb":{"setup":{}}}})' + ) } + } + + return { + getOrCreate, + onCharacteristicGet, + onCharacteristicSet, + onCharacteristicChange, + onInput, + onClose, + waitForParent, + handleWaitForSetup, + configureAdaptiveLightning: ServiceUtilsLegacy.configureAdaptiveLightning + } } diff --git a/src/lib/utils/index.ts b/src/lib/utils/index.ts index 5964b992..7a09bfb6 100644 --- a/src/lib/utils/index.ts +++ b/src/lib/utils/index.ts @@ -1,15 +1,15 @@ import HAPServiceNodeType from '../types/HAPServiceNodeType' module.exports = function (node: HAPServiceNodeType) { - const ServiceUtils = require('./ServiceUtils')(node) - const BridgeUtils = require('./BridgeUtils')() - const AccessoryUtils = require('./AccessoryUtils')(node) - const CharacteristicUtils = require('./CharacteristicUtils')(node) + const ServiceUtils = require('./ServiceUtils')(node) + const BridgeUtils = require('./BridgeUtils')() + const AccessoryUtils = require('./AccessoryUtils')(node) + const CharacteristicUtils = require('./CharacteristicUtils')(node) - return { - ServiceUtils, - BridgeUtils, - AccessoryUtils, - CharacteristicUtils, - } + return { + ServiceUtils, + BridgeUtils, + AccessoryUtils, + CharacteristicUtils + } } diff --git a/src/nodes/bridge.ts b/src/nodes/bridge.ts index 245c3913..3a74566e 100644 --- a/src/nodes/bridge.ts +++ b/src/nodes/bridge.ts @@ -6,8 +6,8 @@ import HostType from '../lib/types/HostType' const log = logger('NRCHKB', 'HAPHostNode') module.exports = (RED: NodeAPI) => { - const HAPHostNode = require('../lib/HAPHostNode')(RED, HostType.BRIDGE) + const HAPHostNode = require('../lib/HAPHostNode')(RED, HostType.BRIDGE) - log.debug('Registering homekit-bridge type') - RED.nodes.registerType('homekit-bridge', HAPHostNode.init) + log.debug('Registering homekit-bridge type') + RED.nodes.registerType('homekit-bridge', HAPHostNode.init) } diff --git a/src/nodes/nrchkb.ts b/src/nodes/nrchkb.ts index f9392a2a..0e60eb21 100644 --- a/src/nodes/nrchkb.ts +++ b/src/nodes/nrchkb.ts @@ -10,67 +10,67 @@ loggerSetup({ timestampEnabled: 'NRCHKB' }) const log = logger('NRCHKB') if (process.env.NRCHKB_EXPERIMENTAL === 'true') { - log.error('Experimental features enabled') + log.error('Experimental features enabled') } module.exports = (RED: NodeAPI) => { - const deprecatedMinimalNodeVersion = '10.22.1' - const minimalNodeVersion = '12.0.0' - const nodeVersion = process.version + const deprecatedMinimalNodeVersion = '10.22.1' + const minimalNodeVersion = '12.0.0' + const nodeVersion = process.version - if (semver.gte(nodeVersion, deprecatedMinimalNodeVersion)) { - log.debug( - `Node.js version requirement met. Required >=${deprecatedMinimalNodeVersion}. Installed ${nodeVersion}` - ) - if (semver.lt(nodeVersion, minimalNodeVersion)) { - log.error( - 'Node.js version requirement met but will be deprecated in Node-RED 2.0.0' - ) - log.error( - `Recommended >=${minimalNodeVersion}. Installed ${nodeVersion}. Consider upgrading.` - ) - } - } else { - throw RangeError( - `Node.js version requirement not met. Required >=${deprecatedMinimalNodeVersion}. Installed ${nodeVersion}` - ) + if (semver.gte(nodeVersion, deprecatedMinimalNodeVersion)) { + log.debug( + `Node.js version requirement met. Required >=${deprecatedMinimalNodeVersion}. Installed ${nodeVersion}` + ) + if (semver.lt(nodeVersion, minimalNodeVersion)) { + log.error( + 'Node.js version requirement met but will be deprecated in Node-RED 2.0.0' + ) + log.error( + `Recommended >=${minimalNodeVersion}. Installed ${nodeVersion}. Consider upgrading.` + ) } + } else { + throw RangeError( + `Node.js version requirement not met. Required >=${deprecatedMinimalNodeVersion}. Installed ${nodeVersion}` + ) + } - const API = require('../lib/api')(RED) + const API = require('../lib/api')(RED) - let rootFolder: string + let rootFolder: string - // Initialize our storage system - if (RED.settings.available() && RED.settings.userDir) { - log.debug('RED settings available') - rootFolder = RED.settings.userDir - } else { - log.error('RED settings not available') - rootFolder = path.join(require('os').homedir(), '.node-red') - } + // Initialize our storage system + if (RED.settings.available() && RED.settings.userDir) { + log.debug('RED settings available') + rootFolder = RED.settings.userDir + } else { + log.error('RED settings not available') + rootFolder = path.join(require('os').homedir(), '.node-red') + } - Storage.init(rootFolder, 'nrchkb').then(() => { - log.debug(`nrchkb storage path set to ${Storage.storagePath()}`) - API.init() + Storage.init(rootFolder, 'nrchkb').then(() => { + log.debug(`nrchkb storage path set to ${Storage.storagePath()}`) + API.init() - const hapStoragePath = path.resolve(rootFolder, 'homekit-persist') + const hapStoragePath = path.resolve(rootFolder, 'homekit-persist') - try { - HAPStorage.setCustomStoragePath(hapStoragePath) - log.debug(`HAPStorage path set to ${hapStoragePath}`) - } catch (error: any) { - log.debug('HAPStorage already initialized') - log.error('node-red restart highly recommended') - log.trace(error) - } + try { + HAPStorage.setCustomStoragePath(hapStoragePath) + log.debug(`HAPStorage path set to ${hapStoragePath}`) + } catch (error: any) { + log.debug('HAPStorage already initialized') + log.error('node-red restart highly recommended') + log.trace(error) + } - // Experimental feature - if (process.env.NRCHKB_EXPERIMENTAL === 'true') { - log.debug('Registering nrchkb type') + // Experimental feature + if (process.env.NRCHKB_EXPERIMENTAL === 'true') { + log.debug('Registering nrchkb type') - RED.nodes.registerType('nrchkb', function (this: any, config) { - RED.nodes.createNode(this, config) - }) - } - }) + RED.nodes.registerType('nrchkb', function (this: any, config) { + RED.nodes.createNode(this, config) + }) + } + }) } diff --git a/src/nodes/service.ts b/src/nodes/service.ts index dc4a7afe..9b6ea289 100644 --- a/src/nodes/service.ts +++ b/src/nodes/service.ts @@ -4,8 +4,8 @@ import { NodeAPI } from 'node-red' const log = logger('NRCHKB', 'HAPServiceNode') module.exports = (RED: NodeAPI) => { - const HAPServiceNode = require('../lib/HAPServiceNode')(RED) + const HAPServiceNode = require('../lib/HAPServiceNode')(RED) - log.debug('Registering homekit-service type') - RED.nodes.registerType('homekit-service', HAPServiceNode.preInit) + log.debug('Registering homekit-service type') + RED.nodes.registerType('homekit-service', HAPServiceNode.preInit) } diff --git a/src/nodes/service2.ts b/src/nodes/service2.ts index d59017e2..02e21666 100644 --- a/src/nodes/service2.ts +++ b/src/nodes/service2.ts @@ -4,10 +4,10 @@ import { NodeAPI } from 'node-red' const log = logger('NRCHKB', 'HAPServiceNode2') module.exports = (RED: NodeAPI) => { - const HAPServiceNode2 = require('../lib/HAPServiceNode2')(RED) + const HAPServiceNode2 = require('../lib/HAPServiceNode2')(RED) - if (process.env.NRCHKB_EXPERIMENTAL === 'true') { - log.debug('Registering homekit-service2 type') - RED.nodes.registerType('homekit-service2', HAPServiceNode2.preInit) - } + if (process.env.NRCHKB_EXPERIMENTAL === 'true') { + log.debug('Registering homekit-service2 type') + RED.nodes.registerType('homekit-service2', HAPServiceNode2.preInit) + } } diff --git a/src/nodes/standalone.ts b/src/nodes/standalone.ts index 5575665d..ff522c54 100644 --- a/src/nodes/standalone.ts +++ b/src/nodes/standalone.ts @@ -6,8 +6,8 @@ import HostType from '../lib/types/HostType' const log = logger('NRCHKB', 'HAPHostNode') module.exports = (RED: NodeAPI) => { - const HAPHostNode = require('../lib/HAPHostNode')(RED, HostType.STANDALONE) + const HAPHostNode = require('../lib/HAPHostNode')(RED, HostType.STANDALONE) - log.debug('Registering homekit-standalone type') - RED.nodes.registerType('homekit-standalone', HAPHostNode.init) + log.debug('Registering homekit-standalone type') + RED.nodes.registerType('homekit-standalone', HAPHostNode.init) } diff --git a/src/nodes/status.ts b/src/nodes/status.ts index a5b900f1..78ce5e10 100644 --- a/src/nodes/status.ts +++ b/src/nodes/status.ts @@ -10,53 +10,51 @@ import { NodeStatusUtils } from '../lib/utils/NodeStatusUtils' const log = logger('NRCHKB', 'HAPStatusNode') module.exports = (RED: NodeAPI) => { - log.debug('Registering homekit-status type') - RED.nodes.registerType( - 'homekit-status', - function (this: HAPStatusNodeType, config: HAPStatusConfigType) { - const self = this - self.config = config - RED.nodes.createNode(self, config) + log.debug('Registering homekit-status type') + RED.nodes.registerType( + 'homekit-status', + function (this: HAPStatusNodeType, config: HAPStatusConfigType) { + const self = this + self.config = config + RED.nodes.createNode(self, config) - self.nodeStatusUtils = new NodeStatusUtils(self) + self.nodeStatusUtils = new NodeStatusUtils(self) - try { - self.serviceNode = RED.nodes.getNode( - self.config.serviceNodeId - ) as HAPServiceNodeType - } catch (error: any) { - log.error(error) - } + try { + self.serviceNode = RED.nodes.getNode( + self.config.serviceNodeId + ) as HAPServiceNodeType + } catch (error: any) { + log.error(error) + } - self.on('input', (_: Record) => { - if (self.serviceNode) { - self.nodeStatusUtils.setStatus( - { - fill: 'green', - shape: 'dot', - text: 'Done', - }, - 3000 - ) - const serializedService = Service.serialize( - self.serviceNode.service - ) - self.send({ - payload: serializedService, - }) - } else { - self.nodeStatusUtils.setStatus({ - fill: 'red', - shape: 'dot', - text: 'Check your config', - }) - } - }) - - self.on('close', (_: boolean, done: () => void) => { - self.serviceNode = undefined - done() - }) + self.on('input', (_: Record) => { + if (self.serviceNode) { + self.nodeStatusUtils.setStatus( + { + fill: 'green', + shape: 'dot', + text: 'Done' + }, + 3000 + ) + const serializedService = Service.serialize(self.serviceNode.service) + self.send({ + payload: serializedService + }) + } else { + self.nodeStatusUtils.setStatus({ + fill: 'red', + shape: 'dot', + text: 'Check your config' + }) } - ) + }) + + self.on('close', (_: boolean, done: () => void) => { + self.serviceNode = undefined + done() + }) + } + ) } diff --git a/src/test/lib/HAPBridgeNode.test.ts b/src/test/lib/HAPBridgeNode.test.ts index f51e4ab4..3c82c3b3 100644 --- a/src/test/lib/HAPBridgeNode.test.ts +++ b/src/test/lib/HAPBridgeNode.test.ts @@ -4,37 +4,37 @@ import { describe, expect, it } from 'vitest' const HAPHostNode = require('../../../build/lib/HAPHostNode')() loggerSetup({ - debugEnabled: true, - errorEnabled: true, - traceEnabled: false, + debugEnabled: true, + errorEnabled: true, + traceEnabled: false }) describe('HAPHostNode', function () { - // allow longer for this suite (configured via package.json vitest.test.testTimeout) + // allow longer for this suite (configured via package.json vitest.test.testTimeout) - it('string macify should pass', function () { - const stringToMacify = 'BRIDGE NAME' - HAPHostNode.macify(stringToMacify) - }) + it('string macify should pass', function () { + const stringToMacify = 'BRIDGE NAME' + HAPHostNode.macify(stringToMacify) + }) - it('null string macify should fail', function () { - const stringToMacify = null as unknown as string - expect(() => { - HAPHostNode.macify(stringToMacify) - }).toThrow('nodeId cannot be empty in macify process') - }) + it('null string macify should fail', function () { + const stringToMacify = null as unknown as string + expect(() => { + HAPHostNode.macify(stringToMacify) + }).toThrow('nodeId cannot be empty in macify process') + }) - it('undefined string macify should fail', function () { - const stringToMacify = undefined as unknown as string - expect(() => { - HAPHostNode.macify(stringToMacify) - }).toThrow('nodeId cannot be empty in macify process') - }) + it('undefined string macify should fail', function () { + const stringToMacify = undefined as unknown as string + expect(() => { + HAPHostNode.macify(stringToMacify) + }).toThrow('nodeId cannot be empty in macify process') + }) - it('empty string macify should fail', function () { - const stringToMacify = '' - expect(() => { - HAPHostNode.macify(stringToMacify) - }).toThrow('nodeId cannot be empty in macify process') - }) + it('empty string macify should fail', function () { + const stringToMacify = '' + expect(() => { + HAPHostNode.macify(stringToMacify) + }).toThrow('nodeId cannot be empty in macify process') + }) }) diff --git a/src/test/lib/NodeStatusUtils.test.ts b/src/test/lib/NodeStatusUtils.test.ts index 12a36f23..e22a4bcc 100644 --- a/src/test/lib/NodeStatusUtils.test.ts +++ b/src/test/lib/NodeStatusUtils.test.ts @@ -1,87 +1,87 @@ import { NodeStatus } from '@node-red/registry' import { - afterAll, - beforeAll, - beforeEach, - describe, - expect, - it, - vi, + afterAll, + beforeAll, + beforeEach, + describe, + expect, + it, + vi } from 'vitest' import { NodeStatusUtils } from '../../lib/utils/NodeStatusUtils' class NodeWithStatusMock { - constructor(public currentStatus: string | NodeStatus = '') {} - status(status: string | NodeStatus): void { - this.currentStatus = status - } + constructor(public currentStatus: string | NodeStatus = '') {} + status(status: string | NodeStatus): void { + this.currentStatus = status + } } describe('NodeStatusUtils', function () { - let node: NodeWithStatusMock - let nodeStatusUtils: NodeStatusUtils + let node: NodeWithStatusMock + let nodeStatusUtils: NodeStatusUtils - beforeAll(function () { - vi.useFakeTimers() - }) + beforeAll(function () { + vi.useFakeTimers() + }) - afterAll(function () { - vi.useRealTimers() - }) + afterAll(function () { + vi.useRealTimers() + }) - beforeEach(function () { - node = new NodeWithStatusMock() - nodeStatusUtils = new NodeStatusUtils(node) - }) + beforeEach(function () { + node = new NodeWithStatusMock() + nodeStatusUtils = new NodeStatusUtils(node) + }) - it('setStatus', function () { - nodeStatusUtils.setStatus('test') - expect(node.currentStatus).toBe('test') - }) + it('setStatus', function () { + nodeStatusUtils.setStatus('test') + expect(node.currentStatus).toBe('test') + }) - it('clearStatus', function () { - nodeStatusUtils.setStatus('test') - expect(node.currentStatus).toBe('test') - nodeStatusUtils.clearStatus() - expect(node.currentStatus).toBe('') - }) + it('clearStatus', function () { + nodeStatusUtils.setStatus('test') + expect(node.currentStatus).toBe('test') + nodeStatusUtils.clearStatus() + expect(node.currentStatus).toBe('') + }) - it('setStatusWithTimeout', function () { - nodeStatusUtils.setStatus('test', 2000) - expect(node.currentStatus).toBe('test') - vi.advanceTimersByTime(1000) - expect(node.currentStatus).toBe('test') - vi.advanceTimersByTime(1000) - expect(node.currentStatus).toBe('') - }) + it('setStatusWithTimeout', function () { + nodeStatusUtils.setStatus('test', 2000) + expect(node.currentStatus).toBe('test') + vi.advanceTimersByTime(1000) + expect(node.currentStatus).toBe('test') + vi.advanceTimersByTime(1000) + expect(node.currentStatus).toBe('') + }) - it('setStatusWithTimeout - should not clear status with different id', function () { - nodeStatusUtils.setStatus('test', 2000) - expect(node.currentStatus).toBe('test') - vi.advanceTimersByTime(1000) - expect(node.currentStatus).toBe('test') - nodeStatusUtils.setStatus('test2', 2000) - vi.advanceTimersByTime(1000) - expect(node.currentStatus).toBe('test2') - vi.advanceTimersByTime(1000) - expect(node.currentStatus).toBe('') - }) + it('setStatusWithTimeout - should not clear status with different id', function () { + nodeStatusUtils.setStatus('test', 2000) + expect(node.currentStatus).toBe('test') + vi.advanceTimersByTime(1000) + expect(node.currentStatus).toBe('test') + nodeStatusUtils.setStatus('test2', 2000) + vi.advanceTimersByTime(1000) + expect(node.currentStatus).toBe('test2') + vi.advanceTimersByTime(1000) + expect(node.currentStatus).toBe('') + }) - it('clearStatusByType - should not clear other type', function () { - nodeStatusUtils.setStatus({ text: 'test' }) - expect(node.currentStatus).toStrictEqual({ text: 'test' }) - nodeStatusUtils.clearStatusByType('NO_RESPONSE') - expect(node.currentStatus).toStrictEqual({ text: 'test' }) - }) + it('clearStatusByType - should not clear other type', function () { + nodeStatusUtils.setStatus({ text: 'test' }) + expect(node.currentStatus).toStrictEqual({ text: 'test' }) + nodeStatusUtils.clearStatusByType('NO_RESPONSE') + expect(node.currentStatus).toStrictEqual({ text: 'test' }) + }) - it('clearStatusByType - should clear same type', function () { - nodeStatusUtils.setStatus({ text: 'test', type: 'NO_RESPONSE' }) - expect(node.currentStatus).toStrictEqual({ - text: 'test', - type: 'NO_RESPONSE', - }) - nodeStatusUtils.clearStatusByType('NO_RESPONSE') - expect(node.currentStatus).toStrictEqual('') + it('clearStatusByType - should clear same type', function () { + nodeStatusUtils.setStatus({ text: 'test', type: 'NO_RESPONSE' }) + expect(node.currentStatus).toStrictEqual({ + text: 'test', + type: 'NO_RESPONSE' }) + nodeStatusUtils.clearStatusByType('NO_RESPONSE') + expect(node.currentStatus).toStrictEqual('') + }) }) diff --git a/src/test/lib/api.test.ts b/src/test/lib/api.test.ts index 69d00a2d..9223e5cf 100644 --- a/src/test/lib/api.test.ts +++ b/src/test/lib/api.test.ts @@ -4,8 +4,8 @@ import { afterAll, afterEach, beforeAll, describe, expect, it } from 'vitest' import { version } from '../../../package.json' import { - accessoryCategoriesResponse, - serviceTypesResponse, + accessoryCategoriesResponse, + serviceTypesResponse } from '../test-utils/data' const API = require('../../../build/lib/api')() @@ -14,74 +14,74 @@ const nrchkb = require('../../../build/nodes/nrchkb') process.env.NRCHKB_EXPERIMENTAL = 'true' loggerSetup({ - debugEnabled: true, - errorEnabled: true, - traceEnabled: false, + debugEnabled: true, + errorEnabled: true, + traceEnabled: false }) describe('api', function () { - beforeAll(function () { - return new Promise((resolve) => helper.startServer(resolve)) - }) + beforeAll(function () { + return new Promise((resolve) => helper.startServer(resolve)) + }) - afterAll(function () { - return new Promise((resolve) => helper.stopServer(resolve)) - }) + afterAll(function () { + return new Promise((resolve) => helper.stopServer(resolve)) + }) - afterEach(function () { - helper.unload() - }) + afterEach(function () { + helper.unload() + }) - it('Service API', async function () { - await helper.load([nrchkb], []) - const response = await helper - .request() - .get('/nrchkb/service/types') - .expect('Content-Type', /json/) - .expect(200) - expect(response.body).toStrictEqual(serviceTypesResponse) - }) + it('Service API', async function () { + await helper.load([nrchkb], []) + const response = await helper + .request() + .get('/nrchkb/service/types') + .expect('Content-Type', /json/) + .expect(200) + expect(response.body).toStrictEqual(serviceTypesResponse) + }) - describe('stringifyVersion', function () { - it('release', function () { - const input = '1.2.3' - const expected = '1.2.3' - const result = API.stringifyVersion(input) - expect(result).toBe(expected) - }) + describe('stringifyVersion', function () { + it('release', function () { + const input = '1.2.3' + const expected = '1.2.3' + const result = API.stringifyVersion(input) + expect(result).toBe(expected) + }) - it('dev', function () { - const input = '1.2.3-dev.45' - const expected = '0.123.45' - const result = API.stringifyVersion(input) - expect(result).toBe(expected) - }) + it('dev', function () { + const input = '1.2.3-dev.45' + const expected = '0.123.45' + const result = API.stringifyVersion(input) + expect(result).toBe(expected) }) + }) - it('NRCHKB Info API', async function () { - await helper.load([nrchkb], []) - const xyzVersion = API.stringifyVersion(version) + it('NRCHKB Info API', async function () { + await helper.load([nrchkb], []) + const xyzVersion = API.stringifyVersion(version) - const response = await helper - .request() - .get('/nrchkb/info') - .expect('Content-Type', /json/) - .expect(200) + const response = await helper + .request() + .get('/nrchkb/info') + .expect('Content-Type', /json/) + .expect(200) - expect(response.body).toStrictEqual({ - experimental: true, - version: xyzVersion, - }) + expect(response.body).toStrictEqual({ + experimental: true, + version: xyzVersion }) + }) - it('Accessory API', async function () { - await helper.load([nrchkb], []) - const response = await helper - .request() - .get('/nrchkb/accessory/categories') - .expect('Content-Type', /json/) - .expect(200) + it('Accessory API', async function () { + await helper.load([nrchkb], []) + const response = await helper + .request() + .get('/nrchkb/accessory/categories') + .expect('Content-Type', /json/) + .expect(200) - expect(response.body).toStrictEqual(accessoryCategoriesResponse) - }) + expect(response.body).toStrictEqual(accessoryCategoriesResponse) + }) }) diff --git a/src/test/nodes/service.test.ts b/src/test/nodes/service.test.ts index d8c61349..c4a0ee22 100644 --- a/src/test/nodes/service.test.ts +++ b/src/test/nodes/service.test.ts @@ -1,13 +1,13 @@ import { loggerSetup } from '@nrchkb/logger' import helper from 'node-red-node-test-helper' import { - afterAll, - afterEach, - beforeAll, - describe, - expect, - it, - vi, + afterAll, + afterEach, + beforeAll, + describe, + expect, + it, + vi } from 'vitest' import { switchServiceBridgeFlow } from '../test-utils/data' @@ -16,113 +16,113 @@ const nrchkb = require('../../../build/nodes/nrchkb') const homekitServiceNode = require('../../../build/nodes/service') loggerSetup({ - debugEnabled: true, - errorEnabled: true, - traceEnabled: false, + debugEnabled: true, + errorEnabled: true, + traceEnabled: false }) describe('Service Node', function () { - beforeAll(function () { - return new Promise((resolve) => helper.startServer(resolve)) + beforeAll(function () { + return new Promise((resolve) => helper.startServer(resolve)) + }) + + afterAll(function () { + return new Promise((resolve) => helper.stopServer(resolve)) + }) + + afterEach(function () { + helper.unload() + }) + + it('should be loaded', async function () { + const { serviceId, flow } = switchServiceBridgeFlow() + await helper.load([nrchkb, homekitBridgeNode, homekitServiceNode], flow) + const s1 = helper.getNode(serviceId) + expect(s1).toHaveProperty('type', 'homekit-service') + }) + + it('should output ON:true payload', async function () { + const { serviceId, flow } = switchServiceBridgeFlow() + await helper.load([nrchkb, homekitBridgeNode, homekitServiceNode], flow) + const s1 = helper.getNode(serviceId) + + await new Promise((resolve) => { + s1.on('input', (msg: any) => { + expect(msg.payload).toHaveProperty('On', true) + resolve() + }) + + s1.receive({ payload: { On: true } }) }) + }) - afterAll(function () { - return new Promise((resolve) => helper.stopServer(resolve)) - }) - - afterEach(function () { - helper.unload() - }) - - it('should be loaded', async function () { - const { serviceId, flow } = switchServiceBridgeFlow() - await helper.load([nrchkb, homekitBridgeNode, homekitServiceNode], flow) - const s1 = helper.getNode(serviceId) - expect(s1).toHaveProperty('type', 'homekit-service') - }) - - it('should output ON:true payload', async function () { - const { serviceId, flow } = switchServiceBridgeFlow() - await helper.load([nrchkb, homekitBridgeNode, homekitServiceNode], flow) - const s1 = helper.getNode(serviceId) + it('should output ON:false payload', async function () { + const { serviceId, flow } = switchServiceBridgeFlow() + await helper.load([nrchkb, homekitBridgeNode, homekitServiceNode], flow) + const s1 = helper.getNode(serviceId) - await new Promise((resolve) => { - s1.on('input', (msg: any) => { - expect(msg.payload).toHaveProperty('On', true) - resolve() - }) + await new Promise((resolve) => { + s1.on('input', function (msg: any) { + expect(msg.payload).toHaveProperty('On', false) + resolve() + }) - s1.receive({ payload: { On: true } }) - }) + s1.receive({ payload: { On: false } }) }) - - it('should output ON:false payload', async function () { - const { serviceId, flow } = switchServiceBridgeFlow() - await helper.load([nrchkb, homekitBridgeNode, homekitServiceNode], flow) - const s1 = helper.getNode(serviceId) - - await new Promise((resolve) => { - s1.on('input', function (msg: any) { - expect(msg.payload).toHaveProperty('On', false) - resolve() - }) - - s1.receive({ payload: { On: false } }) - }) + }) + + it('should output reachable true', async function () { + const { serviceId, flow } = switchServiceBridgeFlow() + await helper.load([nrchkb, homekitBridgeNode, homekitServiceNode], flow) + const s1 = helper.getNode(serviceId) + const h1 = helper.getNode('h1') + + let count = 0 + + await new Promise((resolve) => { + h1.on('input', function (msg: any) { + if (count === 0) { + expect(msg.payload).toHaveProperty('On', true) + expect(msg.hap).toHaveProperty('newValue', true) + expect(msg.hap).toHaveProperty('reachable', true) + resolve() + count++ + } + }) + + s1.receive({ payload: { On: true } }) }) - - it('should output reachable true', async function () { - const { serviceId, flow } = switchServiceBridgeFlow() - await helper.load([nrchkb, homekitBridgeNode, homekitServiceNode], flow) - const s1 = helper.getNode(serviceId) - const h1 = helper.getNode('h1') - - let count = 0 - - await new Promise((resolve) => { - h1.on('input', function (msg: any) { - if (count === 0) { - expect(msg.payload).toHaveProperty('On', true) - expect(msg.hap).toHaveProperty('newValue', true) - expect(msg.hap).toHaveProperty('reachable', true) - resolve() - count++ - } - }) - - s1.receive({ payload: { On: true } }) - }) - }) - - it('should output reachable false', async function () { - const { serviceId, flow } = switchServiceBridgeFlow() - await helper.load([nrchkb, homekitBridgeNode, homekitServiceNode], flow) - const s1 = helper.getNode(serviceId) - const h1 = helper.getNode('h1') - - await new Promise((resolve, reject) => { - // spy status so we can assert it was called - const statusSpy = vi - .spyOn(s1 as any, 'status') - .mockImplementation(() => {}) - - h1.on('input', function (msg: any) { - try { - expect(msg.payload).toHaveProperty('On', false) - expect(msg.hap).toHaveProperty('reachable', false) - expect(statusSpy).toHaveBeenCalledWith({ - fill: 'red', - shape: 'ring', - text: 'Not reachable', - type: 'NO_RESPONSE', - }) - resolve() - } catch (err) { - reject(err) - } - }) - - s1.receive({ payload: { On: 'NO_RESPONSE' } }) - }) + }) + + it('should output reachable false', async function () { + const { serviceId, flow } = switchServiceBridgeFlow() + await helper.load([nrchkb, homekitBridgeNode, homekitServiceNode], flow) + const s1 = helper.getNode(serviceId) + const h1 = helper.getNode('h1') + + await new Promise((resolve, reject) => { + // spy status so we can assert it was called + const statusSpy = vi + .spyOn(s1 as any, 'status') + .mockImplementation(() => {}) + + h1.on('input', function (msg: any) { + try { + expect(msg.payload).toHaveProperty('On', false) + expect(msg.hap).toHaveProperty('reachable', false) + expect(statusSpy).toHaveBeenCalledWith({ + fill: 'red', + shape: 'ring', + text: 'Not reachable', + type: 'NO_RESPONSE' + }) + resolve() + } catch (err) { + reject(err) + } + }) + + s1.receive({ payload: { On: 'NO_RESPONSE' } }) }) + }) }) diff --git a/src/test/nodes/service2.test.ts b/src/test/nodes/service2.test.ts index b5d4cf59..b27159a7 100644 --- a/src/test/nodes/service2.test.ts +++ b/src/test/nodes/service2.test.ts @@ -1,13 +1,13 @@ import { loggerSetup } from '@nrchkb/logger' import helper from 'node-red-node-test-helper' import { - afterAll, - afterEach, - beforeAll, - describe, - expect, - it, - vi, + afterAll, + afterEach, + beforeAll, + describe, + expect, + it, + vi } from 'vitest' import { switchService2BridgeFlow } from '../test-utils/data' @@ -18,127 +18,112 @@ const homekitService2Node = require('../../../build/nodes/service2') process.env.NRCHKB_EXPERIMENTAL = 'true' loggerSetup({ - debugEnabled: true, - errorEnabled: true, - traceEnabled: false, + debugEnabled: true, + errorEnabled: true, + traceEnabled: false }) describe('Service Node', function () { - beforeAll(function () { - return new Promise((resolve) => helper.startServer(resolve)) + beforeAll(function () { + return new Promise((resolve) => helper.startServer(resolve)) + }) + + afterAll(function () { + return new Promise((resolve) => helper.stopServer(resolve)) + }) + + afterEach(function () { + helper.unload() + }) + + it('should be loaded', async function () { + const { serviceId, flow } = switchService2BridgeFlow() + await helper.load([nrchkb, homekitBridgeNode, homekitService2Node], flow) + const s1 = helper.getNode(serviceId) + expect(s1).toHaveProperty('type', 'homekit-service2') + }) + + it('should output ON:true payload', async function () { + const { serviceId, flow } = switchService2BridgeFlow() + await helper.load([nrchkb, homekitBridgeNode, homekitService2Node], flow) + const s1 = helper.getNode(serviceId) + + await new Promise((resolve) => { + s1.on('input', (msg: any) => { + expect(msg.payload).toHaveProperty('On', true) + resolve() + }) + + s1.receive({ payload: { On: true } }) }) + }) - afterAll(function () { - return new Promise((resolve) => helper.stopServer(resolve)) - }) - - afterEach(function () { - helper.unload() - }) - - it('should be loaded', async function () { - const { serviceId, flow } = switchService2BridgeFlow() - await helper.load( - [nrchkb, homekitBridgeNode, homekitService2Node], - flow - ) - const s1 = helper.getNode(serviceId) - expect(s1).toHaveProperty('type', 'homekit-service2') - }) + it('should output ON:false payload', async function () { + const { serviceId, flow } = switchService2BridgeFlow() + await helper.load([nrchkb, homekitBridgeNode, homekitService2Node], flow) + const s1 = helper.getNode(serviceId) - it('should output ON:true payload', async function () { - const { serviceId, flow } = switchService2BridgeFlow() - await helper.load( - [nrchkb, homekitBridgeNode, homekitService2Node], - flow - ) - const s1 = helper.getNode(serviceId) - - await new Promise((resolve) => { - s1.on('input', (msg: any) => { - expect(msg.payload).toHaveProperty('On', true) - resolve() - }) - - s1.receive({ payload: { On: true } }) - }) - }) + await new Promise((resolve) => { + s1.on('input', function (msg: any) { + expect(msg.payload).toHaveProperty('On', false) + resolve() + }) - it('should output ON:false payload', async function () { - const { serviceId, flow } = switchService2BridgeFlow() - await helper.load( - [nrchkb, homekitBridgeNode, homekitService2Node], - flow - ) - const s1 = helper.getNode(serviceId) - - await new Promise((resolve) => { - s1.on('input', function (msg: any) { - expect(msg.payload).toHaveProperty('On', false) - resolve() - }) - - s1.receive({ payload: { On: false } }) - }) + s1.receive({ payload: { On: false } }) }) - - it('should output reachable true', async function () { - const { serviceId, flow } = switchService2BridgeFlow() - await helper.load( - [nrchkb, homekitBridgeNode, homekitService2Node], - flow - ) - const s1 = helper.getNode(serviceId) - const h1 = helper.getNode('h1') - - let count = 0 - - await new Promise((resolve) => { - h1.on('input', function (msg: any) { - if (count === 0) { - expect(msg.payload).toHaveProperty('On', true) - expect(msg.hap).toHaveProperty('newValue', true) - expect(msg.hap).toHaveProperty('reachable', true) - resolve() - count++ - } - }) - - s1.receive({ payload: { On: true } }) - }) + }) + + it('should output reachable true', async function () { + const { serviceId, flow } = switchService2BridgeFlow() + await helper.load([nrchkb, homekitBridgeNode, homekitService2Node], flow) + const s1 = helper.getNode(serviceId) + const h1 = helper.getNode('h1') + + let count = 0 + + await new Promise((resolve) => { + h1.on('input', function (msg: any) { + if (count === 0) { + expect(msg.payload).toHaveProperty('On', true) + expect(msg.hap).toHaveProperty('newValue', true) + expect(msg.hap).toHaveProperty('reachable', true) + resolve() + count++ + } + }) + + s1.receive({ payload: { On: true } }) }) - - it('should output reachable false', async function () { - const { serviceId, flow } = switchService2BridgeFlow() - await helper.load( - [nrchkb, homekitBridgeNode, homekitService2Node], - flow - ) - const s1 = helper.getNode(serviceId) - const h1 = helper.getNode('h1') - - await new Promise((resolve, reject) => { - const statusSpy = vi - .spyOn(s1 as any, 'status') - .mockImplementation(() => {}) - - h1.on('input', function (msg: any) { - try { - expect(msg.payload).toHaveProperty('On', false) - expect(msg.hap).toHaveProperty('reachable', false) - expect(statusSpy).toHaveBeenCalledWith({ - fill: 'red', - shape: 'ring', - text: 'Not reachable', - type: 'NO_RESPONSE', - }) - resolve() - } catch (err) { - reject(err) - } - }) - - s1.receive({ payload: { On: 'NO_RESPONSE' } }) - }) + }) + + it('should output reachable false', async function () { + const { serviceId, flow } = switchService2BridgeFlow() + await helper.load([nrchkb, homekitBridgeNode, homekitService2Node], flow) + const s1 = helper.getNode(serviceId) + const h1 = helper.getNode('h1') + + await new Promise((resolve, reject) => { + const statusSpy = vi + .spyOn(s1 as any, 'status') + .mockImplementation(() => {}) + + h1.on('input', function (msg: any) { + try { + expect(msg.payload).toHaveProperty('On', false) + expect(msg.hap).toHaveProperty('reachable', false) + expect(statusSpy).toHaveBeenCalledWith({ + fill: 'red', + shape: 'ring', + text: 'Not reachable', + type: 'NO_RESPONSE' + }) + resolve() + } catch (err) { + reject(err) + } + }) + + s1.receive({ payload: { On: 'NO_RESPONSE' } }) }) + }) }) diff --git a/src/test/test-utils/data/api.accessory.categories.response.ts b/src/test/test-utils/data/api.accessory.categories.response.ts index 25b318ba..cef33f77 100644 --- a/src/test/test-utils/data/api.accessory.categories.response.ts +++ b/src/test/test-utils/data/api.accessory.categories.response.ts @@ -1,38 +1,38 @@ export const accessoryCategoriesResponse = { - '1': 'OTHER', - '2': 'BRIDGE', - '3': 'FAN', - '4': 'GARAGE_DOOR_OPENER', - '5': 'LIGHTBULB', - '6': 'DOOR_LOCK', - '7': 'OUTLET', - '8': 'SWITCH', - '9': 'THERMOSTAT', - '10': 'SENSOR', - '11': 'SECURITY_SYSTEM', - '12': 'DOOR', - '13': 'WINDOW', - '14': 'WINDOW_COVERING', - '15': 'PROGRAMMABLE_SWITCH', - '16': 'RANGE_EXTENDER', - '17': 'IP_CAMERA', - '18': 'VIDEO_DOORBELL', - '19': 'AIR_PURIFIER', - '20': 'AIR_HEATER', - '21': 'AIR_CONDITIONER', - '22': 'AIR_HUMIDIFIER', - '23': 'AIR_DEHUMIDIFIER', - '24': 'APPLE_TV', - '25': 'HOMEPOD', - '26': 'SPEAKER', - '27': 'AIRPORT', - '28': 'SPRINKLER', - '29': 'FAUCET', - '30': 'SHOWER_HEAD', - '31': 'TELEVISION', - '32': 'TARGET_CONTROLLER', - '33': 'ROUTER', - '34': 'AUDIO_RECEIVER', - '35': 'TV_SET_TOP_BOX', - '36': 'TV_STREAMING_STICK', + '1': 'OTHER', + '2': 'BRIDGE', + '3': 'FAN', + '4': 'GARAGE_DOOR_OPENER', + '5': 'LIGHTBULB', + '6': 'DOOR_LOCK', + '7': 'OUTLET', + '8': 'SWITCH', + '9': 'THERMOSTAT', + '10': 'SENSOR', + '11': 'SECURITY_SYSTEM', + '12': 'DOOR', + '13': 'WINDOW', + '14': 'WINDOW_COVERING', + '15': 'PROGRAMMABLE_SWITCH', + '16': 'RANGE_EXTENDER', + '17': 'IP_CAMERA', + '18': 'VIDEO_DOORBELL', + '19': 'AIR_PURIFIER', + '20': 'AIR_HEATER', + '21': 'AIR_CONDITIONER', + '22': 'AIR_HUMIDIFIER', + '23': 'AIR_DEHUMIDIFIER', + '24': 'APPLE_TV', + '25': 'HOMEPOD', + '26': 'SPEAKER', + '27': 'AIRPORT', + '28': 'SPRINKLER', + '29': 'FAUCET', + '30': 'SHOWER_HEAD', + '31': 'TELEVISION', + '32': 'TARGET_CONTROLLER', + '33': 'ROUTER', + '34': 'AUDIO_RECEIVER', + '35': 'TV_SET_TOP_BOX', + '36': 'TV_STREAMING_STICK' } diff --git a/src/test/test-utils/data/api.service.types.response.ts b/src/test/test-utils/data/api.service.types.response.ts index 3b0aa1b9..71ada317 100644 --- a/src/test/test-utils/data/api.service.types.response.ts +++ b/src/test/test-utils/data/api.service.types.response.ts @@ -1,6149 +1,6146 @@ export const serviceTypesResponse = { - AccessCode: { - UUID: '00000260-0000-1000-8000-0026BB765291', - characteristics: [ - { - UUID: '00000262-0000-1000-8000-0026BB765291', - constructorName: 'AccessCodeControlPoint', - displayName: 'Access Code Control Point', - eventOnlyCharacteristic: false, - props: { - format: 'tlv8', - perms: ['pr', 'pw', 'wr'], - }, - value: '', - }, - { - UUID: '00000261-0000-1000-8000-0026BB765291', - constructorName: 'AccessCodeSupportedConfiguration', - displayName: 'Access Code Supported Configuration', - eventOnlyCharacteristic: false, - props: { - format: 'tlv8', - perms: ['pr'], - }, - value: '', - }, - { - UUID: '00000263-0000-1000-8000-0026BB765291', - constructorName: 'ConfigurationState', - displayName: 'Configuration State', - eventOnlyCharacteristic: false, - props: { - format: 'uint16', - perms: ['ev', 'pr'], - }, - value: 0, - }, - ], - constructorName: 'AccessCode', - displayName: 'AccessCode', - hiddenService: false, - optionalCharacteristics: [], - primaryService: false, - }, - AccessControl: { - UUID: '000000DA-0000-1000-8000-0026BB765291', - characteristics: [ - { - UUID: '000000E5-0000-1000-8000-0026BB765291', - constructorName: 'AccessControlLevel', - displayName: 'Access Control Level', - eventOnlyCharacteristic: false, - props: { - format: 'uint16', - maxValue: 2, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr', 'pw'], - }, - value: 0, - }, - ], - constructorName: 'AccessControl', - displayName: 'AccessControl', - hiddenService: false, - optionalCharacteristics: [ - { - UUID: '000000E4-0000-1000-8000-0026BB765291', - constructorName: 'PasswordSetting', - displayName: 'Password Setting', - eventOnlyCharacteristic: false, - props: { - format: 'tlv8', - perms: ['ev', 'pr', 'pw'], - }, - value: '', - }, - ], - primaryService: false, - }, - AccessoryInformation: { - UUID: '0000003E-0000-1000-8000-0026BB765291', - characteristics: [ - { - UUID: '00000014-0000-1000-8000-0026BB765291', - constructorName: 'Identify', - displayName: 'Identify', - eventOnlyCharacteristic: false, - props: { - format: 'bool', - perms: ['pw'], - }, - value: false, - }, - { - UUID: '00000020-0000-1000-8000-0026BB765291', - constructorName: 'Manufacturer', - displayName: 'Manufacturer', - eventOnlyCharacteristic: false, - props: { - format: 'string', - maxLen: 64, - perms: ['pr'], - }, - value: 'Default-Manufacturer', - }, - { - UUID: '00000021-0000-1000-8000-0026BB765291', - constructorName: 'Model', - displayName: 'Model', - eventOnlyCharacteristic: false, - props: { - format: 'string', - maxLen: 64, - perms: ['pr'], - }, - value: 'Default-Model', - }, - { - UUID: '00000023-0000-1000-8000-0026BB765291', - constructorName: 'Name', - displayName: 'Name', - eventOnlyCharacteristic: false, - props: { - format: 'string', - maxLen: 64, - perms: ['pr'], - }, - value: 'Unnamed Service', - }, - { - UUID: '00000030-0000-1000-8000-0026BB765291', - constructorName: 'SerialNumber', - displayName: 'Serial Number', - eventOnlyCharacteristic: false, - props: { - format: 'string', - maxLen: 64, - perms: ['pr'], - }, - value: 'Default-SerialNumber', - }, - { - UUID: '00000052-0000-1000-8000-0026BB765291', - constructorName: 'FirmwareRevision', - displayName: 'Firmware Revision', - eventOnlyCharacteristic: false, - props: { - format: 'string', - perms: ['pr'], - }, - value: '0.0.0', - }, - ], - constructorName: 'AccessoryInformation', - displayName: 'AccessoryInformation', - hiddenService: false, - optionalCharacteristics: [ - { - UUID: '000000A6-0000-1000-8000-0026BB765291', - constructorName: 'AccessoryFlags', - displayName: 'Accessory Flags', - eventOnlyCharacteristic: false, - props: { - format: 'uint32', - perms: ['ev', 'pr'], - }, - value: 0, - }, - { - UUID: '000000A4-0000-1000-8000-0026BB765291', - constructorName: 'AppMatchingIdentifier', - displayName: 'App Matching Identifier', - eventOnlyCharacteristic: false, - props: { - format: 'tlv8', - perms: ['pr'], - }, - value: '', - }, - { - UUID: '000000E3-0000-1000-8000-0026BB765291', - constructorName: 'ConfiguredName', - displayName: 'Configured Name', - eventOnlyCharacteristic: false, - props: { - format: 'string', - perms: ['ev', 'pr', 'pw'], - }, - value: '', - }, - { - UUID: '0000026D-0000-1000-8000-0026BB765291', - constructorName: 'MatterFirmwareRevisionNumber', - displayName: 'Matter Firmware Revision Number', - eventOnlyCharacteristic: false, - props: { - format: 'uint32', - perms: ['ev', 'pr'], - }, - value: 0, - }, - { - UUID: '0000026C-0000-1000-8000-0026BB765291', - constructorName: 'HardwareFinish', - displayName: 'Hardware Finish', - eventOnlyCharacteristic: false, - props: { - format: 'tlv8', - perms: ['pr'], - }, - value: '', - }, - { - UUID: '00000053-0000-1000-8000-0026BB765291', - constructorName: 'HardwareRevision', - displayName: 'Hardware Revision', - eventOnlyCharacteristic: false, - props: { - format: 'string', - perms: ['pr'], - }, - value: '', - }, - { - UUID: '00000220-0000-1000-8000-0026BB765291', - constructorName: 'ProductData', - displayName: 'Product Data', - eventOnlyCharacteristic: false, - props: { - format: 'data', - perms: ['pr'], - }, - value: '', - }, - { - UUID: '00000054-0000-1000-8000-0026BB765291', - constructorName: 'SoftwareRevision', - displayName: 'Software Revision', - eventOnlyCharacteristic: false, - props: { - format: 'string', - perms: ['pr'], - }, - value: '', - }, - ], - primaryService: false, - }, - AccessoryMetrics: { - UUID: '00000270-0000-1000-8000-0026BB765291', - characteristics: [ - { - UUID: '000000B0-0000-1000-8000-0026BB765291', - constructorName: 'Active', - displayName: 'Active', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr', 'pw'], - validValues: [0, 1], - }, - value: 0, - }, - { - UUID: '00000272-0000-1000-8000-0026BB765291', - constructorName: 'MetricsBufferFullState', - displayName: 'Metrics Buffer Full State', - eventOnlyCharacteristic: false, - props: { - format: 'bool', - perms: ['ev', 'pr'], - }, - value: false, - }, - { - UUID: '00000271-0000-1000-8000-0026BB765291', - constructorName: 'SupportedMetrics', - displayName: 'Supported Metrics', - eventOnlyCharacteristic: false, - props: { - format: 'tlv8', - perms: ['pr', 'pw'], - }, - value: '', - }, - ], - constructorName: 'AccessoryMetrics', - displayName: 'AccessoryMetrics', - hiddenService: false, - optionalCharacteristics: [], - primaryService: false, - }, - AccessoryRuntimeInformation: { - UUID: '00000239-0000-1000-8000-0026BB765291', - characteristics: [ - { - UUID: '0000023C-0000-1000-8000-0026BB765291', - constructorName: 'Ping', - displayName: 'Ping', - eventOnlyCharacteristic: false, - props: { - format: 'data', - perms: ['pr'], - }, - value: '', - }, - ], - constructorName: 'AccessoryRuntimeInformation', - displayName: 'AccessoryRuntimeInformation', - hiddenService: false, - optionalCharacteristics: [ - { - UUID: '0000023B-0000-1000-8000-0026BB765291', - constructorName: 'ActivityInterval', - displayName: 'Activity Interval', - eventOnlyCharacteristic: false, - props: { - format: 'uint32', - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - }, - value: 0, - }, - { - UUID: '0000024A-0000-1000-8000-0026BB765291', - constructorName: 'HeartBeat', - displayName: 'Heart Beat', - eventOnlyCharacteristic: false, - props: { - format: 'uint32', - perms: ['ev', 'pr'], - }, - value: 0, - }, - { - UUID: '0000023A-0000-1000-8000-0026BB765291', - constructorName: 'SleepInterval', - displayName: 'Sleep Interval', - eventOnlyCharacteristic: false, - props: { - format: 'uint32', - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - }, - value: 0, - }, - ], - primaryService: false, - }, - AirPurifier: { - UUID: '000000BB-0000-1000-8000-0026BB765291', - characteristics: [ - { - UUID: '000000B0-0000-1000-8000-0026BB765291', - constructorName: 'Active', - displayName: 'Active', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr', 'pw'], - validValues: [0, 1], - }, - value: 0, - }, - { - UUID: '000000A9-0000-1000-8000-0026BB765291', - constructorName: 'CurrentAirPurifierState', - displayName: 'Current Air Purifier State', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 2, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - validValues: [0, 1, 2], - }, - value: 0, - }, - { - UUID: '000000A8-0000-1000-8000-0026BB765291', - constructorName: 'TargetAirPurifierState', - displayName: 'Target Air Purifier State', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr', 'pw'], - validValues: [0, 1], - }, - value: 0, - }, - ], - constructorName: 'AirPurifier', - displayName: 'AirPurifier', - hiddenService: false, - optionalCharacteristics: [ - { - UUID: '000000A7-0000-1000-8000-0026BB765291', - constructorName: 'LockPhysicalControls', - displayName: 'Lock Physical Controls', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr', 'pw'], - validValues: [0, 1], - }, - value: 0, - }, - { - UUID: '00000023-0000-1000-8000-0026BB765291', - constructorName: 'Name', - displayName: 'Name', - eventOnlyCharacteristic: false, - props: { - format: 'string', - maxLen: 64, - perms: ['pr'], - }, - value: '', - }, - { - UUID: '00000029-0000-1000-8000-0026BB765291', - constructorName: 'RotationSpeed', - displayName: 'Rotation Speed', - eventOnlyCharacteristic: false, - props: { - format: 'float', - maxValue: 100, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr', 'pw'], - unit: 'percentage', - }, - value: 0, - }, - { - UUID: '000000B6-0000-1000-8000-0026BB765291', - constructorName: 'SwingMode', - displayName: 'Swing Mode', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr', 'pw'], - validValues: [0, 1], - }, - value: 0, - }, - ], - primaryService: false, - }, - AirQualitySensor: { - UUID: '0000008D-0000-1000-8000-0026BB765291', - characteristics: [ - { - UUID: '00000095-0000-1000-8000-0026BB765291', - constructorName: 'AirQuality', - displayName: 'Air Quality', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 5, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - validValues: [0, 1, 2, 3, 4, 5], - }, - value: 0, - }, - ], - constructorName: 'AirQualitySensor', - displayName: 'AirQualitySensor', - hiddenService: false, - optionalCharacteristics: [ - { - UUID: '000000C4-0000-1000-8000-0026BB765291', - constructorName: 'NitrogenDioxideDensity', - displayName: 'Nitrogen Dioxide Density', - eventOnlyCharacteristic: false, - props: { - format: 'float', - maxValue: 1000, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - }, - value: 0, - }, - { - UUID: '000000C3-0000-1000-8000-0026BB765291', - constructorName: 'OzoneDensity', - displayName: 'Ozone Density', - eventOnlyCharacteristic: false, - props: { - format: 'float', - maxValue: 1000, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - }, - value: 0, - }, - { - UUID: '000000C7-0000-1000-8000-0026BB765291', - constructorName: 'PM10Density', - displayName: 'PM10 Density', - eventOnlyCharacteristic: false, - props: { - format: 'float', - maxValue: 1000, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - }, - value: 0, - }, - { - UUID: '000000C6-0000-1000-8000-0026BB765291', - constructorName: 'PM2_5Density', - displayName: 'PM2.5 Density', - eventOnlyCharacteristic: false, - props: { - format: 'float', - maxValue: 1000, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - }, - value: 0, - }, - { - UUID: '000000C5-0000-1000-8000-0026BB765291', - constructorName: 'SulphurDioxideDensity', - displayName: 'Sulphur Dioxide Density', - eventOnlyCharacteristic: false, - props: { - format: 'float', - maxValue: 1000, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - }, - value: 0, - }, - { - UUID: '000000C8-0000-1000-8000-0026BB765291', - constructorName: 'VOCDensity', - displayName: 'VOC Density', - eventOnlyCharacteristic: false, - props: { - format: 'float', - maxValue: 1000, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - }, - value: 0, - }, - { - UUID: '00000023-0000-1000-8000-0026BB765291', - constructorName: 'Name', - displayName: 'Name', - eventOnlyCharacteristic: false, - props: { - format: 'string', - maxLen: 64, - perms: ['pr'], - }, - value: '', - }, - { - UUID: '00000075-0000-1000-8000-0026BB765291', - constructorName: 'StatusActive', - displayName: 'Status Active', - eventOnlyCharacteristic: false, - props: { - format: 'bool', - perms: ['ev', 'pr'], - }, - value: false, - }, - { - UUID: '00000077-0000-1000-8000-0026BB765291', - constructorName: 'StatusFault', - displayName: 'Status Fault', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - validValues: [0, 1], - }, - value: 0, - }, - { - UUID: '00000079-0000-1000-8000-0026BB765291', - constructorName: 'StatusLowBattery', - displayName: 'Status Low Battery', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - validValues: [0, 1], - }, - value: 0, - }, - { - UUID: '0000007A-0000-1000-8000-0026BB765291', - constructorName: 'StatusTampered', - displayName: 'Status Tampered', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - validValues: [0, 1], - }, - value: 0, - }, - ], - primaryService: false, - }, - AssetUpdate: { - UUID: '00000267-0000-1000-8000-0026BB765291', - characteristics: [ - { - UUID: '00000269-0000-1000-8000-0026BB765291', - constructorName: 'AssetUpdateReadiness', - displayName: 'Asset Update Readiness', - eventOnlyCharacteristic: false, - props: { - format: 'uint32', - perms: ['ev', 'pr'], - }, - value: 0, - }, - { - UUID: '00000268-0000-1000-8000-0026BB765291', - constructorName: 'SupportedAssetTypes', - displayName: 'Supported Asset Types', - eventOnlyCharacteristic: false, - props: { - format: 'uint32', - perms: ['pr'], - }, - value: 0, - }, - ], - constructorName: 'AssetUpdate', - displayName: 'AssetUpdate', - hiddenService: false, - optionalCharacteristics: [], - primaryService: false, - }, - Assistant: { - UUID: '0000026A-0000-1000-8000-0026BB765291', - characteristics: [ - { - UUID: '000000B0-0000-1000-8000-0026BB765291', - constructorName: 'Active', - displayName: 'Active', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr', 'pw'], - validValues: [0, 1], - }, - value: 0, - }, - { - UUID: '000000E6-0000-1000-8000-0026BB765291', - constructorName: 'Identifier', - displayName: 'Identifier', - eventOnlyCharacteristic: false, - props: { - format: 'uint32', - perms: ['pr'], - }, - value: 0, - }, - { - UUID: '00000023-0000-1000-8000-0026BB765291', - constructorName: 'Name', - displayName: 'Name', - eventOnlyCharacteristic: false, - props: { - format: 'string', - maxLen: 64, - perms: ['pr'], - }, - value: 'Unnamed Service', - }, - ], - constructorName: 'Assistant', - displayName: 'Assistant', - hiddenService: false, - optionalCharacteristics: [], - primaryService: false, - }, - AudioStreamManagement: { - UUID: '00000127-0000-1000-8000-0026BB765291', - characteristics: [ - { - UUID: '00000115-0000-1000-8000-0026BB765291', - constructorName: 'SupportedAudioStreamConfiguration', - displayName: 'Supported Audio Stream Configuration', - eventOnlyCharacteristic: false, - props: { - format: 'tlv8', - perms: ['pr'], - }, - value: '', - }, - { - UUID: '00000128-0000-1000-8000-0026BB765291', - constructorName: 'SelectedAudioStreamConfiguration', - displayName: 'Selected Audio Stream Configuration', - eventOnlyCharacteristic: false, - props: { - format: 'tlv8', - perms: ['pr', 'pw'], - }, - value: '', - }, - ], - constructorName: 'AudioStreamManagement', - displayName: 'AudioStreamManagement', - hiddenService: false, - optionalCharacteristics: [], - primaryService: false, - }, - Battery: { - UUID: '00000096-0000-1000-8000-0026BB765291', - characteristics: [ - { - UUID: '00000079-0000-1000-8000-0026BB765291', - constructorName: 'StatusLowBattery', - displayName: 'Status Low Battery', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - validValues: [0, 1], - }, - value: 0, - }, - ], - constructorName: 'Battery', - displayName: 'Battery', - hiddenService: false, - optionalCharacteristics: [ - { - UUID: '00000068-0000-1000-8000-0026BB765291', - constructorName: 'BatteryLevel', - displayName: 'Battery Level', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 100, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - unit: 'percentage', - }, - value: 0, - }, - { - UUID: '0000008F-0000-1000-8000-0026BB765291', - constructorName: 'ChargingState', - displayName: 'Charging State', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 2, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - validValues: [0, 1, 2], - }, - value: 0, - }, - { - UUID: '00000023-0000-1000-8000-0026BB765291', - constructorName: 'Name', - displayName: 'Name', - eventOnlyCharacteristic: false, - props: { - format: 'string', - maxLen: 64, - perms: ['pr'], - }, - value: '', - }, - ], - primaryService: false, - }, - BatteryService: { - nrchkbDisabledText: 'BatteryService (deprecated, replaced by Battery)', - }, - BridgeConfiguration: { - nrchkbDisabledText: 'BridgeConfiguration (deprecated, unused)', - }, - BridgingState: { - nrchkbDisabledText: 'BridgingState (deprecated, unused)', - }, - CameraControl: { - nrchkbDisabledText: 'CameraControl (deprecated, replaced by)', - }, - CameraEventRecordingManagement: { - nrchkbDisabledText: - 'CameraEventRecordingManagement (deprecated, replaced by CameraRecordingManagement)', - }, - CameraOperatingMode: { - UUID: '0000021A-0000-1000-8000-0026BB765291', - characteristics: [ - { - UUID: '00000223-0000-1000-8000-0026BB765291', - constructorName: 'EventSnapshotsActive', - displayName: 'Event Snapshots Active', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minValue: 0, - perms: ['ev', 'pr', 'pw'], - validValues: [0, 1], - }, - value: 0, - }, - { - UUID: '0000021B-0000-1000-8000-0026BB765291', - constructorName: 'HomeKitCameraActive', - displayName: 'HomeKit Camera Active', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minValue: 0, - perms: ['ev', 'pr', 'pw'], - validValues: [0, 1], - }, - value: 0, - }, - ], - constructorName: 'CameraOperatingMode', - displayName: 'CameraOperatingMode', - hiddenService: false, - optionalCharacteristics: [ - { - UUID: '0000021D-0000-1000-8000-0026BB765291', - constructorName: 'CameraOperatingModeIndicator', - displayName: 'Camera Operating Mode Indicator', - eventOnlyCharacteristic: false, - props: { - format: 'bool', - perms: ['ev', 'pr', 'pw', 'tw'], - }, - value: false, - }, - { - UUID: '00000227-0000-1000-8000-0026BB765291', - constructorName: 'ManuallyDisabled', - displayName: 'Manually Disabled', - eventOnlyCharacteristic: false, - props: { - format: 'bool', - perms: ['ev', 'pr'], - }, - value: false, - }, - { - UUID: '0000011B-0000-1000-8000-0026BB765291', - constructorName: 'NightVision', - displayName: 'Night Vision', - eventOnlyCharacteristic: false, - props: { - format: 'bool', - perms: ['ev', 'pr', 'pw', 'tw'], - }, - value: false, - }, - { - UUID: '00000225-0000-1000-8000-0026BB765291', - constructorName: 'PeriodicSnapshotsActive', - displayName: 'Periodic Snapshots Active', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - perms: ['ev', 'pr', 'pw'], - validValues: [0, 1], - }, - value: 0, - }, - { - UUID: '0000021C-0000-1000-8000-0026BB765291', - constructorName: 'ThirdPartyCameraActive', - displayName: 'Third Party Camera Active', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - perms: ['ev', 'pr'], - validValues: [0, 1], - }, - value: 0, - }, - { - UUID: '00000224-0000-1000-8000-0026BB765291', - constructorName: 'DiagonalFieldOfView', - displayName: 'Diagonal Field Of View', - eventOnlyCharacteristic: false, - props: { - format: 'float', - maxValue: 360, - minValue: 0, - perms: ['ev', 'pr'], - unit: 'arcdegrees', - }, - value: 0, - }, - ], - primaryService: false, - }, - CameraRTPStreamManagement: { - UUID: '00000110-0000-1000-8000-0026BB765291', - characteristics: [ - { - UUID: '00000117-0000-1000-8000-0026BB765291', - constructorName: 'SelectedRTPStreamConfiguration', - displayName: 'Selected RTP Stream Configuration', - eventOnlyCharacteristic: false, - props: { - format: 'tlv8', - perms: ['pr', 'pw'], - }, - value: '', - }, - { - UUID: '00000118-0000-1000-8000-0026BB765291', - constructorName: 'SetupEndpoints', - displayName: 'Setup Endpoints', - eventOnlyCharacteristic: false, - props: { - format: 'tlv8', - perms: ['pr', 'pw'], - }, - value: '', - }, - { - UUID: '00000120-0000-1000-8000-0026BB765291', - constructorName: 'StreamingStatus', - displayName: 'Streaming Status', - eventOnlyCharacteristic: false, - props: { - format: 'tlv8', - perms: ['ev', 'pr'], - }, - value: '', - }, - { - UUID: '00000115-0000-1000-8000-0026BB765291', - constructorName: 'SupportedAudioStreamConfiguration', - displayName: 'Supported Audio Stream Configuration', - eventOnlyCharacteristic: false, - props: { - format: 'tlv8', - perms: ['pr'], - }, - value: '', - }, - { - UUID: '00000116-0000-1000-8000-0026BB765291', - constructorName: 'SupportedRTPConfiguration', - displayName: 'Supported RTP Configuration', - eventOnlyCharacteristic: false, - props: { - format: 'tlv8', - perms: ['pr'], - }, - value: '', - }, - { - UUID: '00000114-0000-1000-8000-0026BB765291', - constructorName: 'SupportedVideoStreamConfiguration', - displayName: 'Supported Video Stream Configuration', - eventOnlyCharacteristic: false, - props: { - format: 'tlv8', - perms: ['pr'], - }, - value: '', - }, - ], - constructorName: 'CameraRTPStreamManagement', - displayName: 'CameraRTPStreamManagement', - hiddenService: false, - optionalCharacteristics: [ - { - UUID: '000000B0-0000-1000-8000-0026BB765291', - constructorName: 'Active', - displayName: 'Active', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr', 'pw'], - validValues: [0, 1], - }, - value: 0, - }, - ], - primaryService: false, - }, - CameraRecordingManagement: { - UUID: '00000204-0000-1000-8000-0026BB765291', - characteristics: [ - { - UUID: '000000B0-0000-1000-8000-0026BB765291', - constructorName: 'Active', - displayName: 'Active', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr', 'pw'], - validValues: [0, 1], - }, - value: 0, - }, - { - UUID: '00000209-0000-1000-8000-0026BB765291', - constructorName: 'SelectedCameraRecordingConfiguration', - displayName: 'Selected Camera Recording Configuration', - eventOnlyCharacteristic: false, - props: { - format: 'tlv8', - perms: ['ev', 'pr', 'pw'], - }, - value: '', - }, - { - UUID: '00000207-0000-1000-8000-0026BB765291', - constructorName: 'SupportedAudioRecordingConfiguration', - displayName: 'Supported Audio Recording Configuration', - eventOnlyCharacteristic: false, - props: { - format: 'tlv8', - perms: ['ev', 'pr'], - }, - value: '', - }, - { - UUID: '00000205-0000-1000-8000-0026BB765291', - constructorName: 'SupportedCameraRecordingConfiguration', - displayName: 'Supported Camera Recording Configuration', - eventOnlyCharacteristic: false, - props: { - format: 'tlv8', - perms: ['ev', 'pr'], - }, - value: '', - }, - { - UUID: '00000206-0000-1000-8000-0026BB765291', - constructorName: 'SupportedVideoRecordingConfiguration', - displayName: 'Supported Video Recording Configuration', - eventOnlyCharacteristic: false, - props: { - format: 'tlv8', - perms: ['ev', 'pr'], - }, - value: '', - }, - ], - constructorName: 'CameraRecordingManagement', - displayName: 'CameraRecordingManagement', - hiddenService: false, - optionalCharacteristics: [ - { - UUID: '00000226-0000-1000-8000-0026BB765291', - constructorName: 'RecordingAudioActive', - displayName: 'Recording Audio Active', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - perms: ['ev', 'pr', 'pw', 'tw'], - validValues: [0, 1], - }, - value: 0, - }, - ], - primaryService: false, - }, - CarbonDioxideSensor: { - UUID: '00000097-0000-1000-8000-0026BB765291', - characteristics: [ - { - UUID: '00000092-0000-1000-8000-0026BB765291', - constructorName: 'CarbonDioxideDetected', - displayName: 'Carbon Dioxide Detected', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - validValues: [0, 1], - }, - value: 0, - }, - ], - constructorName: 'CarbonDioxideSensor', - displayName: 'CarbonDioxideSensor', - hiddenService: false, - optionalCharacteristics: [ - { - UUID: '00000093-0000-1000-8000-0026BB765291', - constructorName: 'CarbonDioxideLevel', - displayName: 'Carbon Dioxide Level', - eventOnlyCharacteristic: false, - props: { - format: 'float', - maxValue: 100000, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - }, - value: 0, - }, - { - UUID: '00000094-0000-1000-8000-0026BB765291', - constructorName: 'CarbonDioxidePeakLevel', - displayName: 'Carbon Dioxide Peak Level', - eventOnlyCharacteristic: false, - props: { - format: 'float', - maxValue: 100000, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - }, - value: 0, - }, - { - UUID: '00000023-0000-1000-8000-0026BB765291', - constructorName: 'Name', - displayName: 'Name', - eventOnlyCharacteristic: false, - props: { - format: 'string', - maxLen: 64, - perms: ['pr'], - }, - value: '', - }, - { - UUID: '00000075-0000-1000-8000-0026BB765291', - constructorName: 'StatusActive', - displayName: 'Status Active', - eventOnlyCharacteristic: false, - props: { - format: 'bool', - perms: ['ev', 'pr'], - }, - value: false, - }, - { - UUID: '00000077-0000-1000-8000-0026BB765291', - constructorName: 'StatusFault', - displayName: 'Status Fault', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - validValues: [0, 1], - }, - value: 0, - }, - { - UUID: '00000079-0000-1000-8000-0026BB765291', - constructorName: 'StatusLowBattery', - displayName: 'Status Low Battery', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - validValues: [0, 1], - }, - value: 0, - }, - { - UUID: '0000007A-0000-1000-8000-0026BB765291', - constructorName: 'StatusTampered', - displayName: 'Status Tampered', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - validValues: [0, 1], - }, - value: 0, - }, - ], - primaryService: false, - }, - CarbonMonoxideSensor: { - UUID: '0000007F-0000-1000-8000-0026BB765291', - characteristics: [ - { - UUID: '00000069-0000-1000-8000-0026BB765291', - constructorName: 'CarbonMonoxideDetected', - displayName: 'Carbon Monoxide Detected', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - validValues: [0, 1], - }, - value: 0, - }, - ], - constructorName: 'CarbonMonoxideSensor', - displayName: 'CarbonMonoxideSensor', - hiddenService: false, - optionalCharacteristics: [ - { - UUID: '00000090-0000-1000-8000-0026BB765291', - constructorName: 'CarbonMonoxideLevel', - displayName: 'Carbon Monoxide Level', - eventOnlyCharacteristic: false, - props: { - format: 'float', - maxValue: 100, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - }, - value: 0, - }, - { - UUID: '00000091-0000-1000-8000-0026BB765291', - constructorName: 'CarbonMonoxidePeakLevel', - displayName: 'Carbon Monoxide Peak Level', - eventOnlyCharacteristic: false, - props: { - format: 'float', - maxValue: 100, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - }, - value: 0, - }, - { - UUID: '00000023-0000-1000-8000-0026BB765291', - constructorName: 'Name', - displayName: 'Name', - eventOnlyCharacteristic: false, - props: { - format: 'string', - maxLen: 64, - perms: ['pr'], - }, - value: '', - }, - { - UUID: '00000075-0000-1000-8000-0026BB765291', - constructorName: 'StatusActive', - displayName: 'Status Active', - eventOnlyCharacteristic: false, - props: { - format: 'bool', - perms: ['ev', 'pr'], - }, - value: false, - }, - { - UUID: '00000077-0000-1000-8000-0026BB765291', - constructorName: 'StatusFault', - displayName: 'Status Fault', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - validValues: [0, 1], - }, - value: 0, - }, - { - UUID: '00000079-0000-1000-8000-0026BB765291', - constructorName: 'StatusLowBattery', - displayName: 'Status Low Battery', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - validValues: [0, 1], - }, - value: 0, - }, - { - UUID: '0000007A-0000-1000-8000-0026BB765291', - constructorName: 'StatusTampered', - displayName: 'Status Tampered', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - validValues: [0, 1], - }, - value: 0, - }, - ], - primaryService: false, - }, - CloudRelay: { - UUID: '0000005A-0000-1000-8000-0026BB765291', - characteristics: [ - { - UUID: '0000005E-0000-1000-8000-0026BB765291', - constructorName: 'RelayControlPoint', - displayName: 'Relay Control Point', - eventOnlyCharacteristic: false, - props: { - format: 'tlv8', - perms: ['ev', 'pr', 'pw'], - }, - value: '', - }, - { - UUID: '0000005C-0000-1000-8000-0026BB765291', - constructorName: 'RelayState', - displayName: 'Relay State', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 5, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - }, - value: 0, - }, - { - UUID: '0000005B-0000-1000-8000-0026BB765291', - constructorName: 'RelayEnabled', - displayName: 'Relay Enabled', - eventOnlyCharacteristic: false, - props: { - format: 'bool', - perms: ['ev', 'pr', 'pw'], - }, - value: false, - }, - ], - constructorName: 'CloudRelay', - displayName: 'CloudRelay', - hiddenService: false, - optionalCharacteristics: [], - primaryService: false, - }, - ContactSensor: { - UUID: '00000080-0000-1000-8000-0026BB765291', - characteristics: [ - { - UUID: '0000006A-0000-1000-8000-0026BB765291', - constructorName: 'ContactSensorState', - displayName: 'Contact Sensor State', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - validValues: [0, 1], - }, - value: 0, - }, - ], - constructorName: 'ContactSensor', - displayName: 'ContactSensor', - hiddenService: false, - optionalCharacteristics: [ - { - UUID: '00000023-0000-1000-8000-0026BB765291', - constructorName: 'Name', - displayName: 'Name', - eventOnlyCharacteristic: false, - props: { - format: 'string', - maxLen: 64, - perms: ['pr'], - }, - value: '', - }, - { - UUID: '00000075-0000-1000-8000-0026BB765291', - constructorName: 'StatusActive', - displayName: 'Status Active', - eventOnlyCharacteristic: false, - props: { - format: 'bool', - perms: ['ev', 'pr'], - }, - value: false, - }, - { - UUID: '00000077-0000-1000-8000-0026BB765291', - constructorName: 'StatusFault', - displayName: 'Status Fault', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - validValues: [0, 1], - }, - value: 0, - }, - { - UUID: '00000079-0000-1000-8000-0026BB765291', - constructorName: 'StatusLowBattery', - displayName: 'Status Low Battery', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - validValues: [0, 1], - }, - value: 0, - }, - { - UUID: '0000007A-0000-1000-8000-0026BB765291', - constructorName: 'StatusTampered', - displayName: 'Status Tampered', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - validValues: [0, 1], - }, - value: 0, - }, - ], - primaryService: false, - }, - DataStreamTransportManagement: { - UUID: '00000129-0000-1000-8000-0026BB765291', - characteristics: [ - { - UUID: '00000131-0000-1000-8000-0026BB765291', - constructorName: 'SetupDataStreamTransport', - displayName: 'Setup Data Stream Transport', - eventOnlyCharacteristic: false, - props: { - format: 'tlv8', - perms: ['pr', 'pw', 'wr'], - }, - value: '', - }, - { - UUID: '00000130-0000-1000-8000-0026BB765291', - constructorName: 'SupportedDataStreamTransportConfiguration', - displayName: 'Supported Data Stream Transport Configuration', - eventOnlyCharacteristic: false, - props: { - format: 'tlv8', - perms: ['pr'], - }, - value: '', - }, - { - UUID: '00000037-0000-1000-8000-0026BB765291', - constructorName: 'Version', - displayName: 'Version', - eventOnlyCharacteristic: false, - props: { - format: 'string', - maxLen: 64, - perms: ['pr'], - }, - value: '', - }, - ], - constructorName: 'DataStreamTransportManagement', - displayName: 'DataStreamTransportManagement', - hiddenService: false, - optionalCharacteristics: [], - primaryService: false, - }, - Diagnostics: { - UUID: '00000237-0000-1000-8000-0026BB765291', - characteristics: [ - { - UUID: '00000238-0000-1000-8000-0026BB765291', - constructorName: 'SupportedDiagnosticsSnapshot', - displayName: 'Supported Diagnostics Snapshot', - eventOnlyCharacteristic: false, - props: { - format: 'tlv8', - perms: ['pr'], - }, - value: '', - }, - ], - constructorName: 'Diagnostics', - displayName: 'Diagnostics', - hiddenService: false, - optionalCharacteristics: [ - { - UUID: '0000024D-0000-1000-8000-0026BB765291', - constructorName: 'SelectedDiagnosticsModes', - displayName: 'Selected Diagnostics Modes', - eventOnlyCharacteristic: false, - props: { - format: 'uint32', - perms: ['pr', 'pw'], - }, - value: 0, - }, - { - UUID: '0000024C-0000-1000-8000-0026BB765291', - constructorName: 'SupportedDiagnosticsModes', - displayName: 'Supported Diagnostics Modes', - eventOnlyCharacteristic: false, - props: { - format: 'uint32', - perms: ['pr'], - }, - value: 0, - }, - ], - primaryService: false, - }, - Door: { - UUID: '00000081-0000-1000-8000-0026BB765291', - characteristics: [ - { - UUID: '0000006D-0000-1000-8000-0026BB765291', - constructorName: 'CurrentPosition', - displayName: 'Current Position', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 100, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - unit: 'percentage', - }, - value: 0, - }, - { - UUID: '00000072-0000-1000-8000-0026BB765291', - constructorName: 'PositionState', - displayName: 'Position State', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 2, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - validValues: [0, 1, 2], - }, - value: 0, - }, - { - UUID: '0000007C-0000-1000-8000-0026BB765291', - constructorName: 'TargetPosition', - displayName: 'Target Position', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 100, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr', 'pw'], - unit: 'percentage', - }, - value: 0, - }, - ], - constructorName: 'Door', - displayName: 'Door', - hiddenService: false, - optionalCharacteristics: [ - { - UUID: '00000023-0000-1000-8000-0026BB765291', - constructorName: 'Name', - displayName: 'Name', - eventOnlyCharacteristic: false, - props: { - format: 'string', - maxLen: 64, - perms: ['pr'], - }, - value: '', - }, - { - UUID: '00000024-0000-1000-8000-0026BB765291', - constructorName: 'ObstructionDetected', - displayName: 'Obstruction Detected', - eventOnlyCharacteristic: false, - props: { - format: 'bool', - perms: ['ev', 'pr'], - }, - value: false, - }, - { - UUID: '0000006F-0000-1000-8000-0026BB765291', - constructorName: 'HoldPosition', - displayName: 'Hold Position', - eventOnlyCharacteristic: false, - props: { - format: 'bool', - perms: ['pw'], - }, - value: false, - }, - ], - primaryService: false, - }, - Doorbell: { - UUID: '00000121-0000-1000-8000-0026BB765291', - characteristics: [ - { - UUID: '00000073-0000-1000-8000-0026BB765291', - constructorName: 'ProgrammableSwitchEvent', - displayName: 'Programmable Switch Event', - eventOnlyCharacteristic: true, - props: { - format: 'uint8', - maxValue: 2, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - validValues: [0, 1, 2], - }, - value: 0, - }, - ], - constructorName: 'Doorbell', - displayName: 'Doorbell', - hiddenService: false, - optionalCharacteristics: [ - { - UUID: '00000008-0000-1000-8000-0026BB765291', - constructorName: 'Brightness', - displayName: 'Brightness', - eventOnlyCharacteristic: false, - props: { - format: 'int', - maxValue: 100, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr', 'pw'], - unit: 'percentage', - }, - value: 0, - }, - { - UUID: '0000011A-0000-1000-8000-0026BB765291', - constructorName: 'Mute', - displayName: 'Mute', - eventOnlyCharacteristic: false, - props: { - format: 'bool', - perms: ['ev', 'pr', 'pw'], - }, - value: false, - }, - { - UUID: '00000023-0000-1000-8000-0026BB765291', - constructorName: 'Name', - displayName: 'Name', - eventOnlyCharacteristic: false, - props: { - format: 'string', - maxLen: 64, - perms: ['pr'], - }, - value: '', - }, - { - UUID: '00000232-0000-1000-8000-0026BB765291', - constructorName: 'OperatingStateResponse', - displayName: 'Operating State Response', - eventOnlyCharacteristic: false, - props: { - format: 'tlv8', - perms: ['ev', 'pr'], - }, - value: '', - }, - { - UUID: '00000119-0000-1000-8000-0026BB765291', - constructorName: 'Volume', - displayName: 'Volume', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 100, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr', 'pw'], - unit: 'percentage', - }, - value: 0, - }, - ], - primaryService: false, - }, - Fan: { - UUID: '00000040-0000-1000-8000-0026BB765291', - characteristics: [ - { - UUID: '00000025-0000-1000-8000-0026BB765291', - constructorName: 'On', - displayName: 'On', - eventOnlyCharacteristic: false, - props: { - format: 'bool', - perms: ['ev', 'pr', 'pw'], - }, - value: false, - }, - ], - constructorName: 'Fan', - displayName: 'Fan', - hiddenService: false, - optionalCharacteristics: [ - { - UUID: '00000023-0000-1000-8000-0026BB765291', - constructorName: 'Name', - displayName: 'Name', - eventOnlyCharacteristic: false, - props: { - format: 'string', - maxLen: 64, - perms: ['pr'], - }, - value: '', - }, - { - UUID: '00000028-0000-1000-8000-0026BB765291', - constructorName: 'RotationDirection', - displayName: 'Rotation Direction', - eventOnlyCharacteristic: false, - props: { - format: 'int', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr', 'pw'], - validValues: [0, 1], - }, - value: 0, - }, - { - UUID: '00000029-0000-1000-8000-0026BB765291', - constructorName: 'RotationSpeed', - displayName: 'Rotation Speed', - eventOnlyCharacteristic: false, - props: { - format: 'float', - maxValue: 100, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr', 'pw'], - unit: 'percentage', - }, - value: 0, - }, - ], - primaryService: false, - }, - Fanv2: { - UUID: '000000B7-0000-1000-8000-0026BB765291', - characteristics: [ - { - UUID: '000000B0-0000-1000-8000-0026BB765291', - constructorName: 'Active', - displayName: 'Active', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr', 'pw'], - validValues: [0, 1], - }, - value: 0, - }, - ], - constructorName: 'Fanv2', - displayName: 'Fanv2', - hiddenService: false, - optionalCharacteristics: [ - { - UUID: '000000AF-0000-1000-8000-0026BB765291', - constructorName: 'CurrentFanState', - displayName: 'Current Fan State', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 2, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - validValues: [0, 1, 2], - }, - value: 0, - }, - { - UUID: '000000BF-0000-1000-8000-0026BB765291', - constructorName: 'TargetFanState', - displayName: 'Target Fan State', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr', 'pw'], - validValues: [0, 1], - }, - value: 0, - }, - { - UUID: '000000A7-0000-1000-8000-0026BB765291', - constructorName: 'LockPhysicalControls', - displayName: 'Lock Physical Controls', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr', 'pw'], - validValues: [0, 1], - }, - value: 0, - }, - { - UUID: '00000023-0000-1000-8000-0026BB765291', - constructorName: 'Name', - displayName: 'Name', - eventOnlyCharacteristic: false, - props: { - format: 'string', - maxLen: 64, - perms: ['pr'], - }, - value: '', - }, - { - UUID: '00000028-0000-1000-8000-0026BB765291', - constructorName: 'RotationDirection', - displayName: 'Rotation Direction', - eventOnlyCharacteristic: false, - props: { - format: 'int', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr', 'pw'], - validValues: [0, 1], - }, - value: 0, - }, - { - UUID: '00000029-0000-1000-8000-0026BB765291', - constructorName: 'RotationSpeed', - displayName: 'Rotation Speed', - eventOnlyCharacteristic: false, - props: { - format: 'float', - maxValue: 100, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr', 'pw'], - unit: 'percentage', - }, - value: 0, - }, - { - UUID: '000000B6-0000-1000-8000-0026BB765291', - constructorName: 'SwingMode', - displayName: 'Swing Mode', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr', 'pw'], - validValues: [0, 1], - }, - value: 0, - }, - ], - primaryService: false, - }, - Faucet: { - UUID: '000000D7-0000-1000-8000-0026BB765291', - characteristics: [ - { - UUID: '000000B0-0000-1000-8000-0026BB765291', - constructorName: 'Active', - displayName: 'Active', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr', 'pw'], - validValues: [0, 1], - }, - value: 0, - }, - ], - constructorName: 'Faucet', - displayName: 'Faucet', - hiddenService: false, - optionalCharacteristics: [ - { - UUID: '00000023-0000-1000-8000-0026BB765291', - constructorName: 'Name', - displayName: 'Name', - eventOnlyCharacteristic: false, - props: { - format: 'string', - maxLen: 64, - perms: ['pr'], - }, - value: '', - }, - { - UUID: '00000077-0000-1000-8000-0026BB765291', - constructorName: 'StatusFault', - displayName: 'Status Fault', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - validValues: [0, 1], - }, - value: 0, - }, - ], - primaryService: false, - }, - FilterMaintenance: { - UUID: '000000BA-0000-1000-8000-0026BB765291', - characteristics: [ - { - UUID: '000000AC-0000-1000-8000-0026BB765291', - constructorName: 'FilterChangeIndication', - displayName: 'Filter Change Indication', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - validValues: [0, 1], - }, - value: 0, - }, - ], - constructorName: 'FilterMaintenance', - displayName: 'FilterMaintenance', - hiddenService: false, - optionalCharacteristics: [ - { - UUID: '000000AB-0000-1000-8000-0026BB765291', - constructorName: 'FilterLifeLevel', - displayName: 'Filter Life Level', - eventOnlyCharacteristic: false, - props: { - format: 'float', - maxValue: 100, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - }, - value: 0, - }, - { - UUID: '000000AD-0000-1000-8000-0026BB765291', - constructorName: 'ResetFilterIndication', - displayName: 'Reset Filter Indication', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 1, - perms: ['pw'], - }, - value: 1, - }, - { - UUID: '00000023-0000-1000-8000-0026BB765291', - constructorName: 'Name', - displayName: 'Name', - eventOnlyCharacteristic: false, - props: { - format: 'string', - maxLen: 64, - perms: ['pr'], - }, - value: '', - }, - ], - primaryService: false, - }, - FirmwareUpdate: { - UUID: '00000236-0000-1000-8000-0026BB765291', - characteristics: [ - { - UUID: '00000234-0000-1000-8000-0026BB765291', - constructorName: 'FirmwareUpdateReadiness', - displayName: 'Firmware Update Readiness', - eventOnlyCharacteristic: false, - props: { - format: 'tlv8', - perms: ['ev', 'pr'], - }, - value: '', - }, - { - UUID: '00000235-0000-1000-8000-0026BB765291', - constructorName: 'FirmwareUpdateStatus', - displayName: 'Firmware Update Status', - eventOnlyCharacteristic: false, - props: { - format: 'tlv8', - perms: ['ev', 'pr'], - }, - value: '', - }, - ], - constructorName: 'FirmwareUpdate', - displayName: 'FirmwareUpdate', - hiddenService: false, - optionalCharacteristics: [ - { - UUID: '0000026F-0000-1000-8000-0026BB765291', - constructorName: 'FirmwareUpdateProtocolList', - displayName: 'Firmware Update Protocol List', - eventOnlyCharacteristic: false, - props: { - format: 'tlv8', - perms: ['pr'], - }, - value: '', - }, - { - UUID: '0000026E-0000-1000-8000-0026BB765291', - constructorName: 'MatterFirmwareUpdateStatus', - displayName: 'Matter Firmware Update Status', - eventOnlyCharacteristic: false, - props: { - format: 'tlv8', - perms: ['ev', 'pr'], - }, - value: '', - }, - { - UUID: '00000249-0000-1000-8000-0026BB765291', - constructorName: 'StagedFirmwareVersion', - displayName: 'Staged Firmware Version', - eventOnlyCharacteristic: false, - props: { - format: 'string', - perms: ['ev', 'pr'], - }, - value: '', - }, - { - UUID: '00000233-0000-1000-8000-0026BB765291', - constructorName: 'SupportedFirmwareUpdateConfiguration', - displayName: 'Supported Firmware Update Configuration', - eventOnlyCharacteristic: false, - props: { - format: 'tlv8', - perms: ['pr'], - }, - value: '', - }, - ], - primaryService: false, - }, - GarageDoorOpener: { - UUID: '00000041-0000-1000-8000-0026BB765291', - characteristics: [ - { - UUID: '0000000E-0000-1000-8000-0026BB765291', - constructorName: 'CurrentDoorState', - displayName: 'Current Door State', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 4, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - validValues: [0, 1, 2, 3, 4], - }, - value: 0, - }, - { - UUID: '00000032-0000-1000-8000-0026BB765291', - constructorName: 'TargetDoorState', - displayName: 'Target Door State', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr', 'pw'], - validValues: [0, 1], - }, - value: 0, - }, - { - UUID: '00000024-0000-1000-8000-0026BB765291', - constructorName: 'ObstructionDetected', - displayName: 'Obstruction Detected', - eventOnlyCharacteristic: false, - props: { - format: 'bool', - perms: ['ev', 'pr'], - }, - value: false, - }, - ], - constructorName: 'GarageDoorOpener', - displayName: 'GarageDoorOpener', - hiddenService: false, - optionalCharacteristics: [ - { - UUID: '0000001D-0000-1000-8000-0026BB765291', - constructorName: 'LockCurrentState', - displayName: 'Lock Current State', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 3, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - validValues: [0, 1, 2, 3], - }, - value: 0, - }, - { - UUID: '0000001E-0000-1000-8000-0026BB765291', - constructorName: 'LockTargetState', - displayName: 'Lock Target State', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr', 'pw'], - validValues: [0, 1], - }, - value: 0, - }, - { - UUID: '00000023-0000-1000-8000-0026BB765291', - constructorName: 'Name', - displayName: 'Name', - eventOnlyCharacteristic: false, - props: { - format: 'string', - maxLen: 64, - perms: ['pr'], - }, - value: '', - }, - ], - primaryService: false, - }, - HeaterCooler: { - UUID: '000000BC-0000-1000-8000-0026BB765291', - characteristics: [ - { - UUID: '000000B0-0000-1000-8000-0026BB765291', - constructorName: 'Active', - displayName: 'Active', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr', 'pw'], - validValues: [0, 1], - }, - value: 0, - }, - { - UUID: '000000B1-0000-1000-8000-0026BB765291', - constructorName: 'CurrentHeaterCoolerState', - displayName: 'Current Heater-Cooler State', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 3, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - validValues: [0, 1, 2, 3], - }, - value: 0, - }, - { - UUID: '000000B2-0000-1000-8000-0026BB765291', - constructorName: 'TargetHeaterCoolerState', - displayName: 'Target Heater-Cooler State', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 2, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr', 'pw'], - validValues: [0, 1, 2], - }, - value: 0, - }, - { - UUID: '00000011-0000-1000-8000-0026BB765291', - constructorName: 'CurrentTemperature', - displayName: 'Current Temperature', - eventOnlyCharacteristic: false, - props: { - format: 'float', - maxValue: 100, - minStep: 0.1, - minValue: -270, - perms: ['ev', 'pr'], - unit: 'celsius', - }, - value: 0, - }, - ], - constructorName: 'HeaterCooler', - displayName: 'HeaterCooler', - hiddenService: false, - optionalCharacteristics: [ - { - UUID: '000000A7-0000-1000-8000-0026BB765291', - constructorName: 'LockPhysicalControls', - displayName: 'Lock Physical Controls', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr', 'pw'], - validValues: [0, 1], - }, - value: 0, - }, - { - UUID: '00000023-0000-1000-8000-0026BB765291', - constructorName: 'Name', - displayName: 'Name', - eventOnlyCharacteristic: false, - props: { - format: 'string', - maxLen: 64, - perms: ['pr'], - }, - value: '', - }, - { - UUID: '00000029-0000-1000-8000-0026BB765291', - constructorName: 'RotationSpeed', - displayName: 'Rotation Speed', - eventOnlyCharacteristic: false, - props: { - format: 'float', - maxValue: 100, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr', 'pw'], - unit: 'percentage', - }, - value: 0, - }, - { - UUID: '000000B6-0000-1000-8000-0026BB765291', - constructorName: 'SwingMode', - displayName: 'Swing Mode', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr', 'pw'], - validValues: [0, 1], - }, - value: 0, - }, - { - UUID: '0000000D-0000-1000-8000-0026BB765291', - constructorName: 'CoolingThresholdTemperature', - displayName: 'Cooling Threshold Temperature', - eventOnlyCharacteristic: false, - props: { - format: 'float', - maxValue: 35, - minStep: 0.1, - minValue: 10, - perms: ['ev', 'pr', 'pw'], - unit: 'celsius', - }, - value: 10, - }, - { - UUID: '00000012-0000-1000-8000-0026BB765291', - constructorName: 'HeatingThresholdTemperature', - displayName: 'Heating Threshold Temperature', - eventOnlyCharacteristic: false, - props: { - format: 'float', - maxValue: 25, - minStep: 0.1, - minValue: 0, - perms: ['ev', 'pr', 'pw'], - unit: 'celsius', - }, - value: 0, - }, - { - UUID: '00000036-0000-1000-8000-0026BB765291', - constructorName: 'TemperatureDisplayUnits', - displayName: 'Temperature Display Units', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr', 'pw'], - validValues: [0, 1], - }, - value: 0, - }, - ], - primaryService: false, - }, - HumidifierDehumidifier: { - UUID: '000000BD-0000-1000-8000-0026BB765291', - characteristics: [ - { - UUID: '000000B0-0000-1000-8000-0026BB765291', - constructorName: 'Active', - displayName: 'Active', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr', 'pw'], - validValues: [0, 1], - }, - value: 0, - }, - { - UUID: '000000B3-0000-1000-8000-0026BB765291', - constructorName: 'CurrentHumidifierDehumidifierState', - displayName: 'Current Humidifier-Dehumidifier State', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 3, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - validValues: [0, 1, 2, 3], - }, - value: 0, - }, - { - UUID: '000000B4-0000-1000-8000-0026BB765291', - constructorName: 'TargetHumidifierDehumidifierState', - displayName: 'Target Humidifier-Dehumidifier State', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 2, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr', 'pw'], - validValues: [0, 1, 2], - }, - value: 0, - }, - { - UUID: '00000010-0000-1000-8000-0026BB765291', - constructorName: 'CurrentRelativeHumidity', - displayName: 'Current Relative Humidity', - eventOnlyCharacteristic: false, - props: { - format: 'float', - maxValue: 100, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - unit: 'percentage', - }, - value: 0, - }, - ], - constructorName: 'HumidifierDehumidifier', - displayName: 'HumidifierDehumidifier', - hiddenService: false, - optionalCharacteristics: [ - { - UUID: '000000A7-0000-1000-8000-0026BB765291', - constructorName: 'LockPhysicalControls', - displayName: 'Lock Physical Controls', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr', 'pw'], - validValues: [0, 1], - }, - value: 0, - }, - { - UUID: '00000023-0000-1000-8000-0026BB765291', - constructorName: 'Name', - displayName: 'Name', - eventOnlyCharacteristic: false, - props: { - format: 'string', - maxLen: 64, - perms: ['pr'], - }, - value: '', - }, - { - UUID: '000000C9-0000-1000-8000-0026BB765291', - constructorName: 'RelativeHumidityDehumidifierThreshold', - displayName: 'Relative Humidity Dehumidifier Threshold', - eventOnlyCharacteristic: false, - props: { - format: 'float', - maxValue: 100, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr', 'pw'], - unit: 'percentage', - }, - value: 0, - }, - { - UUID: '000000CA-0000-1000-8000-0026BB765291', - constructorName: 'RelativeHumidityHumidifierThreshold', - displayName: 'Relative Humidity Humidifier Threshold', - eventOnlyCharacteristic: false, - props: { - format: 'float', - maxValue: 100, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr', 'pw'], - unit: 'percentage', - }, - value: 0, - }, - { - UUID: '00000029-0000-1000-8000-0026BB765291', - constructorName: 'RotationSpeed', - displayName: 'Rotation Speed', - eventOnlyCharacteristic: false, - props: { - format: 'float', - maxValue: 100, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr', 'pw'], - unit: 'percentage', - }, - value: 0, - }, - { - UUID: '000000B6-0000-1000-8000-0026BB765291', - constructorName: 'SwingMode', - displayName: 'Swing Mode', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr', 'pw'], - validValues: [0, 1], - }, - value: 0, - }, - { - UUID: '000000B5-0000-1000-8000-0026BB765291', - constructorName: 'WaterLevel', - displayName: 'Water Level', - eventOnlyCharacteristic: false, - props: { - format: 'float', - maxValue: 100, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - unit: 'percentage', - }, - value: 0, - }, - ], - primaryService: false, - }, - HumiditySensor: { - UUID: '00000082-0000-1000-8000-0026BB765291', - characteristics: [ - { - UUID: '00000010-0000-1000-8000-0026BB765291', - constructorName: 'CurrentRelativeHumidity', - displayName: 'Current Relative Humidity', - eventOnlyCharacteristic: false, - props: { - format: 'float', - maxValue: 100, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - unit: 'percentage', - }, - value: 0, - }, - ], - constructorName: 'HumiditySensor', - displayName: 'HumiditySensor', - hiddenService: false, - optionalCharacteristics: [ - { - UUID: '00000023-0000-1000-8000-0026BB765291', - constructorName: 'Name', - displayName: 'Name', - eventOnlyCharacteristic: false, - props: { - format: 'string', - maxLen: 64, - perms: ['pr'], - }, - value: '', - }, - { - UUID: '00000075-0000-1000-8000-0026BB765291', - constructorName: 'StatusActive', - displayName: 'Status Active', - eventOnlyCharacteristic: false, - props: { - format: 'bool', - perms: ['ev', 'pr'], - }, - value: false, - }, - { - UUID: '00000077-0000-1000-8000-0026BB765291', - constructorName: 'StatusFault', - displayName: 'Status Fault', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - validValues: [0, 1], - }, - value: 0, - }, - { - UUID: '00000079-0000-1000-8000-0026BB765291', - constructorName: 'StatusLowBattery', - displayName: 'Status Low Battery', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - validValues: [0, 1], - }, - value: 0, - }, - { - UUID: '0000007A-0000-1000-8000-0026BB765291', - constructorName: 'StatusTampered', - displayName: 'Status Tampered', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - validValues: [0, 1], - }, - value: 0, - }, - ], - primaryService: false, - }, - InputSource: { - UUID: '000000D9-0000-1000-8000-0026BB765291', - characteristics: [ - { - UUID: '000000E3-0000-1000-8000-0026BB765291', - constructorName: 'ConfiguredName', - displayName: 'Configured Name', - eventOnlyCharacteristic: false, - props: { - format: 'string', - perms: ['ev', 'pr', 'pw'], - }, - value: '', - }, - { - UUID: '000000DB-0000-1000-8000-0026BB765291', - constructorName: 'InputSourceType', - displayName: 'Input Source Type', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 10, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - validValues: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10], - }, - value: 0, - }, - { - UUID: '000000D6-0000-1000-8000-0026BB765291', - constructorName: 'IsConfigured', - displayName: 'Is Configured', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr', 'pw'], - validValues: [0, 1], - }, - value: 0, - }, - { - UUID: '00000023-0000-1000-8000-0026BB765291', - constructorName: 'Name', - displayName: 'Name', - eventOnlyCharacteristic: false, - props: { - format: 'string', - maxLen: 64, - perms: ['pr'], - }, - value: 'Unnamed Service', - }, - { - UUID: '00000135-0000-1000-8000-0026BB765291', - constructorName: 'CurrentVisibilityState', - displayName: 'Current Visibility State', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - validValues: [0, 1], - }, - value: 0, - }, - ], - constructorName: 'InputSource', - displayName: 'InputSource', - hiddenService: false, - optionalCharacteristics: [ - { - UUID: '000000E6-0000-1000-8000-0026BB765291', - constructorName: 'Identifier', - displayName: 'Identifier', - eventOnlyCharacteristic: false, - props: { - format: 'uint32', - perms: ['pr'], - }, - value: 0, - }, - { - UUID: '000000DC-0000-1000-8000-0026BB765291', - constructorName: 'InputDeviceType', - displayName: 'Input Device Type', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 6, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - validValues: [0, 1, 2, 3, 4, 5, 6], - }, - value: 0, - }, - { - UUID: '00000134-0000-1000-8000-0026BB765291', - constructorName: 'TargetVisibilityState', - displayName: 'Target Visibility State', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr', 'pw'], - validValues: [0, 1], - }, - value: 0, - }, - ], - primaryService: false, - }, - IrrigationSystem: { - UUID: '000000CF-0000-1000-8000-0026BB765291', - characteristics: [ - { - UUID: '000000B0-0000-1000-8000-0026BB765291', - constructorName: 'Active', - displayName: 'Active', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr', 'pw'], - validValues: [0, 1], - }, - value: 0, - }, - { - UUID: '000000D1-0000-1000-8000-0026BB765291', - constructorName: 'ProgramMode', - displayName: 'Program Mode', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 2, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - validValues: [0, 1, 2], - }, - value: 0, - }, - { - UUID: '000000D2-0000-1000-8000-0026BB765291', - constructorName: 'InUse', - displayName: 'In Use', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - validValues: [0, 1], - }, - value: 0, - }, - ], - constructorName: 'IrrigationSystem', - displayName: 'IrrigationSystem', - hiddenService: false, - optionalCharacteristics: [ - { - UUID: '000000D4-0000-1000-8000-0026BB765291', - constructorName: 'RemainingDuration', - displayName: 'Remaining Duration', - eventOnlyCharacteristic: false, - props: { - format: 'uint32', - maxValue: 3600, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - unit: 'seconds', - }, - value: 0, - }, - { - UUID: '00000023-0000-1000-8000-0026BB765291', - constructorName: 'Name', - displayName: 'Name', - eventOnlyCharacteristic: false, - props: { - format: 'string', - maxLen: 64, - perms: ['pr'], - }, - value: '', - }, - { - UUID: '00000077-0000-1000-8000-0026BB765291', - constructorName: 'StatusFault', - displayName: 'Status Fault', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - validValues: [0, 1], - }, - value: 0, - }, - ], - primaryService: false, - }, - LeakSensor: { - UUID: '00000083-0000-1000-8000-0026BB765291', - characteristics: [ - { - UUID: '00000070-0000-1000-8000-0026BB765291', - constructorName: 'LeakDetected', - displayName: 'Leak Detected', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - validValues: [0, 1], - }, - value: 0, - }, - ], - constructorName: 'LeakSensor', - displayName: 'LeakSensor', - hiddenService: false, - optionalCharacteristics: [ - { - UUID: '00000023-0000-1000-8000-0026BB765291', - constructorName: 'Name', - displayName: 'Name', - eventOnlyCharacteristic: false, - props: { - format: 'string', - maxLen: 64, - perms: ['pr'], - }, - value: '', - }, - { - UUID: '00000075-0000-1000-8000-0026BB765291', - constructorName: 'StatusActive', - displayName: 'Status Active', - eventOnlyCharacteristic: false, - props: { - format: 'bool', - perms: ['ev', 'pr'], - }, - value: false, - }, - { - UUID: '00000077-0000-1000-8000-0026BB765291', - constructorName: 'StatusFault', - displayName: 'Status Fault', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - validValues: [0, 1], - }, - value: 0, - }, - { - UUID: '00000079-0000-1000-8000-0026BB765291', - constructorName: 'StatusLowBattery', - displayName: 'Status Low Battery', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - validValues: [0, 1], - }, - value: 0, - }, - { - UUID: '0000007A-0000-1000-8000-0026BB765291', - constructorName: 'StatusTampered', - displayName: 'Status Tampered', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - validValues: [0, 1], - }, - value: 0, - }, - ], - primaryService: false, - }, - LightSensor: { - UUID: '00000084-0000-1000-8000-0026BB765291', - characteristics: [ - { - UUID: '0000006B-0000-1000-8000-0026BB765291', - constructorName: 'CurrentAmbientLightLevel', - displayName: 'Current Ambient Light Level', - eventOnlyCharacteristic: false, - props: { - format: 'float', - maxValue: 100000, - minValue: 0.0001, - perms: ['ev', 'pr'], - unit: 'lux', - }, - value: 0.0001, - }, - ], - constructorName: 'LightSensor', - displayName: 'LightSensor', - hiddenService: false, - optionalCharacteristics: [ - { - UUID: '00000023-0000-1000-8000-0026BB765291', - constructorName: 'Name', - displayName: 'Name', - eventOnlyCharacteristic: false, - props: { - format: 'string', - maxLen: 64, - perms: ['pr'], - }, - value: '', - }, - { - UUID: '00000075-0000-1000-8000-0026BB765291', - constructorName: 'StatusActive', - displayName: 'Status Active', - eventOnlyCharacteristic: false, - props: { - format: 'bool', - perms: ['ev', 'pr'], - }, - value: false, - }, - { - UUID: '00000077-0000-1000-8000-0026BB765291', - constructorName: 'StatusFault', - displayName: 'Status Fault', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - validValues: [0, 1], - }, - value: 0, - }, - { - UUID: '00000079-0000-1000-8000-0026BB765291', - constructorName: 'StatusLowBattery', - displayName: 'Status Low Battery', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - validValues: [0, 1], - }, - value: 0, - }, - { - UUID: '0000007A-0000-1000-8000-0026BB765291', - constructorName: 'StatusTampered', - displayName: 'Status Tampered', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - validValues: [0, 1], - }, - value: 0, - }, - ], - primaryService: false, - }, - Lightbulb: { - UUID: '00000043-0000-1000-8000-0026BB765291', - characteristics: [ - { - UUID: '00000025-0000-1000-8000-0026BB765291', - constructorName: 'On', - displayName: 'On', - eventOnlyCharacteristic: false, - props: { - format: 'bool', - perms: ['ev', 'pr', 'pw'], - }, - value: false, - }, - ], - constructorName: 'Lightbulb', - displayName: 'Lightbulb', - hiddenService: false, - optionalCharacteristics: [ - { - UUID: '00000008-0000-1000-8000-0026BB765291', - constructorName: 'Brightness', - displayName: 'Brightness', - eventOnlyCharacteristic: false, - props: { - format: 'int', - maxValue: 100, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr', 'pw'], - unit: 'percentage', - }, - value: 0, - }, - { - UUID: '0000024B-0000-1000-8000-0026BB765291', - constructorName: 'CharacteristicValueActiveTransitionCount', - displayName: 'Characteristic Value Active Transition Count', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - perms: ['ev', 'pr'], - }, - value: 0, - }, - { - UUID: '00000143-0000-1000-8000-0026BB765291', - constructorName: 'CharacteristicValueTransitionControl', - displayName: 'Characteristic Value Transition Control', - eventOnlyCharacteristic: false, - props: { - format: 'tlv8', - perms: ['pr', 'pw', 'wr'], - }, - value: '', - }, - { - UUID: '000000CE-0000-1000-8000-0026BB765291', - constructorName: 'ColorTemperature', - displayName: 'Color Temperature', - eventOnlyCharacteristic: false, - props: { - format: 'int', - maxValue: 500, - minStep: 1, - minValue: 140, - perms: ['ev', 'pr', 'pw'], - }, - value: 140, - }, - { - UUID: '00000013-0000-1000-8000-0026BB765291', - constructorName: 'Hue', - displayName: 'Hue', - eventOnlyCharacteristic: false, - props: { - format: 'float', - maxValue: 360, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr', 'pw'], - unit: 'arcdegrees', - }, - value: 0, - }, - { - UUID: '00000023-0000-1000-8000-0026BB765291', - constructorName: 'Name', - displayName: 'Name', - eventOnlyCharacteristic: false, - props: { - format: 'string', - maxLen: 64, - perms: ['pr'], - }, - value: '', - }, - { - UUID: '0000002F-0000-1000-8000-0026BB765291', - constructorName: 'Saturation', - displayName: 'Saturation', - eventOnlyCharacteristic: false, - props: { - format: 'float', - maxValue: 100, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr', 'pw'], - unit: 'percentage', - }, - value: 0, - }, - { - UUID: '00000144-0000-1000-8000-0026BB765291', - constructorName: - 'SupportedCharacteristicValueTransitionConfiguration', - displayName: - 'Supported Characteristic Value Transition Configuration', - eventOnlyCharacteristic: false, - props: { - format: 'tlv8', - perms: ['pr'], - }, - value: '', - }, - ], - primaryService: false, - }, - LockManagement: { - UUID: '00000044-0000-1000-8000-0026BB765291', - characteristics: [ - { - UUID: '00000019-0000-1000-8000-0026BB765291', - constructorName: 'LockControlPoint', - displayName: 'Lock Control Point', - eventOnlyCharacteristic: false, - props: { - format: 'tlv8', - perms: ['pw'], - }, - value: '', - }, - { - UUID: '00000037-0000-1000-8000-0026BB765291', - constructorName: 'Version', - displayName: 'Version', - eventOnlyCharacteristic: false, - props: { - format: 'string', - maxLen: 64, - perms: ['pr'], - }, - value: '', - }, - ], - constructorName: 'LockManagement', - displayName: 'LockManagement', - hiddenService: false, - optionalCharacteristics: [ - { - UUID: '00000001-0000-1000-8000-0026BB765291', - constructorName: 'AdministratorOnlyAccess', - displayName: 'Administrator Only Access', - eventOnlyCharacteristic: false, - props: { - format: 'bool', - perms: ['ev', 'pr', 'pw'], - }, - value: false, - }, - { - UUID: '00000005-0000-1000-8000-0026BB765291', - constructorName: 'AudioFeedback', - displayName: 'Audio Feedback', - eventOnlyCharacteristic: false, - props: { - format: 'bool', - perms: ['ev', 'pr', 'pw'], - }, - value: false, - }, - { - UUID: '0000000E-0000-1000-8000-0026BB765291', - constructorName: 'CurrentDoorState', - displayName: 'Current Door State', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 4, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - validValues: [0, 1, 2, 3, 4], - }, - value: 0, - }, - { - UUID: '0000001A-0000-1000-8000-0026BB765291', - constructorName: 'LockManagementAutoSecurityTimeout', - displayName: 'Lock Management Auto Security Timeout', - eventOnlyCharacteristic: false, - props: { - format: 'uint32', - perms: ['ev', 'pr', 'pw'], - unit: 'seconds', - }, - value: 0, - }, - { - UUID: '0000001C-0000-1000-8000-0026BB765291', - constructorName: 'LockLastKnownAction', - displayName: 'Lock Last Known Action', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 10, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - validValues: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10], - }, - value: 0, - }, - { - UUID: '0000001F-0000-1000-8000-0026BB765291', - constructorName: 'Logs', - displayName: 'Logs', - eventOnlyCharacteristic: false, - props: { - format: 'tlv8', - perms: ['ev', 'pr'], - }, - value: '', - }, - { - UUID: '00000022-0000-1000-8000-0026BB765291', - constructorName: 'MotionDetected', - displayName: 'Motion Detected', - eventOnlyCharacteristic: false, - props: { - format: 'bool', - perms: ['ev', 'pr'], - }, - value: false, - }, - ], - primaryService: false, - }, - LockMechanism: { - UUID: '00000045-0000-1000-8000-0026BB765291', - characteristics: [ - { - UUID: '0000001D-0000-1000-8000-0026BB765291', - constructorName: 'LockCurrentState', - displayName: 'Lock Current State', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 3, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - validValues: [0, 1, 2, 3], - }, - value: 0, - }, - { - UUID: '0000001E-0000-1000-8000-0026BB765291', - constructorName: 'LockTargetState', - displayName: 'Lock Target State', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr', 'pw'], - validValues: [0, 1], - }, - value: 0, - }, - ], - constructorName: 'LockMechanism', - displayName: 'LockMechanism', - hiddenService: false, - optionalCharacteristics: [ - { - UUID: '00000023-0000-1000-8000-0026BB765291', - constructorName: 'Name', - displayName: 'Name', - eventOnlyCharacteristic: false, - props: { - format: 'string', - maxLen: 64, - perms: ['pr'], - }, - value: '', - }, - ], - primaryService: false, - }, - Microphone: { - UUID: '00000112-0000-1000-8000-0026BB765291', - characteristics: [ - { - UUID: '0000011A-0000-1000-8000-0026BB765291', - constructorName: 'Mute', - displayName: 'Mute', - eventOnlyCharacteristic: false, - props: { - format: 'bool', - perms: ['ev', 'pr', 'pw'], - }, - value: false, - }, - ], - constructorName: 'Microphone', - displayName: 'Microphone', - hiddenService: false, - optionalCharacteristics: [ - { - UUID: '00000119-0000-1000-8000-0026BB765291', - constructorName: 'Volume', - displayName: 'Volume', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 100, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr', 'pw'], - unit: 'percentage', - }, - value: 0, - }, - ], - primaryService: false, - }, - MotionSensor: { - UUID: '00000085-0000-1000-8000-0026BB765291', - characteristics: [ - { - UUID: '00000022-0000-1000-8000-0026BB765291', - constructorName: 'MotionDetected', - displayName: 'Motion Detected', - eventOnlyCharacteristic: false, - props: { - format: 'bool', - perms: ['ev', 'pr'], - }, - value: false, - }, - ], - constructorName: 'MotionSensor', - displayName: 'MotionSensor', - hiddenService: false, - optionalCharacteristics: [ - { - UUID: '00000023-0000-1000-8000-0026BB765291', - constructorName: 'Name', - displayName: 'Name', - eventOnlyCharacteristic: false, - props: { - format: 'string', - maxLen: 64, - perms: ['pr'], - }, - value: '', - }, - { - UUID: '00000075-0000-1000-8000-0026BB765291', - constructorName: 'StatusActive', - displayName: 'Status Active', - eventOnlyCharacteristic: false, - props: { - format: 'bool', - perms: ['ev', 'pr'], - }, - value: false, - }, - { - UUID: '00000077-0000-1000-8000-0026BB765291', - constructorName: 'StatusFault', - displayName: 'Status Fault', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - validValues: [0, 1], - }, - value: 0, - }, - { - UUID: '00000079-0000-1000-8000-0026BB765291', - constructorName: 'StatusLowBattery', - displayName: 'Status Low Battery', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - validValues: [0, 1], - }, - value: 0, - }, - { - UUID: '0000007A-0000-1000-8000-0026BB765291', - constructorName: 'StatusTampered', - displayName: 'Status Tampered', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - validValues: [0, 1], - }, - value: 0, - }, - ], - primaryService: false, - }, - NFCAccess: { - UUID: '00000266-0000-1000-8000-0026BB765291', - characteristics: [ - { - UUID: '00000263-0000-1000-8000-0026BB765291', - constructorName: 'ConfigurationState', - displayName: 'Configuration State', - eventOnlyCharacteristic: false, - props: { - format: 'uint16', - perms: ['ev', 'pr'], - }, - value: 0, - }, - { - UUID: '00000264-0000-1000-8000-0026BB765291', - constructorName: 'NFCAccessControlPoint', - displayName: 'NFC Access Control Point', - eventOnlyCharacteristic: false, - props: { - format: 'tlv8', - perms: ['pr', 'pw', 'wr'], - }, - value: '', - }, - { - UUID: '00000265-0000-1000-8000-0026BB765291', - constructorName: 'NFCAccessSupportedConfiguration', - displayName: 'NFC Access Supported Configuration', - eventOnlyCharacteristic: false, - props: { - format: 'tlv8', - perms: ['pr'], - }, - value: '', - }, - ], - constructorName: 'NFCAccess', - displayName: 'NFCAccess', - hiddenService: false, - optionalCharacteristics: [], - primaryService: false, - }, - OccupancySensor: { - UUID: '00000086-0000-1000-8000-0026BB765291', - characteristics: [ - { - UUID: '00000071-0000-1000-8000-0026BB765291', - constructorName: 'OccupancyDetected', - displayName: 'Occupancy Detected', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - validValues: [0, 1], - }, - value: 0, - }, - ], - constructorName: 'OccupancySensor', - displayName: 'OccupancySensor', - hiddenService: false, - optionalCharacteristics: [ - { - UUID: '00000023-0000-1000-8000-0026BB765291', - constructorName: 'Name', - displayName: 'Name', - eventOnlyCharacteristic: false, - props: { - format: 'string', - maxLen: 64, - perms: ['pr'], - }, - value: '', - }, - { - UUID: '00000075-0000-1000-8000-0026BB765291', - constructorName: 'StatusActive', - displayName: 'Status Active', - eventOnlyCharacteristic: false, - props: { - format: 'bool', - perms: ['ev', 'pr'], - }, - value: false, - }, - { - UUID: '00000077-0000-1000-8000-0026BB765291', - constructorName: 'StatusFault', - displayName: 'Status Fault', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - validValues: [0, 1], - }, - value: 0, - }, - { - UUID: '00000079-0000-1000-8000-0026BB765291', - constructorName: 'StatusLowBattery', - displayName: 'Status Low Battery', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - validValues: [0, 1], - }, - value: 0, - }, - { - UUID: '0000007A-0000-1000-8000-0026BB765291', - constructorName: 'StatusTampered', - displayName: 'Status Tampered', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - validValues: [0, 1], - }, - value: 0, - }, - ], - primaryService: false, - }, - Outlet: { - UUID: '00000047-0000-1000-8000-0026BB765291', - characteristics: [ - { - UUID: '00000025-0000-1000-8000-0026BB765291', - constructorName: 'On', - displayName: 'On', - eventOnlyCharacteristic: false, - props: { - format: 'bool', - perms: ['ev', 'pr', 'pw'], - }, - value: false, - }, - ], - constructorName: 'Outlet', - displayName: 'Outlet', - hiddenService: false, - optionalCharacteristics: [ - { - UUID: '00000023-0000-1000-8000-0026BB765291', - constructorName: 'Name', - displayName: 'Name', - eventOnlyCharacteristic: false, - props: { - format: 'string', - maxLen: 64, - perms: ['pr'], - }, - value: '', - }, - { - UUID: '00000026-0000-1000-8000-0026BB765291', - constructorName: 'OutletInUse', - displayName: 'Outlet In Use', - eventOnlyCharacteristic: false, - props: { - format: 'bool', - perms: ['ev', 'pr'], - }, - value: false, - }, - ], - primaryService: false, - }, - Pairing: { - UUID: '00000055-0000-1000-8000-0026BB765291', - characteristics: [ - { - UUID: '00000050-0000-1000-8000-0026BB765291', - constructorName: 'ListPairings', - displayName: 'List Pairings', - eventOnlyCharacteristic: false, - props: { - format: 'tlv8', - perms: ['pr', 'pw'], - }, - value: '', - }, - { - UUID: '0000004C-0000-1000-8000-0026BB765291', - constructorName: 'PairSetup', - displayName: 'Pair Setup', - eventOnlyCharacteristic: false, - props: { - format: 'tlv8', - perms: ['pr', 'pw'], - }, - value: '', - }, - { - UUID: '0000004E-0000-1000-8000-0026BB765291', - constructorName: 'PairVerify', - displayName: 'Pair Verify', - eventOnlyCharacteristic: false, - props: { - format: 'tlv8', - perms: ['pr', 'pw'], - }, - value: '', - }, - { - UUID: '0000004F-0000-1000-8000-0026BB765291', - constructorName: 'PairingFeatures', - displayName: 'Pairing Features', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - perms: ['pr'], - }, - value: 0, - }, - ], - constructorName: 'Pairing', - displayName: 'Pairing', - hiddenService: false, - optionalCharacteristics: [], - primaryService: false, - }, - PowerManagement: { - UUID: '00000221-0000-1000-8000-0026BB765291', - characteristics: [ - { - UUID: '00000222-0000-1000-8000-0026BB765291', - constructorName: 'WakeConfiguration', - displayName: 'Wake Configuration', - eventOnlyCharacteristic: false, - props: { - format: 'tlv8', - perms: ['pr'], - }, - value: '', - }, - ], - constructorName: 'PowerManagement', - displayName: 'PowerManagement', - hiddenService: false, - optionalCharacteristics: [ - { - UUID: '00000252-0000-1000-8000-0026BB765291', - constructorName: 'SelectedSleepConfiguration', - displayName: 'Selected Sleep Configuration', - eventOnlyCharacteristic: false, - props: { - format: 'tlv8', - perms: ['ev', 'pr', 'pw', 'wr'], - }, - value: '', - }, - { - UUID: '00000251-0000-1000-8000-0026BB765291', - constructorName: 'SupportedSleepConfiguration', - displayName: 'Supported Sleep Configuration', - eventOnlyCharacteristic: false, - props: { - format: 'tlv8', - perms: ['pr'], - }, - value: '', - }, - ], - primaryService: false, - }, - ProtocolInformation: { - UUID: '000000A2-0000-1000-8000-0026BB765291', - characteristics: [ - { - UUID: '00000037-0000-1000-8000-0026BB765291', - constructorName: 'Version', - displayName: 'Version', - eventOnlyCharacteristic: false, - props: { - format: 'string', - maxLen: 64, - perms: ['pr'], - }, - value: '', - }, - ], - constructorName: 'ProtocolInformation', - displayName: 'ProtocolInformation', - hiddenService: false, - optionalCharacteristics: [], - primaryService: false, - }, - Relay: { - nrchkbDisabledText: 'Relay (deprecated, replaced by CloudRelay)', - }, - SecuritySystem: { - UUID: '0000007E-0000-1000-8000-0026BB765291', - characteristics: [ - { - UUID: '00000066-0000-1000-8000-0026BB765291', - constructorName: 'SecuritySystemCurrentState', - displayName: 'Security System Current State', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 4, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - validValues: [0, 1, 2, 3, 4], - }, - value: 0, - }, - { - UUID: '00000067-0000-1000-8000-0026BB765291', - constructorName: 'SecuritySystemTargetState', - displayName: 'Security System Target State', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 3, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr', 'pw'], - validValues: [0, 1, 2, 3], - }, - value: 0, - }, - ], - constructorName: 'SecuritySystem', - displayName: 'SecuritySystem', - hiddenService: false, - optionalCharacteristics: [ - { - UUID: '00000023-0000-1000-8000-0026BB765291', - constructorName: 'Name', - displayName: 'Name', - eventOnlyCharacteristic: false, - props: { - format: 'string', - maxLen: 64, - perms: ['pr'], - }, - value: '', - }, - { - UUID: '0000008E-0000-1000-8000-0026BB765291', - constructorName: 'SecuritySystemAlarmType', - displayName: 'Security System Alarm Type', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - validValues: [0, 1], - perms: ['ev', 'pr'], - }, - value: 0, - }, - { - UUID: '00000077-0000-1000-8000-0026BB765291', - constructorName: 'StatusFault', - displayName: 'Status Fault', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - validValues: [0, 1], - }, - value: 0, - }, - { - UUID: '0000007A-0000-1000-8000-0026BB765291', - constructorName: 'StatusTampered', - displayName: 'Status Tampered', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - validValues: [0, 1], - }, - value: 0, - }, - ], - primaryService: false, - }, - ServiceLabel: { - UUID: '000000CC-0000-1000-8000-0026BB765291', - characteristics: [ - { - UUID: '000000CD-0000-1000-8000-0026BB765291', - constructorName: 'ServiceLabelNamespace', - displayName: 'Service Label Namespace', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['pr'], - validValues: [0, 1], - }, - value: 0, - }, - ], - constructorName: 'ServiceLabel', - displayName: 'ServiceLabel', - hiddenService: false, - optionalCharacteristics: [], - primaryService: false, - }, - Siri: { - UUID: '00000133-0000-1000-8000-0026BB765291', - characteristics: [ - { - UUID: '00000132-0000-1000-8000-0026BB765291', - constructorName: 'SiriInputType', - displayName: 'Siri Input Type', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 0, - minValue: 0, - perms: ['pr'], - validValues: [0], - }, - value: 0, - }, - ], - constructorName: 'Siri', - displayName: 'Siri', - hiddenService: false, - optionalCharacteristics: [ - { - UUID: '0000026B-0000-1000-8000-0026BB765291', - constructorName: 'MultifunctionButton', - displayName: 'Multifunction Button', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minValue: 0, - perms: ['ev', 'pr'], - }, - value: 0, - }, - { - UUID: '00000255-0000-1000-8000-0026BB765291', - constructorName: 'SiriEnable', - displayName: 'Siri Enable', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minValue: 0, - perms: ['ev', 'pr', 'pw'], - }, - value: 0, - }, - { - UUID: '0000025A-0000-1000-8000-0026BB765291', - constructorName: 'SiriEngineVersion', - displayName: 'Siri Engine Version', - eventOnlyCharacteristic: false, - props: { - format: 'string', - perms: ['pr'], - }, - value: '', - }, - { - UUID: '00000258-0000-1000-8000-0026BB765291', - constructorName: 'SiriLightOnUse', - displayName: 'Siri Light On Use', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minValue: 0, - perms: ['ev', 'pr', 'pw'], - }, - value: 0, - }, - { - UUID: '00000256-0000-1000-8000-0026BB765291', - constructorName: 'SiriListening', - displayName: 'Siri Listening', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minValue: 0, - perms: ['ev', 'pr', 'pw'], - }, - value: 0, - }, - { - UUID: '00000257-0000-1000-8000-0026BB765291', - constructorName: 'SiriTouchToUse', - displayName: 'Siri Touch To Use', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minValue: 0, - perms: ['ev', 'pr', 'pw'], - }, - value: 0, - }, - ], - primaryService: false, - }, - SiriEndpoint: { - UUID: '00000253-0000-1000-8000-0026BB765291', - characteristics: [ - { - UUID: '00000254-0000-1000-8000-0026BB765291', - constructorName: 'SiriEndpointSessionStatus', - displayName: 'Siri Endpoint Session Status', - eventOnlyCharacteristic: false, - props: { - format: 'tlv8', - perms: ['ev', 'pr'], - }, - value: '', - }, - { - UUID: '00000037-0000-1000-8000-0026BB765291', - constructorName: 'Version', - displayName: 'Version', - eventOnlyCharacteristic: false, - props: { - format: 'string', - maxLen: 64, - perms: ['pr'], - }, - value: '', - }, - ], - constructorName: 'SiriEndpoint', - displayName: 'SiriEndpoint', - hiddenService: false, - optionalCharacteristics: [ - { - UUID: '000000E7-0000-1000-8000-0026BB765291', - constructorName: 'ActiveIdentifier', - displayName: 'Active Identifier', - eventOnlyCharacteristic: false, - props: { - format: 'uint32', - perms: ['ev', 'pr', 'pw'], - }, - value: 0, - }, - { - UUID: '00000227-0000-1000-8000-0026BB765291', - constructorName: 'ManuallyDisabled', - displayName: 'Manually Disabled', - eventOnlyCharacteristic: false, - props: { - format: 'bool', - perms: ['ev', 'pr'], - }, - value: false, - }, - ], - primaryService: false, - }, - Slat: { - nrchkbDisabledText: 'Slat (deprecated, replaced by Slats)', - }, - Slats: { - UUID: '000000B9-0000-1000-8000-0026BB765291', - characteristics: [ - { - UUID: '000000AA-0000-1000-8000-0026BB765291', - constructorName: 'CurrentSlatState', - displayName: 'Current Slat State', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 2, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - validValues: [0, 1, 2], - }, - value: 0, - }, - { - UUID: '000000C0-0000-1000-8000-0026BB765291', - constructorName: 'SlatType', - displayName: 'Slat Type', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['pr'], - validValues: [0, 1], - }, - value: 0, - }, - ], - constructorName: 'Slats', - displayName: 'Slats', - hiddenService: false, - optionalCharacteristics: [ - { - UUID: '00000023-0000-1000-8000-0026BB765291', - constructorName: 'Name', - displayName: 'Name', - eventOnlyCharacteristic: false, - props: { - format: 'string', - maxLen: 64, - perms: ['pr'], - }, - value: '', - }, - { - UUID: '000000B6-0000-1000-8000-0026BB765291', - constructorName: 'SwingMode', - displayName: 'Swing Mode', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr', 'pw'], - validValues: [0, 1], - }, - value: 0, - }, - { - UUID: '000000C1-0000-1000-8000-0026BB765291', - constructorName: 'CurrentTiltAngle', - displayName: 'Current Tilt Angle', - eventOnlyCharacteristic: false, - props: { - format: 'int', - maxValue: 90, - minStep: 1, - minValue: -90, - perms: ['ev', 'pr'], - unit: 'arcdegrees', - }, - value: -90, - }, - { - UUID: '000000C2-0000-1000-8000-0026BB765291', - constructorName: 'TargetTiltAngle', - displayName: 'Target Tilt Angle', - eventOnlyCharacteristic: false, - props: { - format: 'int', - maxValue: 90, - minStep: 1, - minValue: -90, - perms: ['ev', 'pr', 'pw'], - unit: 'arcdegrees', - }, - value: -90, - }, - ], - primaryService: false, - }, - SmartSpeaker: { - UUID: '00000228-0000-1000-8000-0026BB765291', - characteristics: [ - { - UUID: '000000E0-0000-1000-8000-0026BB765291', - constructorName: 'CurrentMediaState', - displayName: 'Current Media State', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 5, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - validValues: [0, 1, 2, 4, 5], - }, - value: 0, - }, - { - UUID: '00000137-0000-1000-8000-0026BB765291', - constructorName: 'TargetMediaState', - displayName: 'Target Media State', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 2, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr', 'pw'], - validValues: [0, 1, 2], - }, - value: 0, - }, - ], - constructorName: 'SmartSpeaker', - displayName: 'SmartSpeaker', - hiddenService: false, - optionalCharacteristics: [ - { - UUID: '0000025B-0000-1000-8000-0026BB765291', - constructorName: 'AirPlayEnable', - displayName: 'AirPlay Enable', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minValue: 0, - perms: ['ev', 'pr', 'pw'], - }, - value: 0, - }, - { - UUID: '000000E3-0000-1000-8000-0026BB765291', - constructorName: 'ConfiguredName', - displayName: 'Configured Name', - eventOnlyCharacteristic: false, - props: { - format: 'string', - perms: ['ev', 'pr', 'pw'], - }, - value: '', - }, - { - UUID: '0000011A-0000-1000-8000-0026BB765291', - constructorName: 'Mute', - displayName: 'Mute', - eventOnlyCharacteristic: false, - props: { - format: 'bool', - perms: ['ev', 'pr', 'pw'], - }, - value: false, - }, - { - UUID: '00000023-0000-1000-8000-0026BB765291', - constructorName: 'Name', - displayName: 'Name', - eventOnlyCharacteristic: false, - props: { - format: 'string', - maxLen: 64, - perms: ['pr'], - }, - value: '', - }, - { - UUID: '00000119-0000-1000-8000-0026BB765291', - constructorName: 'Volume', - displayName: 'Volume', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 100, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr', 'pw'], - unit: 'percentage', - }, - value: 0, - }, - ], - primaryService: false, - }, - SmokeSensor: { - UUID: '00000087-0000-1000-8000-0026BB765291', - characteristics: [ - { - UUID: '00000076-0000-1000-8000-0026BB765291', - constructorName: 'SmokeDetected', - displayName: 'Smoke Detected', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - validValues: [0, 1], - }, - value: 0, - }, - ], - constructorName: 'SmokeSensor', - displayName: 'SmokeSensor', - hiddenService: false, - optionalCharacteristics: [ - { - UUID: '00000023-0000-1000-8000-0026BB765291', - constructorName: 'Name', - displayName: 'Name', - eventOnlyCharacteristic: false, - props: { - format: 'string', - maxLen: 64, - perms: ['pr'], - }, - value: '', - }, - { - UUID: '00000075-0000-1000-8000-0026BB765291', - constructorName: 'StatusActive', - displayName: 'Status Active', - eventOnlyCharacteristic: false, - props: { - format: 'bool', - perms: ['ev', 'pr'], - }, - value: false, - }, - { - UUID: '00000077-0000-1000-8000-0026BB765291', - constructorName: 'StatusFault', - displayName: 'Status Fault', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - validValues: [0, 1], - }, - value: 0, - }, - { - UUID: '00000079-0000-1000-8000-0026BB765291', - constructorName: 'StatusLowBattery', - displayName: 'Status Low Battery', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - validValues: [0, 1], - }, - value: 0, - }, - { - UUID: '0000007A-0000-1000-8000-0026BB765291', - constructorName: 'StatusTampered', - displayName: 'Status Tampered', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - validValues: [0, 1], - }, - value: 0, - }, - ], - primaryService: false, - }, - Speaker: { - UUID: '00000113-0000-1000-8000-0026BB765291', - characteristics: [ - { - UUID: '0000011A-0000-1000-8000-0026BB765291', - constructorName: 'Mute', - displayName: 'Mute', - eventOnlyCharacteristic: false, - props: { - format: 'bool', - perms: ['ev', 'pr', 'pw'], - }, - value: false, - }, - ], - constructorName: 'Speaker', - displayName: 'Speaker', - hiddenService: false, - optionalCharacteristics: [ - { - UUID: '000000B0-0000-1000-8000-0026BB765291', - constructorName: 'Active', - displayName: 'Active', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr', 'pw'], - validValues: [0, 1], - }, - value: 0, - }, - { - UUID: '00000119-0000-1000-8000-0026BB765291', - constructorName: 'Volume', - displayName: 'Volume', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 100, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr', 'pw'], - unit: 'percentage', - }, - value: 0, - }, - ], - primaryService: false, - }, - StatefulProgrammableSwitch: { - UUID: '00000088-0000-1000-8000-0026BB765291', - characteristics: [ - { - UUID: '00000073-0000-1000-8000-0026BB765291', - constructorName: 'ProgrammableSwitchEvent', - displayName: 'Programmable Switch Event', - eventOnlyCharacteristic: true, - props: { - format: 'uint8', - maxValue: 2, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - validValues: [0, 1, 2], - }, - value: 0, - }, - { - UUID: '00000074-0000-1000-8000-0026BB765291', - constructorName: 'ProgrammableSwitchOutputState', - displayName: 'Programmable Switch Output State', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr', 'pw'], - }, - value: 0, - }, - ], - constructorName: 'StatefulProgrammableSwitch', - displayName: 'StatefulProgrammableSwitch', - hiddenService: false, - optionalCharacteristics: [ - { - UUID: '00000023-0000-1000-8000-0026BB765291', - constructorName: 'Name', - displayName: 'Name', - eventOnlyCharacteristic: false, - props: { - format: 'string', - maxLen: 64, - perms: ['pr'], - }, - value: '', - }, - ], - primaryService: false, - }, - StatelessProgrammableSwitch: { - UUID: '00000089-0000-1000-8000-0026BB765291', - characteristics: [ - { - UUID: '00000073-0000-1000-8000-0026BB765291', - constructorName: 'ProgrammableSwitchEvent', - displayName: 'Programmable Switch Event', - eventOnlyCharacteristic: true, - props: { - format: 'uint8', - maxValue: 2, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - validValues: [0, 1, 2], - }, - value: 0, - }, - ], - constructorName: 'StatelessProgrammableSwitch', - displayName: 'StatelessProgrammableSwitch', - hiddenService: false, - optionalCharacteristics: [ - { - UUID: '00000023-0000-1000-8000-0026BB765291', - constructorName: 'Name', - displayName: 'Name', - eventOnlyCharacteristic: false, - props: { - format: 'string', - maxLen: 64, - perms: ['pr'], - }, - value: '', - }, - { - UUID: '000000CB-0000-1000-8000-0026BB765291', - constructorName: 'ServiceLabelIndex', - displayName: 'Service Label Index', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 255, - minStep: 1, - minValue: 1, - perms: ['pr'], - }, - value: 1, - }, - ], - primaryService: false, - }, - Switch: { - UUID: '00000049-0000-1000-8000-0026BB765291', - characteristics: [ - { - UUID: '00000025-0000-1000-8000-0026BB765291', - constructorName: 'On', - displayName: 'On', - eventOnlyCharacteristic: false, - props: { - format: 'bool', - perms: ['ev', 'pr', 'pw'], - }, - value: false, - }, - ], - constructorName: 'Switch', - displayName: 'Switch', - hiddenService: false, - optionalCharacteristics: [ - { - UUID: '00000023-0000-1000-8000-0026BB765291', - constructorName: 'Name', - displayName: 'Name', - eventOnlyCharacteristic: false, - props: { - format: 'string', - maxLen: 64, - perms: ['pr'], - }, - value: '', - }, - ], - primaryService: false, - }, - TapManagement: { - UUID: '0000022E-0000-1000-8000-0026BB765291', - characteristics: [ - { - UUID: '000000B0-0000-1000-8000-0026BB765291', - constructorName: 'Active', - displayName: 'Active', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr', 'pw'], - validValues: [0, 1], - }, - value: 0, - }, - { - UUID: '00000250-0000-1000-8000-0026BB765291', - constructorName: 'CryptoHash', - displayName: 'Crypto Hash', - eventOnlyCharacteristic: false, - props: { - format: 'tlv8', - perms: ['pw', 'wr'], - }, - value: '', - }, - { - UUID: '0000022F-0000-1000-8000-0026BB765291', - constructorName: 'TapType', - displayName: 'Tap Type', - eventOnlyCharacteristic: false, - props: { - format: 'uint16', - perms: ['pr'], - }, - value: 0, - }, - { - UUID: '00000231-0000-1000-8000-0026BB765291', - constructorName: 'Token', - displayName: 'Token', - eventOnlyCharacteristic: false, - props: { - format: 'data', - perms: ['pw'], - }, - value: '', - }, - ], - constructorName: 'TapManagement', - displayName: 'TapManagement', - hiddenService: false, - optionalCharacteristics: [], - primaryService: false, - }, - TargetControl: { - UUID: '00000125-0000-1000-8000-0026BB765291', - characteristics: [ - { - UUID: '000000B0-0000-1000-8000-0026BB765291', - constructorName: 'Active', - displayName: 'Active', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr', 'pw'], - validValues: [0, 1], - }, - value: 0, - }, - { - UUID: '000000E7-0000-1000-8000-0026BB765291', - constructorName: 'ActiveIdentifier', - displayName: 'Active Identifier', - eventOnlyCharacteristic: false, - props: { - format: 'uint32', - perms: ['ev', 'pr', 'pw'], - }, - value: 0, - }, - { - UUID: '00000126-0000-1000-8000-0026BB765291', - constructorName: 'ButtonEvent', - displayName: 'Button Event', - eventOnlyCharacteristic: false, - props: { - adminOnlyAccess: [2], - format: 'tlv8', - perms: ['ev', 'pr'], - }, - value: '', - }, - ], - constructorName: 'TargetControl', - displayName: 'TargetControl', - hiddenService: false, - optionalCharacteristics: [ - { - UUID: '00000023-0000-1000-8000-0026BB765291', - constructorName: 'Name', - displayName: 'Name', - eventOnlyCharacteristic: false, - props: { - format: 'string', - maxLen: 64, - perms: ['pr'], - }, - value: '', - }, - ], - primaryService: false, - }, - TargetControlManagement: { - UUID: '00000122-0000-1000-8000-0026BB765291', - characteristics: [ - { - UUID: '00000123-0000-1000-8000-0026BB765291', - constructorName: 'TargetControlSupportedConfiguration', - displayName: 'Target Control Supported Configuration', - eventOnlyCharacteristic: false, - props: { - format: 'tlv8', - perms: ['pr'], - }, - value: '', - }, - { - UUID: '00000124-0000-1000-8000-0026BB765291', - constructorName: 'TargetControlList', - displayName: 'Target Control List', - eventOnlyCharacteristic: false, - props: { - adminOnlyAccess: [0, 1], - format: 'tlv8', - perms: ['pr', 'pw', 'wr'], - }, - value: '', - }, - ], - constructorName: 'TargetControlManagement', - displayName: 'TargetControlManagement', - hiddenService: false, - optionalCharacteristics: [], - primaryService: false, - }, - Television: { - UUID: '000000D8-0000-1000-8000-0026BB765291', - characteristics: [ - { - UUID: '000000B0-0000-1000-8000-0026BB765291', - constructorName: 'Active', - displayName: 'Active', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr', 'pw'], - validValues: [0, 1], - }, - value: 0, - }, - { - UUID: '000000E7-0000-1000-8000-0026BB765291', - constructorName: 'ActiveIdentifier', - displayName: 'Active Identifier', - eventOnlyCharacteristic: false, - props: { - format: 'uint32', - perms: ['ev', 'pr', 'pw'], - }, - value: 0, - }, - { - UUID: '000000E3-0000-1000-8000-0026BB765291', - constructorName: 'ConfiguredName', - displayName: 'Configured Name', - eventOnlyCharacteristic: false, - props: { - format: 'string', - perms: ['ev', 'pr', 'pw'], - }, - value: '', - }, - { - UUID: '000000E1-0000-1000-8000-0026BB765291', - constructorName: 'RemoteKey', - displayName: 'Remote Key', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 16, - minStep: 1, - minValue: 0, - perms: ['pw'], - validValues: [ - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, - ], - }, - value: 0, - }, - { - UUID: '000000E8-0000-1000-8000-0026BB765291', - constructorName: 'SleepDiscoveryMode', - displayName: 'Sleep Discovery Mode', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - validValues: [0, 1], - }, - value: 0, - }, - ], - constructorName: 'Television', - displayName: 'Television', - hiddenService: false, - optionalCharacteristics: [ - { - UUID: '00000008-0000-1000-8000-0026BB765291', - constructorName: 'Brightness', - displayName: 'Brightness', - eventOnlyCharacteristic: false, - props: { - format: 'int', - maxValue: 100, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr', 'pw'], - unit: 'percentage', - }, - value: 0, - }, - { - UUID: '000000DD-0000-1000-8000-0026BB765291', - constructorName: 'ClosedCaptions', - displayName: 'Closed Captions', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr', 'pw'], - validValues: [0, 1], - }, - value: 0, - }, - { - UUID: '00000136-0000-1000-8000-0026BB765291', - constructorName: 'DisplayOrder', - displayName: 'Display Order', - eventOnlyCharacteristic: false, - props: { - format: 'tlv8', - perms: ['ev', 'pr', 'pw'], - }, - value: '', - }, - { - UUID: '000000E0-0000-1000-8000-0026BB765291', - constructorName: 'CurrentMediaState', - displayName: 'Current Media State', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 5, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - validValues: [0, 1, 2, 4, 5], - }, - value: 0, - }, - { - UUID: '00000137-0000-1000-8000-0026BB765291', - constructorName: 'TargetMediaState', - displayName: 'Target Media State', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 2, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr', 'pw'], - validValues: [0, 1, 2], - }, - value: 0, - }, - { - UUID: '00000023-0000-1000-8000-0026BB765291', - constructorName: 'Name', - displayName: 'Name', - eventOnlyCharacteristic: false, - props: { - format: 'string', - maxLen: 64, - perms: ['pr'], - }, - value: '', - }, - { - UUID: '000000E2-0000-1000-8000-0026BB765291', - constructorName: 'PictureMode', - displayName: 'Picture Mode', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 13, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr', 'pw'], - validValues: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13], - }, - value: 0, - }, - { - UUID: '000000DF-0000-1000-8000-0026BB765291', - constructorName: 'PowerModeSelection', - displayName: 'Power Mode Selection', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['pw'], - validValues: [0, 1], - }, - value: 0, - }, - ], - primaryService: false, - }, - TelevisionSpeaker: { - UUID: '00000113-0000-1000-8000-0026BB765291', - characteristics: [ - { - UUID: '0000011A-0000-1000-8000-0026BB765291', - constructorName: 'Mute', - displayName: 'Mute', - eventOnlyCharacteristic: false, - props: { - format: 'bool', - perms: ['ev', 'pr', 'pw'], - }, - value: false, - }, - ], - constructorName: 'TelevisionSpeaker', - displayName: 'TelevisionSpeaker', - hiddenService: false, - optionalCharacteristics: [ - { - UUID: '000000B0-0000-1000-8000-0026BB765291', - constructorName: 'Active', - displayName: 'Active', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr', 'pw'], - validValues: [0, 1], - }, - value: 0, - }, - { - UUID: '00000119-0000-1000-8000-0026BB765291', - constructorName: 'Volume', - displayName: 'Volume', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 100, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr', 'pw'], - unit: 'percentage', - }, - value: 0, - }, - { - UUID: '000000E9-0000-1000-8000-0026BB765291', - constructorName: 'VolumeControlType', - displayName: 'Volume Control Type', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 3, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - validValues: [0, 1, 2, 3], - }, - value: 0, - }, - { - UUID: '000000EA-0000-1000-8000-0026BB765291', - constructorName: 'VolumeSelector', - displayName: 'Volume Selector', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['pw'], - validValues: [0, 1], - }, - value: 0, - }, - ], - primaryService: false, - }, - TemperatureSensor: { - UUID: '0000008A-0000-1000-8000-0026BB765291', - characteristics: [ - { - UUID: '00000011-0000-1000-8000-0026BB765291', - constructorName: 'CurrentTemperature', - displayName: 'Current Temperature', - eventOnlyCharacteristic: false, - props: { - format: 'float', - maxValue: 100, - minStep: 0.1, - minValue: -270, - perms: ['ev', 'pr'], - unit: 'celsius', - }, - value: 0, - }, - ], - constructorName: 'TemperatureSensor', - displayName: 'TemperatureSensor', - hiddenService: false, - optionalCharacteristics: [ - { - UUID: '00000023-0000-1000-8000-0026BB765291', - constructorName: 'Name', - displayName: 'Name', - eventOnlyCharacteristic: false, - props: { - format: 'string', - maxLen: 64, - perms: ['pr'], - }, - value: '', - }, - { - UUID: '00000075-0000-1000-8000-0026BB765291', - constructorName: 'StatusActive', - displayName: 'Status Active', - eventOnlyCharacteristic: false, - props: { - format: 'bool', - perms: ['ev', 'pr'], - }, - value: false, - }, - { - UUID: '00000077-0000-1000-8000-0026BB765291', - constructorName: 'StatusFault', - displayName: 'Status Fault', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - validValues: [0, 1], - }, - value: 0, - }, - { - UUID: '00000079-0000-1000-8000-0026BB765291', - constructorName: 'StatusLowBattery', - displayName: 'Status Low Battery', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - validValues: [0, 1], - }, - value: 0, - }, - { - UUID: '0000007A-0000-1000-8000-0026BB765291', - constructorName: 'StatusTampered', - displayName: 'Status Tampered', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - validValues: [0, 1], - }, - value: 0, - }, - ], - primaryService: false, - }, - Thermostat: { - UUID: '0000004A-0000-1000-8000-0026BB765291', - characteristics: [ - { - UUID: '0000000F-0000-1000-8000-0026BB765291', - constructorName: 'CurrentHeatingCoolingState', - displayName: 'Current Heating Cooling State', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 2, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - validValues: [0, 1, 2], - }, - value: 0, - }, - { - UUID: '00000033-0000-1000-8000-0026BB765291', - constructorName: 'TargetHeatingCoolingState', - displayName: 'Target Heating Cooling State', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 3, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr', 'pw'], - validValues: [0, 1, 2, 3], - }, - value: 0, - }, - { - UUID: '00000011-0000-1000-8000-0026BB765291', - constructorName: 'CurrentTemperature', - displayName: 'Current Temperature', - eventOnlyCharacteristic: false, - props: { - format: 'float', - maxValue: 100, - minStep: 0.1, - minValue: -270, - perms: ['ev', 'pr'], - unit: 'celsius', - }, - value: 0, - }, - { - UUID: '00000035-0000-1000-8000-0026BB765291', - constructorName: 'TargetTemperature', - displayName: 'Target Temperature', - eventOnlyCharacteristic: false, - props: { - format: 'float', - maxValue: 38, - minStep: 0.1, - minValue: 10, - perms: ['ev', 'pr', 'pw'], - unit: 'celsius', - }, - value: 10, - }, - { - UUID: '00000036-0000-1000-8000-0026BB765291', - constructorName: 'TemperatureDisplayUnits', - displayName: 'Temperature Display Units', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr', 'pw'], - validValues: [0, 1], - }, - value: 0, - }, - ], - constructorName: 'Thermostat', - displayName: 'Thermostat', - hiddenService: false, - optionalCharacteristics: [ - { - UUID: '00000023-0000-1000-8000-0026BB765291', - constructorName: 'Name', - displayName: 'Name', - eventOnlyCharacteristic: false, - props: { - format: 'string', - maxLen: 64, - perms: ['pr'], - }, - value: '', - }, - { - UUID: '00000010-0000-1000-8000-0026BB765291', - constructorName: 'CurrentRelativeHumidity', - displayName: 'Current Relative Humidity', - eventOnlyCharacteristic: false, - props: { - format: 'float', - maxValue: 100, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - unit: 'percentage', - }, - value: 0, - }, - { - UUID: '00000034-0000-1000-8000-0026BB765291', - constructorName: 'TargetRelativeHumidity', - displayName: 'Target Relative Humidity', - eventOnlyCharacteristic: false, - props: { - format: 'float', - maxValue: 100, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr', 'pw'], - unit: 'percentage', - }, - value: 0, - }, - { - UUID: '0000000D-0000-1000-8000-0026BB765291', - constructorName: 'CoolingThresholdTemperature', - displayName: 'Cooling Threshold Temperature', - eventOnlyCharacteristic: false, - props: { - format: 'float', - maxValue: 35, - minStep: 0.1, - minValue: 10, - perms: ['ev', 'pr', 'pw'], - unit: 'celsius', - }, - value: 10, - }, - { - UUID: '00000012-0000-1000-8000-0026BB765291', - constructorName: 'HeatingThresholdTemperature', - displayName: 'Heating Threshold Temperature', - eventOnlyCharacteristic: false, - props: { - format: 'float', - maxValue: 25, - minStep: 0.1, - minValue: 0, - perms: ['ev', 'pr', 'pw'], - unit: 'celsius', - }, - value: 0, - }, - ], - primaryService: false, - }, - ThreadTransport: { - UUID: '00000701-0000-1000-8000-0026BB765291', - characteristics: [ - { - UUID: '0000022B-0000-1000-8000-0026BB765291', - constructorName: 'CurrentTransport', - displayName: 'Current Transport', - eventOnlyCharacteristic: false, - props: { - format: 'bool', - perms: ['pr'], - }, - value: false, - }, - { - UUID: '00000704-0000-1000-8000-0026BB765291', - constructorName: 'ThreadControlPoint', - displayName: 'Thread Control Point', - eventOnlyCharacteristic: false, - props: { - format: 'tlv8', - perms: ['pw'], - }, - value: '', - }, - { - UUID: '00000702-0000-1000-8000-0026BB765291', - constructorName: 'ThreadNodeCapabilities', - displayName: 'Thread Node Capabilities', - eventOnlyCharacteristic: false, - props: { - format: 'uint16', - maxValue: 31, - minStep: 1, - minValue: 0, - perms: ['pr'], - }, - value: 0, - }, - { - UUID: '00000703-0000-1000-8000-0026BB765291', - constructorName: 'ThreadStatus', - displayName: 'Thread Status', - eventOnlyCharacteristic: false, - props: { - format: 'uint16', - maxValue: 6, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - }, - value: 0, - }, - ], - constructorName: 'ThreadTransport', - displayName: 'ThreadTransport', - hiddenService: false, - optionalCharacteristics: [ - { - UUID: '00000246-0000-1000-8000-0026BB765291', - constructorName: 'CCAEnergyDetectThreshold', - displayName: 'CCA Energy Detect Threshold', - eventOnlyCharacteristic: false, - props: { - format: 'int', - perms: ['pr'], - }, - value: 0, - }, - { - UUID: '00000245-0000-1000-8000-0026BB765291', - constructorName: 'CCASignalDetectThreshold', - displayName: 'CCA Signal Detect Threshold', - eventOnlyCharacteristic: false, - props: { - format: 'int', - perms: ['pr'], - }, - value: 0, - }, - { - UUID: '0000023D-0000-1000-8000-0026BB765291', - constructorName: 'EventRetransmissionMaximum', - displayName: 'Event Retransmission Maximum', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - perms: ['pr'], - }, - value: 0, - }, - { - UUID: '0000023E-0000-1000-8000-0026BB765291', - constructorName: 'EventTransmissionCounters', - displayName: 'Event Transmission Counters', - eventOnlyCharacteristic: false, - props: { - format: 'uint32', - perms: ['pr'], - }, - value: 0, - }, - { - UUID: '00000247-0000-1000-8000-0026BB765291', - constructorName: 'MACRetransmissionMaximum', - displayName: 'MAC Retransmission Maximum', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - perms: ['pr'], - }, - value: 0, - }, - { - UUID: '00000248-0000-1000-8000-0026BB765291', - constructorName: 'MACTransmissionCounters', - displayName: 'MAC Transmission Counters', - eventOnlyCharacteristic: false, - props: { - format: 'data', - perms: ['pr'], - }, - value: '', - }, - { - UUID: '00000244-0000-1000-8000-0026BB765291', - constructorName: 'ReceiverSensitivity', - displayName: 'Receiver Sensitivity', - eventOnlyCharacteristic: false, - props: { - format: 'int', - perms: ['pr'], - }, - value: 0, - }, - { - UUID: '0000023F-0000-1000-8000-0026BB765291', - constructorName: 'ReceivedSignalStrengthIndication', - displayName: 'Received Signal Strength Indication', - eventOnlyCharacteristic: false, - props: { - format: 'int', - perms: ['pr'], - }, - value: 0, - }, - { - UUID: '00000241-0000-1000-8000-0026BB765291', - constructorName: 'SignalToNoiseRatio', - displayName: 'Signal To Noise Ratio', - eventOnlyCharacteristic: false, - props: { - format: 'int', - perms: ['pr'], - }, - value: 0, - }, - { - UUID: '00000706-0000-1000-8000-0026BB765291', - constructorName: 'ThreadOpenThreadVersion', - displayName: 'Thread OpenThread Version', - eventOnlyCharacteristic: false, - props: { - format: 'string', - perms: ['pr'], - }, - value: '', - }, - { - UUID: '00000242-0000-1000-8000-0026BB765291', - constructorName: 'TransmitPower', - displayName: 'Transmit Power', - eventOnlyCharacteristic: false, - props: { - format: 'int', - perms: ['pr'], - }, - value: 0, - }, - { - UUID: '00000243-0000-1000-8000-0026BB765291', - constructorName: 'MaximumTransmitPower', - displayName: 'Maximum Transmit Power', - eventOnlyCharacteristic: false, - props: { - format: 'int', - perms: ['pr'], - }, - value: 0, - }, - ], - primaryService: false, - }, - TimeInformation: { - nrchkbDisabledText: 'TimeInformation (deprecated, unused)', - }, - TransferTransportManagement: { - UUID: '00000203-0000-1000-8000-0026BB765291', - characteristics: [ - { - UUID: '00000202-0000-1000-8000-0026BB765291', - constructorName: 'SupportedTransferTransportConfiguration', - displayName: 'Supported Transfer Transport Configuration', - eventOnlyCharacteristic: false, - props: { - format: 'tlv8', - perms: ['pr'], - }, - value: '', - }, - { - UUID: '00000201-0000-1000-8000-0026BB765291', - constructorName: 'SetupTransferTransport', - displayName: 'Setup Transfer Transport', - eventOnlyCharacteristic: false, - props: { - format: 'tlv8', - perms: ['pw', 'wr'], - }, - value: '', - }, - ], - constructorName: 'TransferTransportManagement', - displayName: 'TransferTransportManagement', - hiddenService: false, - optionalCharacteristics: [], - primaryService: false, - }, - Tunnel: { - UUID: '00000056-0000-1000-8000-0026BB765291', - characteristics: [ - { - UUID: '00000057-0000-1000-8000-0026BB765291', - constructorName: 'AccessoryIdentifier', - displayName: 'Accessory Identifier', - eventOnlyCharacteristic: false, - props: { - format: 'string', - perms: ['pr'], - }, - value: '', - }, - { - UUID: '00000061-0000-1000-8000-0026BB765291', - constructorName: 'TunnelConnectionTimeout', - displayName: 'Tunnel Connection Timeout', - eventOnlyCharacteristic: false, - props: { - format: 'int', - perms: ['ev', 'pr', 'pw'], - }, - value: 0, - }, - { - UUID: '00000060-0000-1000-8000-0026BB765291', - constructorName: 'TunneledAccessoryAdvertising', - displayName: 'Tunneled Accessory Advertising', - eventOnlyCharacteristic: false, - props: { - format: 'bool', - perms: ['ev', 'pr', 'pw'], - }, - value: false, - }, - { - UUID: '00000059-0000-1000-8000-0026BB765291', - constructorName: 'TunneledAccessoryConnected', - displayName: 'Tunneled Accessory Connected', - eventOnlyCharacteristic: false, - props: { - format: 'bool', - perms: ['ev', 'pr', 'pw'], - }, - value: false, - }, - { - UUID: '00000058-0000-1000-8000-0026BB765291', - constructorName: 'TunneledAccessoryStateNumber', - displayName: 'Tunneled Accessory State Number', - eventOnlyCharacteristic: false, - props: { - format: 'int', - perms: ['ev', 'pr'], - }, - value: 0, - }, - ], - constructorName: 'Tunnel', - displayName: 'Tunnel', - hiddenService: false, - optionalCharacteristics: [], - primaryService: false, - }, - TunneledBTLEAccessoryService: { - nrchkbDisabledText: - 'TunneledBTLEAccessoryService (deprecated, replaced by Tunnel)', - }, - Valve: { - UUID: '000000D0-0000-1000-8000-0026BB765291', - characteristics: [ - { - UUID: '000000B0-0000-1000-8000-0026BB765291', - constructorName: 'Active', - displayName: 'Active', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr', 'pw'], - validValues: [0, 1], - }, - value: 0, - }, - { - UUID: '000000D2-0000-1000-8000-0026BB765291', - constructorName: 'InUse', - displayName: 'In Use', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - validValues: [0, 1], - }, - value: 0, - }, - { - UUID: '000000D5-0000-1000-8000-0026BB765291', - constructorName: 'ValveType', - displayName: 'Valve Type', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 3, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - validValues: [0, 1, 2, 3], - }, - value: 0, - }, - ], - constructorName: 'Valve', - displayName: 'Valve', - hiddenService: false, - optionalCharacteristics: [ - { - UUID: '000000D6-0000-1000-8000-0026BB765291', - constructorName: 'IsConfigured', - displayName: 'Is Configured', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr', 'pw'], - validValues: [0, 1], - }, - value: 0, - }, - { - UUID: '00000023-0000-1000-8000-0026BB765291', - constructorName: 'Name', - displayName: 'Name', - eventOnlyCharacteristic: false, - props: { - format: 'string', - maxLen: 64, - perms: ['pr'], - }, - value: '', - }, - { - UUID: '000000D4-0000-1000-8000-0026BB765291', - constructorName: 'RemainingDuration', - displayName: 'Remaining Duration', - eventOnlyCharacteristic: false, - props: { - format: 'uint32', - maxValue: 3600, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - unit: 'seconds', - }, - value: 0, - }, - { - UUID: '000000CB-0000-1000-8000-0026BB765291', - constructorName: 'ServiceLabelIndex', - displayName: 'Service Label Index', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 255, - minStep: 1, - minValue: 1, - perms: ['pr'], - }, - value: 1, - }, - { - UUID: '000000D3-0000-1000-8000-0026BB765291', - constructorName: 'SetDuration', - displayName: 'Set Duration', - eventOnlyCharacteristic: false, - props: { - format: 'uint32', - maxValue: 3600, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr', 'pw'], - unit: 'seconds', - }, - value: 0, - }, - { - UUID: '00000077-0000-1000-8000-0026BB765291', - constructorName: 'StatusFault', - displayName: 'Status Fault', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - validValues: [0, 1], - }, - value: 0, - }, - ], - primaryService: false, - }, - WiFiRouter: { - UUID: '0000020A-0000-1000-8000-0026BB765291', - characteristics: [ - { - UUID: '000000E3-0000-1000-8000-0026BB765291', - constructorName: 'ConfiguredName', - displayName: 'Configured Name', - eventOnlyCharacteristic: false, - props: { - format: 'string', - perms: ['ev', 'pr', 'pw'], - }, - value: '', - }, - { - UUID: '00000215-0000-1000-8000-0026BB765291', - constructorName: 'ManagedNetworkEnable', - displayName: 'Managed Network Enable', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minValue: 0, - perms: ['ev', 'pr', 'pw', 'tw'], - validValues: [0, 1], - }, - value: 0, - }, - { - UUID: '0000021F-0000-1000-8000-0026BB765291', - constructorName: 'NetworkAccessViolationControl', - displayName: 'Network Access Violation Control', - eventOnlyCharacteristic: false, - props: { - format: 'tlv8', - perms: ['ev', 'pr', 'pw', 'tw', 'wr'], - }, - value: '', - }, - { - UUID: '0000020C-0000-1000-8000-0026BB765291', - constructorName: 'NetworkClientProfileControl', - displayName: 'Network Client Profile Control', - eventOnlyCharacteristic: false, - props: { - format: 'tlv8', - perms: ['ev', 'pr', 'pw', 'tw', 'wr'], - }, - value: '', - }, - { - UUID: '0000020D-0000-1000-8000-0026BB765291', - constructorName: 'NetworkClientStatusControl', - displayName: 'Network Client Status Control', - eventOnlyCharacteristic: false, - props: { - format: 'tlv8', - perms: ['pr', 'pw', 'wr'], - }, - value: '', - }, - { - UUID: '0000020E-0000-1000-8000-0026BB765291', - constructorName: 'RouterStatus', - displayName: 'Router Status', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 1, - minValue: 0, - perms: ['ev', 'pr'], - validValues: [0, 1], - }, - value: 0, - }, - { - UUID: '00000210-0000-1000-8000-0026BB765291', - constructorName: 'SupportedRouterConfiguration', - displayName: 'Supported Router Configuration', - eventOnlyCharacteristic: false, - props: { - format: 'tlv8', - perms: ['pr'], - }, - value: '', - }, - { - UUID: '00000211-0000-1000-8000-0026BB765291', - constructorName: 'WANConfigurationList', - displayName: 'WAN Configuration List', - eventOnlyCharacteristic: false, - props: { - format: 'tlv8', - perms: ['ev', 'pr'], - }, - value: '', - }, - { - UUID: '00000212-0000-1000-8000-0026BB765291', - constructorName: 'WANStatusList', - displayName: 'WAN Status List', - eventOnlyCharacteristic: false, - props: { - format: 'tlv8', - perms: ['ev', 'pr'], - }, - value: '', - }, - ], - constructorName: 'WiFiRouter', - displayName: 'WiFiRouter', - hiddenService: false, - optionalCharacteristics: [], - primaryService: false, - }, - WiFiSatellite: { - UUID: '0000020F-0000-1000-8000-0026BB765291', - characteristics: [ - { - UUID: '0000021E-0000-1000-8000-0026BB765291', - constructorName: 'WiFiSatelliteStatus', - displayName: 'Wi-Fi Satellite Status', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 2, - minValue: 0, - perms: ['ev', 'pr'], - validValues: [0, 1, 2], - }, - value: 0, - }, - ], - constructorName: 'WiFiSatellite', - displayName: 'WiFiSatellite', - hiddenService: false, - optionalCharacteristics: [], - primaryService: false, - }, - WiFiTransport: { - UUID: '0000022A-0000-1000-8000-0026BB765291', - characteristics: [ - { - UUID: '0000022B-0000-1000-8000-0026BB765291', - constructorName: 'CurrentTransport', - displayName: 'Current Transport', - eventOnlyCharacteristic: false, - props: { - format: 'bool', - perms: ['pr'], - }, - value: false, - }, - { - UUID: '0000022C-0000-1000-8000-0026BB765291', - constructorName: 'WiFiCapabilities', - displayName: 'Wi-Fi Capabilities', - eventOnlyCharacteristic: false, - props: { - format: 'uint32', - perms: ['pr'], - }, - value: 0, - }, - ], - constructorName: 'WiFiTransport', - displayName: 'WiFiTransport', - hiddenService: false, - optionalCharacteristics: [ - { - UUID: '0000022D-0000-1000-8000-0026BB765291', - constructorName: 'WiFiConfigurationControl', - displayName: 'Wi-Fi Configuration Control', - eventOnlyCharacteristic: false, - props: { - format: 'tlv8', - perms: ['ev', 'pr', 'pw', 'tw', 'wr'], - }, - value: '', - }, - ], - primaryService: false, - }, - Window: { - UUID: '0000008B-0000-1000-8000-0026BB765291', - characteristics: [ - { - UUID: '0000006D-0000-1000-8000-0026BB765291', - constructorName: 'CurrentPosition', - displayName: 'Current Position', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 100, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - unit: 'percentage', - }, - value: 0, - }, - { - UUID: '00000072-0000-1000-8000-0026BB765291', - constructorName: 'PositionState', - displayName: 'Position State', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 2, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - validValues: [0, 1, 2], - }, - value: 0, - }, - { - UUID: '0000007C-0000-1000-8000-0026BB765291', - constructorName: 'TargetPosition', - displayName: 'Target Position', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 100, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr', 'pw'], - unit: 'percentage', - }, - value: 0, - }, - ], - constructorName: 'Window', - displayName: 'Window', - hiddenService: false, - optionalCharacteristics: [ - { - UUID: '00000023-0000-1000-8000-0026BB765291', - constructorName: 'Name', - displayName: 'Name', - eventOnlyCharacteristic: false, - props: { - format: 'string', - maxLen: 64, - perms: ['pr'], - }, - value: '', - }, - { - UUID: '00000024-0000-1000-8000-0026BB765291', - constructorName: 'ObstructionDetected', - displayName: 'Obstruction Detected', - eventOnlyCharacteristic: false, - props: { - format: 'bool', - perms: ['ev', 'pr'], - }, - value: false, - }, - { - UUID: '0000006F-0000-1000-8000-0026BB765291', - constructorName: 'HoldPosition', - displayName: 'Hold Position', - eventOnlyCharacteristic: false, - props: { - format: 'bool', - perms: ['pw'], - }, - value: false, - }, - ], - primaryService: false, - }, - WindowCovering: { - UUID: '0000008C-0000-1000-8000-0026BB765291', - characteristics: [ - { - UUID: '0000006D-0000-1000-8000-0026BB765291', - constructorName: 'CurrentPosition', - displayName: 'Current Position', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 100, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - unit: 'percentage', - }, - value: 0, - }, - { - UUID: '00000072-0000-1000-8000-0026BB765291', - constructorName: 'PositionState', - displayName: 'Position State', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 2, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr'], - validValues: [0, 1, 2], - }, - value: 0, - }, - { - UUID: '0000007C-0000-1000-8000-0026BB765291', - constructorName: 'TargetPosition', - displayName: 'Target Position', - eventOnlyCharacteristic: false, - props: { - format: 'uint8', - maxValue: 100, - minStep: 1, - minValue: 0, - perms: ['ev', 'pr', 'pw'], - unit: 'percentage', - }, - value: 0, - }, - ], - constructorName: 'WindowCovering', - displayName: 'WindowCovering', - hiddenService: false, - optionalCharacteristics: [ - { - UUID: '0000006C-0000-1000-8000-0026BB765291', - constructorName: 'CurrentHorizontalTiltAngle', - displayName: 'Current Horizontal Tilt Angle', - eventOnlyCharacteristic: false, - props: { - format: 'int', - maxValue: 90, - minStep: 1, - minValue: -90, - perms: ['ev', 'pr'], - unit: 'arcdegrees', - }, - value: -90, - }, - { - UUID: '0000007B-0000-1000-8000-0026BB765291', - constructorName: 'TargetHorizontalTiltAngle', - displayName: 'Target Horizontal Tilt Angle', - eventOnlyCharacteristic: false, - props: { - format: 'int', - maxValue: 90, - minStep: 1, - minValue: -90, - perms: ['ev', 'pr', 'pw'], - unit: 'arcdegrees', - }, - value: -90, - }, - { - UUID: '00000023-0000-1000-8000-0026BB765291', - constructorName: 'Name', - displayName: 'Name', - eventOnlyCharacteristic: false, - props: { - format: 'string', - maxLen: 64, - perms: ['pr'], - }, - value: '', - }, - { - UUID: '00000024-0000-1000-8000-0026BB765291', - constructorName: 'ObstructionDetected', - displayName: 'Obstruction Detected', - eventOnlyCharacteristic: false, - props: { - format: 'bool', - perms: ['ev', 'pr'], - }, - value: false, - }, - { - UUID: '0000006F-0000-1000-8000-0026BB765291', - constructorName: 'HoldPosition', - displayName: 'Hold Position', - eventOnlyCharacteristic: false, - props: { - format: 'bool', - perms: ['pw'], - }, - value: false, - }, - { - UUID: '0000006E-0000-1000-8000-0026BB765291', - constructorName: 'CurrentVerticalTiltAngle', - displayName: 'Current Vertical Tilt Angle', - eventOnlyCharacteristic: false, - props: { - format: 'int', - maxValue: 90, - minStep: 1, - minValue: -90, - perms: ['ev', 'pr'], - unit: 'arcdegrees', - }, - value: -90, - }, - { - UUID: '0000007D-0000-1000-8000-0026BB765291', - constructorName: 'TargetVerticalTiltAngle', - displayName: 'Target Vertical Tilt Angle', - eventOnlyCharacteristic: false, - props: { - format: 'int', - maxValue: 90, - minStep: 1, - minValue: -90, - perms: ['ev', 'pr', 'pw'], - unit: 'arcdegrees', - }, - value: -90, - }, - ], - primaryService: false, - }, + AccessCode: { + UUID: '00000260-0000-1000-8000-0026BB765291', + characteristics: [ + { + UUID: '00000262-0000-1000-8000-0026BB765291', + constructorName: 'AccessCodeControlPoint', + displayName: 'Access Code Control Point', + eventOnlyCharacteristic: false, + props: { + format: 'tlv8', + perms: ['pr', 'pw', 'wr'] + }, + value: '' + }, + { + UUID: '00000261-0000-1000-8000-0026BB765291', + constructorName: 'AccessCodeSupportedConfiguration', + displayName: 'Access Code Supported Configuration', + eventOnlyCharacteristic: false, + props: { + format: 'tlv8', + perms: ['pr'] + }, + value: '' + }, + { + UUID: '00000263-0000-1000-8000-0026BB765291', + constructorName: 'ConfigurationState', + displayName: 'Configuration State', + eventOnlyCharacteristic: false, + props: { + format: 'uint16', + perms: ['ev', 'pr'] + }, + value: 0 + } + ], + constructorName: 'AccessCode', + displayName: 'AccessCode', + hiddenService: false, + optionalCharacteristics: [], + primaryService: false + }, + AccessControl: { + UUID: '000000DA-0000-1000-8000-0026BB765291', + characteristics: [ + { + UUID: '000000E5-0000-1000-8000-0026BB765291', + constructorName: 'AccessControlLevel', + displayName: 'Access Control Level', + eventOnlyCharacteristic: false, + props: { + format: 'uint16', + maxValue: 2, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr', 'pw'] + }, + value: 0 + } + ], + constructorName: 'AccessControl', + displayName: 'AccessControl', + hiddenService: false, + optionalCharacteristics: [ + { + UUID: '000000E4-0000-1000-8000-0026BB765291', + constructorName: 'PasswordSetting', + displayName: 'Password Setting', + eventOnlyCharacteristic: false, + props: { + format: 'tlv8', + perms: ['ev', 'pr', 'pw'] + }, + value: '' + } + ], + primaryService: false + }, + AccessoryInformation: { + UUID: '0000003E-0000-1000-8000-0026BB765291', + characteristics: [ + { + UUID: '00000014-0000-1000-8000-0026BB765291', + constructorName: 'Identify', + displayName: 'Identify', + eventOnlyCharacteristic: false, + props: { + format: 'bool', + perms: ['pw'] + }, + value: false + }, + { + UUID: '00000020-0000-1000-8000-0026BB765291', + constructorName: 'Manufacturer', + displayName: 'Manufacturer', + eventOnlyCharacteristic: false, + props: { + format: 'string', + maxLen: 64, + perms: ['pr'] + }, + value: 'Default-Manufacturer' + }, + { + UUID: '00000021-0000-1000-8000-0026BB765291', + constructorName: 'Model', + displayName: 'Model', + eventOnlyCharacteristic: false, + props: { + format: 'string', + maxLen: 64, + perms: ['pr'] + }, + value: 'Default-Model' + }, + { + UUID: '00000023-0000-1000-8000-0026BB765291', + constructorName: 'Name', + displayName: 'Name', + eventOnlyCharacteristic: false, + props: { + format: 'string', + maxLen: 64, + perms: ['pr'] + }, + value: 'Unnamed Service' + }, + { + UUID: '00000030-0000-1000-8000-0026BB765291', + constructorName: 'SerialNumber', + displayName: 'Serial Number', + eventOnlyCharacteristic: false, + props: { + format: 'string', + maxLen: 64, + perms: ['pr'] + }, + value: 'Default-SerialNumber' + }, + { + UUID: '00000052-0000-1000-8000-0026BB765291', + constructorName: 'FirmwareRevision', + displayName: 'Firmware Revision', + eventOnlyCharacteristic: false, + props: { + format: 'string', + perms: ['pr'] + }, + value: '0.0.0' + } + ], + constructorName: 'AccessoryInformation', + displayName: 'AccessoryInformation', + hiddenService: false, + optionalCharacteristics: [ + { + UUID: '000000A6-0000-1000-8000-0026BB765291', + constructorName: 'AccessoryFlags', + displayName: 'Accessory Flags', + eventOnlyCharacteristic: false, + props: { + format: 'uint32', + perms: ['ev', 'pr'] + }, + value: 0 + }, + { + UUID: '000000A4-0000-1000-8000-0026BB765291', + constructorName: 'AppMatchingIdentifier', + displayName: 'App Matching Identifier', + eventOnlyCharacteristic: false, + props: { + format: 'tlv8', + perms: ['pr'] + }, + value: '' + }, + { + UUID: '000000E3-0000-1000-8000-0026BB765291', + constructorName: 'ConfiguredName', + displayName: 'Configured Name', + eventOnlyCharacteristic: false, + props: { + format: 'string', + perms: ['ev', 'pr', 'pw'] + }, + value: '' + }, + { + UUID: '0000026D-0000-1000-8000-0026BB765291', + constructorName: 'MatterFirmwareRevisionNumber', + displayName: 'Matter Firmware Revision Number', + eventOnlyCharacteristic: false, + props: { + format: 'uint32', + perms: ['ev', 'pr'] + }, + value: 0 + }, + { + UUID: '0000026C-0000-1000-8000-0026BB765291', + constructorName: 'HardwareFinish', + displayName: 'Hardware Finish', + eventOnlyCharacteristic: false, + props: { + format: 'tlv8', + perms: ['pr'] + }, + value: '' + }, + { + UUID: '00000053-0000-1000-8000-0026BB765291', + constructorName: 'HardwareRevision', + displayName: 'Hardware Revision', + eventOnlyCharacteristic: false, + props: { + format: 'string', + perms: ['pr'] + }, + value: '' + }, + { + UUID: '00000220-0000-1000-8000-0026BB765291', + constructorName: 'ProductData', + displayName: 'Product Data', + eventOnlyCharacteristic: false, + props: { + format: 'data', + perms: ['pr'] + }, + value: '' + }, + { + UUID: '00000054-0000-1000-8000-0026BB765291', + constructorName: 'SoftwareRevision', + displayName: 'Software Revision', + eventOnlyCharacteristic: false, + props: { + format: 'string', + perms: ['pr'] + }, + value: '' + } + ], + primaryService: false + }, + AccessoryMetrics: { + UUID: '00000270-0000-1000-8000-0026BB765291', + characteristics: [ + { + UUID: '000000B0-0000-1000-8000-0026BB765291', + constructorName: 'Active', + displayName: 'Active', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr', 'pw'], + validValues: [0, 1] + }, + value: 0 + }, + { + UUID: '00000272-0000-1000-8000-0026BB765291', + constructorName: 'MetricsBufferFullState', + displayName: 'Metrics Buffer Full State', + eventOnlyCharacteristic: false, + props: { + format: 'bool', + perms: ['ev', 'pr'] + }, + value: false + }, + { + UUID: '00000271-0000-1000-8000-0026BB765291', + constructorName: 'SupportedMetrics', + displayName: 'Supported Metrics', + eventOnlyCharacteristic: false, + props: { + format: 'tlv8', + perms: ['pr', 'pw'] + }, + value: '' + } + ], + constructorName: 'AccessoryMetrics', + displayName: 'AccessoryMetrics', + hiddenService: false, + optionalCharacteristics: [], + primaryService: false + }, + AccessoryRuntimeInformation: { + UUID: '00000239-0000-1000-8000-0026BB765291', + characteristics: [ + { + UUID: '0000023C-0000-1000-8000-0026BB765291', + constructorName: 'Ping', + displayName: 'Ping', + eventOnlyCharacteristic: false, + props: { + format: 'data', + perms: ['pr'] + }, + value: '' + } + ], + constructorName: 'AccessoryRuntimeInformation', + displayName: 'AccessoryRuntimeInformation', + hiddenService: false, + optionalCharacteristics: [ + { + UUID: '0000023B-0000-1000-8000-0026BB765291', + constructorName: 'ActivityInterval', + displayName: 'Activity Interval', + eventOnlyCharacteristic: false, + props: { + format: 'uint32', + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'] + }, + value: 0 + }, + { + UUID: '0000024A-0000-1000-8000-0026BB765291', + constructorName: 'HeartBeat', + displayName: 'Heart Beat', + eventOnlyCharacteristic: false, + props: { + format: 'uint32', + perms: ['ev', 'pr'] + }, + value: 0 + }, + { + UUID: '0000023A-0000-1000-8000-0026BB765291', + constructorName: 'SleepInterval', + displayName: 'Sleep Interval', + eventOnlyCharacteristic: false, + props: { + format: 'uint32', + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'] + }, + value: 0 + } + ], + primaryService: false + }, + AirPurifier: { + UUID: '000000BB-0000-1000-8000-0026BB765291', + characteristics: [ + { + UUID: '000000B0-0000-1000-8000-0026BB765291', + constructorName: 'Active', + displayName: 'Active', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr', 'pw'], + validValues: [0, 1] + }, + value: 0 + }, + { + UUID: '000000A9-0000-1000-8000-0026BB765291', + constructorName: 'CurrentAirPurifierState', + displayName: 'Current Air Purifier State', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 2, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'], + validValues: [0, 1, 2] + }, + value: 0 + }, + { + UUID: '000000A8-0000-1000-8000-0026BB765291', + constructorName: 'TargetAirPurifierState', + displayName: 'Target Air Purifier State', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr', 'pw'], + validValues: [0, 1] + }, + value: 0 + } + ], + constructorName: 'AirPurifier', + displayName: 'AirPurifier', + hiddenService: false, + optionalCharacteristics: [ + { + UUID: '000000A7-0000-1000-8000-0026BB765291', + constructorName: 'LockPhysicalControls', + displayName: 'Lock Physical Controls', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr', 'pw'], + validValues: [0, 1] + }, + value: 0 + }, + { + UUID: '00000023-0000-1000-8000-0026BB765291', + constructorName: 'Name', + displayName: 'Name', + eventOnlyCharacteristic: false, + props: { + format: 'string', + maxLen: 64, + perms: ['pr'] + }, + value: '' + }, + { + UUID: '00000029-0000-1000-8000-0026BB765291', + constructorName: 'RotationSpeed', + displayName: 'Rotation Speed', + eventOnlyCharacteristic: false, + props: { + format: 'float', + maxValue: 100, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr', 'pw'], + unit: 'percentage' + }, + value: 0 + }, + { + UUID: '000000B6-0000-1000-8000-0026BB765291', + constructorName: 'SwingMode', + displayName: 'Swing Mode', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr', 'pw'], + validValues: [0, 1] + }, + value: 0 + } + ], + primaryService: false + }, + AirQualitySensor: { + UUID: '0000008D-0000-1000-8000-0026BB765291', + characteristics: [ + { + UUID: '00000095-0000-1000-8000-0026BB765291', + constructorName: 'AirQuality', + displayName: 'Air Quality', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 5, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'], + validValues: [0, 1, 2, 3, 4, 5] + }, + value: 0 + } + ], + constructorName: 'AirQualitySensor', + displayName: 'AirQualitySensor', + hiddenService: false, + optionalCharacteristics: [ + { + UUID: '000000C4-0000-1000-8000-0026BB765291', + constructorName: 'NitrogenDioxideDensity', + displayName: 'Nitrogen Dioxide Density', + eventOnlyCharacteristic: false, + props: { + format: 'float', + maxValue: 1000, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'] + }, + value: 0 + }, + { + UUID: '000000C3-0000-1000-8000-0026BB765291', + constructorName: 'OzoneDensity', + displayName: 'Ozone Density', + eventOnlyCharacteristic: false, + props: { + format: 'float', + maxValue: 1000, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'] + }, + value: 0 + }, + { + UUID: '000000C7-0000-1000-8000-0026BB765291', + constructorName: 'PM10Density', + displayName: 'PM10 Density', + eventOnlyCharacteristic: false, + props: { + format: 'float', + maxValue: 1000, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'] + }, + value: 0 + }, + { + UUID: '000000C6-0000-1000-8000-0026BB765291', + constructorName: 'PM2_5Density', + displayName: 'PM2.5 Density', + eventOnlyCharacteristic: false, + props: { + format: 'float', + maxValue: 1000, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'] + }, + value: 0 + }, + { + UUID: '000000C5-0000-1000-8000-0026BB765291', + constructorName: 'SulphurDioxideDensity', + displayName: 'Sulphur Dioxide Density', + eventOnlyCharacteristic: false, + props: { + format: 'float', + maxValue: 1000, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'] + }, + value: 0 + }, + { + UUID: '000000C8-0000-1000-8000-0026BB765291', + constructorName: 'VOCDensity', + displayName: 'VOC Density', + eventOnlyCharacteristic: false, + props: { + format: 'float', + maxValue: 1000, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'] + }, + value: 0 + }, + { + UUID: '00000023-0000-1000-8000-0026BB765291', + constructorName: 'Name', + displayName: 'Name', + eventOnlyCharacteristic: false, + props: { + format: 'string', + maxLen: 64, + perms: ['pr'] + }, + value: '' + }, + { + UUID: '00000075-0000-1000-8000-0026BB765291', + constructorName: 'StatusActive', + displayName: 'Status Active', + eventOnlyCharacteristic: false, + props: { + format: 'bool', + perms: ['ev', 'pr'] + }, + value: false + }, + { + UUID: '00000077-0000-1000-8000-0026BB765291', + constructorName: 'StatusFault', + displayName: 'Status Fault', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'], + validValues: [0, 1] + }, + value: 0 + }, + { + UUID: '00000079-0000-1000-8000-0026BB765291', + constructorName: 'StatusLowBattery', + displayName: 'Status Low Battery', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'], + validValues: [0, 1] + }, + value: 0 + }, + { + UUID: '0000007A-0000-1000-8000-0026BB765291', + constructorName: 'StatusTampered', + displayName: 'Status Tampered', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'], + validValues: [0, 1] + }, + value: 0 + } + ], + primaryService: false + }, + AssetUpdate: { + UUID: '00000267-0000-1000-8000-0026BB765291', + characteristics: [ + { + UUID: '00000269-0000-1000-8000-0026BB765291', + constructorName: 'AssetUpdateReadiness', + displayName: 'Asset Update Readiness', + eventOnlyCharacteristic: false, + props: { + format: 'uint32', + perms: ['ev', 'pr'] + }, + value: 0 + }, + { + UUID: '00000268-0000-1000-8000-0026BB765291', + constructorName: 'SupportedAssetTypes', + displayName: 'Supported Asset Types', + eventOnlyCharacteristic: false, + props: { + format: 'uint32', + perms: ['pr'] + }, + value: 0 + } + ], + constructorName: 'AssetUpdate', + displayName: 'AssetUpdate', + hiddenService: false, + optionalCharacteristics: [], + primaryService: false + }, + Assistant: { + UUID: '0000026A-0000-1000-8000-0026BB765291', + characteristics: [ + { + UUID: '000000B0-0000-1000-8000-0026BB765291', + constructorName: 'Active', + displayName: 'Active', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr', 'pw'], + validValues: [0, 1] + }, + value: 0 + }, + { + UUID: '000000E6-0000-1000-8000-0026BB765291', + constructorName: 'Identifier', + displayName: 'Identifier', + eventOnlyCharacteristic: false, + props: { + format: 'uint32', + perms: ['pr'] + }, + value: 0 + }, + { + UUID: '00000023-0000-1000-8000-0026BB765291', + constructorName: 'Name', + displayName: 'Name', + eventOnlyCharacteristic: false, + props: { + format: 'string', + maxLen: 64, + perms: ['pr'] + }, + value: 'Unnamed Service' + } + ], + constructorName: 'Assistant', + displayName: 'Assistant', + hiddenService: false, + optionalCharacteristics: [], + primaryService: false + }, + AudioStreamManagement: { + UUID: '00000127-0000-1000-8000-0026BB765291', + characteristics: [ + { + UUID: '00000115-0000-1000-8000-0026BB765291', + constructorName: 'SupportedAudioStreamConfiguration', + displayName: 'Supported Audio Stream Configuration', + eventOnlyCharacteristic: false, + props: { + format: 'tlv8', + perms: ['pr'] + }, + value: '' + }, + { + UUID: '00000128-0000-1000-8000-0026BB765291', + constructorName: 'SelectedAudioStreamConfiguration', + displayName: 'Selected Audio Stream Configuration', + eventOnlyCharacteristic: false, + props: { + format: 'tlv8', + perms: ['pr', 'pw'] + }, + value: '' + } + ], + constructorName: 'AudioStreamManagement', + displayName: 'AudioStreamManagement', + hiddenService: false, + optionalCharacteristics: [], + primaryService: false + }, + Battery: { + UUID: '00000096-0000-1000-8000-0026BB765291', + characteristics: [ + { + UUID: '00000079-0000-1000-8000-0026BB765291', + constructorName: 'StatusLowBattery', + displayName: 'Status Low Battery', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'], + validValues: [0, 1] + }, + value: 0 + } + ], + constructorName: 'Battery', + displayName: 'Battery', + hiddenService: false, + optionalCharacteristics: [ + { + UUID: '00000068-0000-1000-8000-0026BB765291', + constructorName: 'BatteryLevel', + displayName: 'Battery Level', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 100, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'], + unit: 'percentage' + }, + value: 0 + }, + { + UUID: '0000008F-0000-1000-8000-0026BB765291', + constructorName: 'ChargingState', + displayName: 'Charging State', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 2, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'], + validValues: [0, 1, 2] + }, + value: 0 + }, + { + UUID: '00000023-0000-1000-8000-0026BB765291', + constructorName: 'Name', + displayName: 'Name', + eventOnlyCharacteristic: false, + props: { + format: 'string', + maxLen: 64, + perms: ['pr'] + }, + value: '' + } + ], + primaryService: false + }, + BatteryService: { + nrchkbDisabledText: 'BatteryService (deprecated, replaced by Battery)' + }, + BridgeConfiguration: { + nrchkbDisabledText: 'BridgeConfiguration (deprecated, unused)' + }, + BridgingState: { + nrchkbDisabledText: 'BridgingState (deprecated, unused)' + }, + CameraControl: { + nrchkbDisabledText: 'CameraControl (deprecated, replaced by)' + }, + CameraEventRecordingManagement: { + nrchkbDisabledText: + 'CameraEventRecordingManagement (deprecated, replaced by CameraRecordingManagement)' + }, + CameraOperatingMode: { + UUID: '0000021A-0000-1000-8000-0026BB765291', + characteristics: [ + { + UUID: '00000223-0000-1000-8000-0026BB765291', + constructorName: 'EventSnapshotsActive', + displayName: 'Event Snapshots Active', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minValue: 0, + perms: ['ev', 'pr', 'pw'], + validValues: [0, 1] + }, + value: 0 + }, + { + UUID: '0000021B-0000-1000-8000-0026BB765291', + constructorName: 'HomeKitCameraActive', + displayName: 'HomeKit Camera Active', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minValue: 0, + perms: ['ev', 'pr', 'pw'], + validValues: [0, 1] + }, + value: 0 + } + ], + constructorName: 'CameraOperatingMode', + displayName: 'CameraOperatingMode', + hiddenService: false, + optionalCharacteristics: [ + { + UUID: '0000021D-0000-1000-8000-0026BB765291', + constructorName: 'CameraOperatingModeIndicator', + displayName: 'Camera Operating Mode Indicator', + eventOnlyCharacteristic: false, + props: { + format: 'bool', + perms: ['ev', 'pr', 'pw', 'tw'] + }, + value: false + }, + { + UUID: '00000227-0000-1000-8000-0026BB765291', + constructorName: 'ManuallyDisabled', + displayName: 'Manually Disabled', + eventOnlyCharacteristic: false, + props: { + format: 'bool', + perms: ['ev', 'pr'] + }, + value: false + }, + { + UUID: '0000011B-0000-1000-8000-0026BB765291', + constructorName: 'NightVision', + displayName: 'Night Vision', + eventOnlyCharacteristic: false, + props: { + format: 'bool', + perms: ['ev', 'pr', 'pw', 'tw'] + }, + value: false + }, + { + UUID: '00000225-0000-1000-8000-0026BB765291', + constructorName: 'PeriodicSnapshotsActive', + displayName: 'Periodic Snapshots Active', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + perms: ['ev', 'pr', 'pw'], + validValues: [0, 1] + }, + value: 0 + }, + { + UUID: '0000021C-0000-1000-8000-0026BB765291', + constructorName: 'ThirdPartyCameraActive', + displayName: 'Third Party Camera Active', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + perms: ['ev', 'pr'], + validValues: [0, 1] + }, + value: 0 + }, + { + UUID: '00000224-0000-1000-8000-0026BB765291', + constructorName: 'DiagonalFieldOfView', + displayName: 'Diagonal Field Of View', + eventOnlyCharacteristic: false, + props: { + format: 'float', + maxValue: 360, + minValue: 0, + perms: ['ev', 'pr'], + unit: 'arcdegrees' + }, + value: 0 + } + ], + primaryService: false + }, + CameraRTPStreamManagement: { + UUID: '00000110-0000-1000-8000-0026BB765291', + characteristics: [ + { + UUID: '00000117-0000-1000-8000-0026BB765291', + constructorName: 'SelectedRTPStreamConfiguration', + displayName: 'Selected RTP Stream Configuration', + eventOnlyCharacteristic: false, + props: { + format: 'tlv8', + perms: ['pr', 'pw'] + }, + value: '' + }, + { + UUID: '00000118-0000-1000-8000-0026BB765291', + constructorName: 'SetupEndpoints', + displayName: 'Setup Endpoints', + eventOnlyCharacteristic: false, + props: { + format: 'tlv8', + perms: ['pr', 'pw'] + }, + value: '' + }, + { + UUID: '00000120-0000-1000-8000-0026BB765291', + constructorName: 'StreamingStatus', + displayName: 'Streaming Status', + eventOnlyCharacteristic: false, + props: { + format: 'tlv8', + perms: ['ev', 'pr'] + }, + value: '' + }, + { + UUID: '00000115-0000-1000-8000-0026BB765291', + constructorName: 'SupportedAudioStreamConfiguration', + displayName: 'Supported Audio Stream Configuration', + eventOnlyCharacteristic: false, + props: { + format: 'tlv8', + perms: ['pr'] + }, + value: '' + }, + { + UUID: '00000116-0000-1000-8000-0026BB765291', + constructorName: 'SupportedRTPConfiguration', + displayName: 'Supported RTP Configuration', + eventOnlyCharacteristic: false, + props: { + format: 'tlv8', + perms: ['pr'] + }, + value: '' + }, + { + UUID: '00000114-0000-1000-8000-0026BB765291', + constructorName: 'SupportedVideoStreamConfiguration', + displayName: 'Supported Video Stream Configuration', + eventOnlyCharacteristic: false, + props: { + format: 'tlv8', + perms: ['pr'] + }, + value: '' + } + ], + constructorName: 'CameraRTPStreamManagement', + displayName: 'CameraRTPStreamManagement', + hiddenService: false, + optionalCharacteristics: [ + { + UUID: '000000B0-0000-1000-8000-0026BB765291', + constructorName: 'Active', + displayName: 'Active', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr', 'pw'], + validValues: [0, 1] + }, + value: 0 + } + ], + primaryService: false + }, + CameraRecordingManagement: { + UUID: '00000204-0000-1000-8000-0026BB765291', + characteristics: [ + { + UUID: '000000B0-0000-1000-8000-0026BB765291', + constructorName: 'Active', + displayName: 'Active', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr', 'pw'], + validValues: [0, 1] + }, + value: 0 + }, + { + UUID: '00000209-0000-1000-8000-0026BB765291', + constructorName: 'SelectedCameraRecordingConfiguration', + displayName: 'Selected Camera Recording Configuration', + eventOnlyCharacteristic: false, + props: { + format: 'tlv8', + perms: ['ev', 'pr', 'pw'] + }, + value: '' + }, + { + UUID: '00000207-0000-1000-8000-0026BB765291', + constructorName: 'SupportedAudioRecordingConfiguration', + displayName: 'Supported Audio Recording Configuration', + eventOnlyCharacteristic: false, + props: { + format: 'tlv8', + perms: ['ev', 'pr'] + }, + value: '' + }, + { + UUID: '00000205-0000-1000-8000-0026BB765291', + constructorName: 'SupportedCameraRecordingConfiguration', + displayName: 'Supported Camera Recording Configuration', + eventOnlyCharacteristic: false, + props: { + format: 'tlv8', + perms: ['ev', 'pr'] + }, + value: '' + }, + { + UUID: '00000206-0000-1000-8000-0026BB765291', + constructorName: 'SupportedVideoRecordingConfiguration', + displayName: 'Supported Video Recording Configuration', + eventOnlyCharacteristic: false, + props: { + format: 'tlv8', + perms: ['ev', 'pr'] + }, + value: '' + } + ], + constructorName: 'CameraRecordingManagement', + displayName: 'CameraRecordingManagement', + hiddenService: false, + optionalCharacteristics: [ + { + UUID: '00000226-0000-1000-8000-0026BB765291', + constructorName: 'RecordingAudioActive', + displayName: 'Recording Audio Active', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + perms: ['ev', 'pr', 'pw', 'tw'], + validValues: [0, 1] + }, + value: 0 + } + ], + primaryService: false + }, + CarbonDioxideSensor: { + UUID: '00000097-0000-1000-8000-0026BB765291', + characteristics: [ + { + UUID: '00000092-0000-1000-8000-0026BB765291', + constructorName: 'CarbonDioxideDetected', + displayName: 'Carbon Dioxide Detected', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'], + validValues: [0, 1] + }, + value: 0 + } + ], + constructorName: 'CarbonDioxideSensor', + displayName: 'CarbonDioxideSensor', + hiddenService: false, + optionalCharacteristics: [ + { + UUID: '00000093-0000-1000-8000-0026BB765291', + constructorName: 'CarbonDioxideLevel', + displayName: 'Carbon Dioxide Level', + eventOnlyCharacteristic: false, + props: { + format: 'float', + maxValue: 100000, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'] + }, + value: 0 + }, + { + UUID: '00000094-0000-1000-8000-0026BB765291', + constructorName: 'CarbonDioxidePeakLevel', + displayName: 'Carbon Dioxide Peak Level', + eventOnlyCharacteristic: false, + props: { + format: 'float', + maxValue: 100000, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'] + }, + value: 0 + }, + { + UUID: '00000023-0000-1000-8000-0026BB765291', + constructorName: 'Name', + displayName: 'Name', + eventOnlyCharacteristic: false, + props: { + format: 'string', + maxLen: 64, + perms: ['pr'] + }, + value: '' + }, + { + UUID: '00000075-0000-1000-8000-0026BB765291', + constructorName: 'StatusActive', + displayName: 'Status Active', + eventOnlyCharacteristic: false, + props: { + format: 'bool', + perms: ['ev', 'pr'] + }, + value: false + }, + { + UUID: '00000077-0000-1000-8000-0026BB765291', + constructorName: 'StatusFault', + displayName: 'Status Fault', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'], + validValues: [0, 1] + }, + value: 0 + }, + { + UUID: '00000079-0000-1000-8000-0026BB765291', + constructorName: 'StatusLowBattery', + displayName: 'Status Low Battery', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'], + validValues: [0, 1] + }, + value: 0 + }, + { + UUID: '0000007A-0000-1000-8000-0026BB765291', + constructorName: 'StatusTampered', + displayName: 'Status Tampered', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'], + validValues: [0, 1] + }, + value: 0 + } + ], + primaryService: false + }, + CarbonMonoxideSensor: { + UUID: '0000007F-0000-1000-8000-0026BB765291', + characteristics: [ + { + UUID: '00000069-0000-1000-8000-0026BB765291', + constructorName: 'CarbonMonoxideDetected', + displayName: 'Carbon Monoxide Detected', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'], + validValues: [0, 1] + }, + value: 0 + } + ], + constructorName: 'CarbonMonoxideSensor', + displayName: 'CarbonMonoxideSensor', + hiddenService: false, + optionalCharacteristics: [ + { + UUID: '00000090-0000-1000-8000-0026BB765291', + constructorName: 'CarbonMonoxideLevel', + displayName: 'Carbon Monoxide Level', + eventOnlyCharacteristic: false, + props: { + format: 'float', + maxValue: 100, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'] + }, + value: 0 + }, + { + UUID: '00000091-0000-1000-8000-0026BB765291', + constructorName: 'CarbonMonoxidePeakLevel', + displayName: 'Carbon Monoxide Peak Level', + eventOnlyCharacteristic: false, + props: { + format: 'float', + maxValue: 100, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'] + }, + value: 0 + }, + { + UUID: '00000023-0000-1000-8000-0026BB765291', + constructorName: 'Name', + displayName: 'Name', + eventOnlyCharacteristic: false, + props: { + format: 'string', + maxLen: 64, + perms: ['pr'] + }, + value: '' + }, + { + UUID: '00000075-0000-1000-8000-0026BB765291', + constructorName: 'StatusActive', + displayName: 'Status Active', + eventOnlyCharacteristic: false, + props: { + format: 'bool', + perms: ['ev', 'pr'] + }, + value: false + }, + { + UUID: '00000077-0000-1000-8000-0026BB765291', + constructorName: 'StatusFault', + displayName: 'Status Fault', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'], + validValues: [0, 1] + }, + value: 0 + }, + { + UUID: '00000079-0000-1000-8000-0026BB765291', + constructorName: 'StatusLowBattery', + displayName: 'Status Low Battery', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'], + validValues: [0, 1] + }, + value: 0 + }, + { + UUID: '0000007A-0000-1000-8000-0026BB765291', + constructorName: 'StatusTampered', + displayName: 'Status Tampered', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'], + validValues: [0, 1] + }, + value: 0 + } + ], + primaryService: false + }, + CloudRelay: { + UUID: '0000005A-0000-1000-8000-0026BB765291', + characteristics: [ + { + UUID: '0000005E-0000-1000-8000-0026BB765291', + constructorName: 'RelayControlPoint', + displayName: 'Relay Control Point', + eventOnlyCharacteristic: false, + props: { + format: 'tlv8', + perms: ['ev', 'pr', 'pw'] + }, + value: '' + }, + { + UUID: '0000005C-0000-1000-8000-0026BB765291', + constructorName: 'RelayState', + displayName: 'Relay State', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 5, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'] + }, + value: 0 + }, + { + UUID: '0000005B-0000-1000-8000-0026BB765291', + constructorName: 'RelayEnabled', + displayName: 'Relay Enabled', + eventOnlyCharacteristic: false, + props: { + format: 'bool', + perms: ['ev', 'pr', 'pw'] + }, + value: false + } + ], + constructorName: 'CloudRelay', + displayName: 'CloudRelay', + hiddenService: false, + optionalCharacteristics: [], + primaryService: false + }, + ContactSensor: { + UUID: '00000080-0000-1000-8000-0026BB765291', + characteristics: [ + { + UUID: '0000006A-0000-1000-8000-0026BB765291', + constructorName: 'ContactSensorState', + displayName: 'Contact Sensor State', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'], + validValues: [0, 1] + }, + value: 0 + } + ], + constructorName: 'ContactSensor', + displayName: 'ContactSensor', + hiddenService: false, + optionalCharacteristics: [ + { + UUID: '00000023-0000-1000-8000-0026BB765291', + constructorName: 'Name', + displayName: 'Name', + eventOnlyCharacteristic: false, + props: { + format: 'string', + maxLen: 64, + perms: ['pr'] + }, + value: '' + }, + { + UUID: '00000075-0000-1000-8000-0026BB765291', + constructorName: 'StatusActive', + displayName: 'Status Active', + eventOnlyCharacteristic: false, + props: { + format: 'bool', + perms: ['ev', 'pr'] + }, + value: false + }, + { + UUID: '00000077-0000-1000-8000-0026BB765291', + constructorName: 'StatusFault', + displayName: 'Status Fault', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'], + validValues: [0, 1] + }, + value: 0 + }, + { + UUID: '00000079-0000-1000-8000-0026BB765291', + constructorName: 'StatusLowBattery', + displayName: 'Status Low Battery', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'], + validValues: [0, 1] + }, + value: 0 + }, + { + UUID: '0000007A-0000-1000-8000-0026BB765291', + constructorName: 'StatusTampered', + displayName: 'Status Tampered', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'], + validValues: [0, 1] + }, + value: 0 + } + ], + primaryService: false + }, + DataStreamTransportManagement: { + UUID: '00000129-0000-1000-8000-0026BB765291', + characteristics: [ + { + UUID: '00000131-0000-1000-8000-0026BB765291', + constructorName: 'SetupDataStreamTransport', + displayName: 'Setup Data Stream Transport', + eventOnlyCharacteristic: false, + props: { + format: 'tlv8', + perms: ['pr', 'pw', 'wr'] + }, + value: '' + }, + { + UUID: '00000130-0000-1000-8000-0026BB765291', + constructorName: 'SupportedDataStreamTransportConfiguration', + displayName: 'Supported Data Stream Transport Configuration', + eventOnlyCharacteristic: false, + props: { + format: 'tlv8', + perms: ['pr'] + }, + value: '' + }, + { + UUID: '00000037-0000-1000-8000-0026BB765291', + constructorName: 'Version', + displayName: 'Version', + eventOnlyCharacteristic: false, + props: { + format: 'string', + maxLen: 64, + perms: ['pr'] + }, + value: '' + } + ], + constructorName: 'DataStreamTransportManagement', + displayName: 'DataStreamTransportManagement', + hiddenService: false, + optionalCharacteristics: [], + primaryService: false + }, + Diagnostics: { + UUID: '00000237-0000-1000-8000-0026BB765291', + characteristics: [ + { + UUID: '00000238-0000-1000-8000-0026BB765291', + constructorName: 'SupportedDiagnosticsSnapshot', + displayName: 'Supported Diagnostics Snapshot', + eventOnlyCharacteristic: false, + props: { + format: 'tlv8', + perms: ['pr'] + }, + value: '' + } + ], + constructorName: 'Diagnostics', + displayName: 'Diagnostics', + hiddenService: false, + optionalCharacteristics: [ + { + UUID: '0000024D-0000-1000-8000-0026BB765291', + constructorName: 'SelectedDiagnosticsModes', + displayName: 'Selected Diagnostics Modes', + eventOnlyCharacteristic: false, + props: { + format: 'uint32', + perms: ['pr', 'pw'] + }, + value: 0 + }, + { + UUID: '0000024C-0000-1000-8000-0026BB765291', + constructorName: 'SupportedDiagnosticsModes', + displayName: 'Supported Diagnostics Modes', + eventOnlyCharacteristic: false, + props: { + format: 'uint32', + perms: ['pr'] + }, + value: 0 + } + ], + primaryService: false + }, + Door: { + UUID: '00000081-0000-1000-8000-0026BB765291', + characteristics: [ + { + UUID: '0000006D-0000-1000-8000-0026BB765291', + constructorName: 'CurrentPosition', + displayName: 'Current Position', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 100, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'], + unit: 'percentage' + }, + value: 0 + }, + { + UUID: '00000072-0000-1000-8000-0026BB765291', + constructorName: 'PositionState', + displayName: 'Position State', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 2, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'], + validValues: [0, 1, 2] + }, + value: 0 + }, + { + UUID: '0000007C-0000-1000-8000-0026BB765291', + constructorName: 'TargetPosition', + displayName: 'Target Position', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 100, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr', 'pw'], + unit: 'percentage' + }, + value: 0 + } + ], + constructorName: 'Door', + displayName: 'Door', + hiddenService: false, + optionalCharacteristics: [ + { + UUID: '00000023-0000-1000-8000-0026BB765291', + constructorName: 'Name', + displayName: 'Name', + eventOnlyCharacteristic: false, + props: { + format: 'string', + maxLen: 64, + perms: ['pr'] + }, + value: '' + }, + { + UUID: '00000024-0000-1000-8000-0026BB765291', + constructorName: 'ObstructionDetected', + displayName: 'Obstruction Detected', + eventOnlyCharacteristic: false, + props: { + format: 'bool', + perms: ['ev', 'pr'] + }, + value: false + }, + { + UUID: '0000006F-0000-1000-8000-0026BB765291', + constructorName: 'HoldPosition', + displayName: 'Hold Position', + eventOnlyCharacteristic: false, + props: { + format: 'bool', + perms: ['pw'] + }, + value: false + } + ], + primaryService: false + }, + Doorbell: { + UUID: '00000121-0000-1000-8000-0026BB765291', + characteristics: [ + { + UUID: '00000073-0000-1000-8000-0026BB765291', + constructorName: 'ProgrammableSwitchEvent', + displayName: 'Programmable Switch Event', + eventOnlyCharacteristic: true, + props: { + format: 'uint8', + maxValue: 2, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'], + validValues: [0, 1, 2] + }, + value: 0 + } + ], + constructorName: 'Doorbell', + displayName: 'Doorbell', + hiddenService: false, + optionalCharacteristics: [ + { + UUID: '00000008-0000-1000-8000-0026BB765291', + constructorName: 'Brightness', + displayName: 'Brightness', + eventOnlyCharacteristic: false, + props: { + format: 'int', + maxValue: 100, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr', 'pw'], + unit: 'percentage' + }, + value: 0 + }, + { + UUID: '0000011A-0000-1000-8000-0026BB765291', + constructorName: 'Mute', + displayName: 'Mute', + eventOnlyCharacteristic: false, + props: { + format: 'bool', + perms: ['ev', 'pr', 'pw'] + }, + value: false + }, + { + UUID: '00000023-0000-1000-8000-0026BB765291', + constructorName: 'Name', + displayName: 'Name', + eventOnlyCharacteristic: false, + props: { + format: 'string', + maxLen: 64, + perms: ['pr'] + }, + value: '' + }, + { + UUID: '00000232-0000-1000-8000-0026BB765291', + constructorName: 'OperatingStateResponse', + displayName: 'Operating State Response', + eventOnlyCharacteristic: false, + props: { + format: 'tlv8', + perms: ['ev', 'pr'] + }, + value: '' + }, + { + UUID: '00000119-0000-1000-8000-0026BB765291', + constructorName: 'Volume', + displayName: 'Volume', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 100, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr', 'pw'], + unit: 'percentage' + }, + value: 0 + } + ], + primaryService: false + }, + Fan: { + UUID: '00000040-0000-1000-8000-0026BB765291', + characteristics: [ + { + UUID: '00000025-0000-1000-8000-0026BB765291', + constructorName: 'On', + displayName: 'On', + eventOnlyCharacteristic: false, + props: { + format: 'bool', + perms: ['ev', 'pr', 'pw'] + }, + value: false + } + ], + constructorName: 'Fan', + displayName: 'Fan', + hiddenService: false, + optionalCharacteristics: [ + { + UUID: '00000023-0000-1000-8000-0026BB765291', + constructorName: 'Name', + displayName: 'Name', + eventOnlyCharacteristic: false, + props: { + format: 'string', + maxLen: 64, + perms: ['pr'] + }, + value: '' + }, + { + UUID: '00000028-0000-1000-8000-0026BB765291', + constructorName: 'RotationDirection', + displayName: 'Rotation Direction', + eventOnlyCharacteristic: false, + props: { + format: 'int', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr', 'pw'], + validValues: [0, 1] + }, + value: 0 + }, + { + UUID: '00000029-0000-1000-8000-0026BB765291', + constructorName: 'RotationSpeed', + displayName: 'Rotation Speed', + eventOnlyCharacteristic: false, + props: { + format: 'float', + maxValue: 100, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr', 'pw'], + unit: 'percentage' + }, + value: 0 + } + ], + primaryService: false + }, + Fanv2: { + UUID: '000000B7-0000-1000-8000-0026BB765291', + characteristics: [ + { + UUID: '000000B0-0000-1000-8000-0026BB765291', + constructorName: 'Active', + displayName: 'Active', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr', 'pw'], + validValues: [0, 1] + }, + value: 0 + } + ], + constructorName: 'Fanv2', + displayName: 'Fanv2', + hiddenService: false, + optionalCharacteristics: [ + { + UUID: '000000AF-0000-1000-8000-0026BB765291', + constructorName: 'CurrentFanState', + displayName: 'Current Fan State', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 2, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'], + validValues: [0, 1, 2] + }, + value: 0 + }, + { + UUID: '000000BF-0000-1000-8000-0026BB765291', + constructorName: 'TargetFanState', + displayName: 'Target Fan State', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr', 'pw'], + validValues: [0, 1] + }, + value: 0 + }, + { + UUID: '000000A7-0000-1000-8000-0026BB765291', + constructorName: 'LockPhysicalControls', + displayName: 'Lock Physical Controls', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr', 'pw'], + validValues: [0, 1] + }, + value: 0 + }, + { + UUID: '00000023-0000-1000-8000-0026BB765291', + constructorName: 'Name', + displayName: 'Name', + eventOnlyCharacteristic: false, + props: { + format: 'string', + maxLen: 64, + perms: ['pr'] + }, + value: '' + }, + { + UUID: '00000028-0000-1000-8000-0026BB765291', + constructorName: 'RotationDirection', + displayName: 'Rotation Direction', + eventOnlyCharacteristic: false, + props: { + format: 'int', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr', 'pw'], + validValues: [0, 1] + }, + value: 0 + }, + { + UUID: '00000029-0000-1000-8000-0026BB765291', + constructorName: 'RotationSpeed', + displayName: 'Rotation Speed', + eventOnlyCharacteristic: false, + props: { + format: 'float', + maxValue: 100, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr', 'pw'], + unit: 'percentage' + }, + value: 0 + }, + { + UUID: '000000B6-0000-1000-8000-0026BB765291', + constructorName: 'SwingMode', + displayName: 'Swing Mode', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr', 'pw'], + validValues: [0, 1] + }, + value: 0 + } + ], + primaryService: false + }, + Faucet: { + UUID: '000000D7-0000-1000-8000-0026BB765291', + characteristics: [ + { + UUID: '000000B0-0000-1000-8000-0026BB765291', + constructorName: 'Active', + displayName: 'Active', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr', 'pw'], + validValues: [0, 1] + }, + value: 0 + } + ], + constructorName: 'Faucet', + displayName: 'Faucet', + hiddenService: false, + optionalCharacteristics: [ + { + UUID: '00000023-0000-1000-8000-0026BB765291', + constructorName: 'Name', + displayName: 'Name', + eventOnlyCharacteristic: false, + props: { + format: 'string', + maxLen: 64, + perms: ['pr'] + }, + value: '' + }, + { + UUID: '00000077-0000-1000-8000-0026BB765291', + constructorName: 'StatusFault', + displayName: 'Status Fault', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'], + validValues: [0, 1] + }, + value: 0 + } + ], + primaryService: false + }, + FilterMaintenance: { + UUID: '000000BA-0000-1000-8000-0026BB765291', + characteristics: [ + { + UUID: '000000AC-0000-1000-8000-0026BB765291', + constructorName: 'FilterChangeIndication', + displayName: 'Filter Change Indication', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'], + validValues: [0, 1] + }, + value: 0 + } + ], + constructorName: 'FilterMaintenance', + displayName: 'FilterMaintenance', + hiddenService: false, + optionalCharacteristics: [ + { + UUID: '000000AB-0000-1000-8000-0026BB765291', + constructorName: 'FilterLifeLevel', + displayName: 'Filter Life Level', + eventOnlyCharacteristic: false, + props: { + format: 'float', + maxValue: 100, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'] + }, + value: 0 + }, + { + UUID: '000000AD-0000-1000-8000-0026BB765291', + constructorName: 'ResetFilterIndication', + displayName: 'Reset Filter Indication', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 1, + perms: ['pw'] + }, + value: 1 + }, + { + UUID: '00000023-0000-1000-8000-0026BB765291', + constructorName: 'Name', + displayName: 'Name', + eventOnlyCharacteristic: false, + props: { + format: 'string', + maxLen: 64, + perms: ['pr'] + }, + value: '' + } + ], + primaryService: false + }, + FirmwareUpdate: { + UUID: '00000236-0000-1000-8000-0026BB765291', + characteristics: [ + { + UUID: '00000234-0000-1000-8000-0026BB765291', + constructorName: 'FirmwareUpdateReadiness', + displayName: 'Firmware Update Readiness', + eventOnlyCharacteristic: false, + props: { + format: 'tlv8', + perms: ['ev', 'pr'] + }, + value: '' + }, + { + UUID: '00000235-0000-1000-8000-0026BB765291', + constructorName: 'FirmwareUpdateStatus', + displayName: 'Firmware Update Status', + eventOnlyCharacteristic: false, + props: { + format: 'tlv8', + perms: ['ev', 'pr'] + }, + value: '' + } + ], + constructorName: 'FirmwareUpdate', + displayName: 'FirmwareUpdate', + hiddenService: false, + optionalCharacteristics: [ + { + UUID: '0000026F-0000-1000-8000-0026BB765291', + constructorName: 'FirmwareUpdateProtocolList', + displayName: 'Firmware Update Protocol List', + eventOnlyCharacteristic: false, + props: { + format: 'tlv8', + perms: ['pr'] + }, + value: '' + }, + { + UUID: '0000026E-0000-1000-8000-0026BB765291', + constructorName: 'MatterFirmwareUpdateStatus', + displayName: 'Matter Firmware Update Status', + eventOnlyCharacteristic: false, + props: { + format: 'tlv8', + perms: ['ev', 'pr'] + }, + value: '' + }, + { + UUID: '00000249-0000-1000-8000-0026BB765291', + constructorName: 'StagedFirmwareVersion', + displayName: 'Staged Firmware Version', + eventOnlyCharacteristic: false, + props: { + format: 'string', + perms: ['ev', 'pr'] + }, + value: '' + }, + { + UUID: '00000233-0000-1000-8000-0026BB765291', + constructorName: 'SupportedFirmwareUpdateConfiguration', + displayName: 'Supported Firmware Update Configuration', + eventOnlyCharacteristic: false, + props: { + format: 'tlv8', + perms: ['pr'] + }, + value: '' + } + ], + primaryService: false + }, + GarageDoorOpener: { + UUID: '00000041-0000-1000-8000-0026BB765291', + characteristics: [ + { + UUID: '0000000E-0000-1000-8000-0026BB765291', + constructorName: 'CurrentDoorState', + displayName: 'Current Door State', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 4, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'], + validValues: [0, 1, 2, 3, 4] + }, + value: 0 + }, + { + UUID: '00000032-0000-1000-8000-0026BB765291', + constructorName: 'TargetDoorState', + displayName: 'Target Door State', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr', 'pw'], + validValues: [0, 1] + }, + value: 0 + }, + { + UUID: '00000024-0000-1000-8000-0026BB765291', + constructorName: 'ObstructionDetected', + displayName: 'Obstruction Detected', + eventOnlyCharacteristic: false, + props: { + format: 'bool', + perms: ['ev', 'pr'] + }, + value: false + } + ], + constructorName: 'GarageDoorOpener', + displayName: 'GarageDoorOpener', + hiddenService: false, + optionalCharacteristics: [ + { + UUID: '0000001D-0000-1000-8000-0026BB765291', + constructorName: 'LockCurrentState', + displayName: 'Lock Current State', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 3, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'], + validValues: [0, 1, 2, 3] + }, + value: 0 + }, + { + UUID: '0000001E-0000-1000-8000-0026BB765291', + constructorName: 'LockTargetState', + displayName: 'Lock Target State', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr', 'pw'], + validValues: [0, 1] + }, + value: 0 + }, + { + UUID: '00000023-0000-1000-8000-0026BB765291', + constructorName: 'Name', + displayName: 'Name', + eventOnlyCharacteristic: false, + props: { + format: 'string', + maxLen: 64, + perms: ['pr'] + }, + value: '' + } + ], + primaryService: false + }, + HeaterCooler: { + UUID: '000000BC-0000-1000-8000-0026BB765291', + characteristics: [ + { + UUID: '000000B0-0000-1000-8000-0026BB765291', + constructorName: 'Active', + displayName: 'Active', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr', 'pw'], + validValues: [0, 1] + }, + value: 0 + }, + { + UUID: '000000B1-0000-1000-8000-0026BB765291', + constructorName: 'CurrentHeaterCoolerState', + displayName: 'Current Heater-Cooler State', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 3, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'], + validValues: [0, 1, 2, 3] + }, + value: 0 + }, + { + UUID: '000000B2-0000-1000-8000-0026BB765291', + constructorName: 'TargetHeaterCoolerState', + displayName: 'Target Heater-Cooler State', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 2, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr', 'pw'], + validValues: [0, 1, 2] + }, + value: 0 + }, + { + UUID: '00000011-0000-1000-8000-0026BB765291', + constructorName: 'CurrentTemperature', + displayName: 'Current Temperature', + eventOnlyCharacteristic: false, + props: { + format: 'float', + maxValue: 100, + minStep: 0.1, + minValue: -270, + perms: ['ev', 'pr'], + unit: 'celsius' + }, + value: 0 + } + ], + constructorName: 'HeaterCooler', + displayName: 'HeaterCooler', + hiddenService: false, + optionalCharacteristics: [ + { + UUID: '000000A7-0000-1000-8000-0026BB765291', + constructorName: 'LockPhysicalControls', + displayName: 'Lock Physical Controls', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr', 'pw'], + validValues: [0, 1] + }, + value: 0 + }, + { + UUID: '00000023-0000-1000-8000-0026BB765291', + constructorName: 'Name', + displayName: 'Name', + eventOnlyCharacteristic: false, + props: { + format: 'string', + maxLen: 64, + perms: ['pr'] + }, + value: '' + }, + { + UUID: '00000029-0000-1000-8000-0026BB765291', + constructorName: 'RotationSpeed', + displayName: 'Rotation Speed', + eventOnlyCharacteristic: false, + props: { + format: 'float', + maxValue: 100, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr', 'pw'], + unit: 'percentage' + }, + value: 0 + }, + { + UUID: '000000B6-0000-1000-8000-0026BB765291', + constructorName: 'SwingMode', + displayName: 'Swing Mode', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr', 'pw'], + validValues: [0, 1] + }, + value: 0 + }, + { + UUID: '0000000D-0000-1000-8000-0026BB765291', + constructorName: 'CoolingThresholdTemperature', + displayName: 'Cooling Threshold Temperature', + eventOnlyCharacteristic: false, + props: { + format: 'float', + maxValue: 35, + minStep: 0.1, + minValue: 10, + perms: ['ev', 'pr', 'pw'], + unit: 'celsius' + }, + value: 10 + }, + { + UUID: '00000012-0000-1000-8000-0026BB765291', + constructorName: 'HeatingThresholdTemperature', + displayName: 'Heating Threshold Temperature', + eventOnlyCharacteristic: false, + props: { + format: 'float', + maxValue: 25, + minStep: 0.1, + minValue: 0, + perms: ['ev', 'pr', 'pw'], + unit: 'celsius' + }, + value: 0 + }, + { + UUID: '00000036-0000-1000-8000-0026BB765291', + constructorName: 'TemperatureDisplayUnits', + displayName: 'Temperature Display Units', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr', 'pw'], + validValues: [0, 1] + }, + value: 0 + } + ], + primaryService: false + }, + HumidifierDehumidifier: { + UUID: '000000BD-0000-1000-8000-0026BB765291', + characteristics: [ + { + UUID: '000000B0-0000-1000-8000-0026BB765291', + constructorName: 'Active', + displayName: 'Active', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr', 'pw'], + validValues: [0, 1] + }, + value: 0 + }, + { + UUID: '000000B3-0000-1000-8000-0026BB765291', + constructorName: 'CurrentHumidifierDehumidifierState', + displayName: 'Current Humidifier-Dehumidifier State', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 3, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'], + validValues: [0, 1, 2, 3] + }, + value: 0 + }, + { + UUID: '000000B4-0000-1000-8000-0026BB765291', + constructorName: 'TargetHumidifierDehumidifierState', + displayName: 'Target Humidifier-Dehumidifier State', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 2, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr', 'pw'], + validValues: [0, 1, 2] + }, + value: 0 + }, + { + UUID: '00000010-0000-1000-8000-0026BB765291', + constructorName: 'CurrentRelativeHumidity', + displayName: 'Current Relative Humidity', + eventOnlyCharacteristic: false, + props: { + format: 'float', + maxValue: 100, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'], + unit: 'percentage' + }, + value: 0 + } + ], + constructorName: 'HumidifierDehumidifier', + displayName: 'HumidifierDehumidifier', + hiddenService: false, + optionalCharacteristics: [ + { + UUID: '000000A7-0000-1000-8000-0026BB765291', + constructorName: 'LockPhysicalControls', + displayName: 'Lock Physical Controls', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr', 'pw'], + validValues: [0, 1] + }, + value: 0 + }, + { + UUID: '00000023-0000-1000-8000-0026BB765291', + constructorName: 'Name', + displayName: 'Name', + eventOnlyCharacteristic: false, + props: { + format: 'string', + maxLen: 64, + perms: ['pr'] + }, + value: '' + }, + { + UUID: '000000C9-0000-1000-8000-0026BB765291', + constructorName: 'RelativeHumidityDehumidifierThreshold', + displayName: 'Relative Humidity Dehumidifier Threshold', + eventOnlyCharacteristic: false, + props: { + format: 'float', + maxValue: 100, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr', 'pw'], + unit: 'percentage' + }, + value: 0 + }, + { + UUID: '000000CA-0000-1000-8000-0026BB765291', + constructorName: 'RelativeHumidityHumidifierThreshold', + displayName: 'Relative Humidity Humidifier Threshold', + eventOnlyCharacteristic: false, + props: { + format: 'float', + maxValue: 100, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr', 'pw'], + unit: 'percentage' + }, + value: 0 + }, + { + UUID: '00000029-0000-1000-8000-0026BB765291', + constructorName: 'RotationSpeed', + displayName: 'Rotation Speed', + eventOnlyCharacteristic: false, + props: { + format: 'float', + maxValue: 100, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr', 'pw'], + unit: 'percentage' + }, + value: 0 + }, + { + UUID: '000000B6-0000-1000-8000-0026BB765291', + constructorName: 'SwingMode', + displayName: 'Swing Mode', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr', 'pw'], + validValues: [0, 1] + }, + value: 0 + }, + { + UUID: '000000B5-0000-1000-8000-0026BB765291', + constructorName: 'WaterLevel', + displayName: 'Water Level', + eventOnlyCharacteristic: false, + props: { + format: 'float', + maxValue: 100, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'], + unit: 'percentage' + }, + value: 0 + } + ], + primaryService: false + }, + HumiditySensor: { + UUID: '00000082-0000-1000-8000-0026BB765291', + characteristics: [ + { + UUID: '00000010-0000-1000-8000-0026BB765291', + constructorName: 'CurrentRelativeHumidity', + displayName: 'Current Relative Humidity', + eventOnlyCharacteristic: false, + props: { + format: 'float', + maxValue: 100, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'], + unit: 'percentage' + }, + value: 0 + } + ], + constructorName: 'HumiditySensor', + displayName: 'HumiditySensor', + hiddenService: false, + optionalCharacteristics: [ + { + UUID: '00000023-0000-1000-8000-0026BB765291', + constructorName: 'Name', + displayName: 'Name', + eventOnlyCharacteristic: false, + props: { + format: 'string', + maxLen: 64, + perms: ['pr'] + }, + value: '' + }, + { + UUID: '00000075-0000-1000-8000-0026BB765291', + constructorName: 'StatusActive', + displayName: 'Status Active', + eventOnlyCharacteristic: false, + props: { + format: 'bool', + perms: ['ev', 'pr'] + }, + value: false + }, + { + UUID: '00000077-0000-1000-8000-0026BB765291', + constructorName: 'StatusFault', + displayName: 'Status Fault', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'], + validValues: [0, 1] + }, + value: 0 + }, + { + UUID: '00000079-0000-1000-8000-0026BB765291', + constructorName: 'StatusLowBattery', + displayName: 'Status Low Battery', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'], + validValues: [0, 1] + }, + value: 0 + }, + { + UUID: '0000007A-0000-1000-8000-0026BB765291', + constructorName: 'StatusTampered', + displayName: 'Status Tampered', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'], + validValues: [0, 1] + }, + value: 0 + } + ], + primaryService: false + }, + InputSource: { + UUID: '000000D9-0000-1000-8000-0026BB765291', + characteristics: [ + { + UUID: '000000E3-0000-1000-8000-0026BB765291', + constructorName: 'ConfiguredName', + displayName: 'Configured Name', + eventOnlyCharacteristic: false, + props: { + format: 'string', + perms: ['ev', 'pr', 'pw'] + }, + value: '' + }, + { + UUID: '000000DB-0000-1000-8000-0026BB765291', + constructorName: 'InputSourceType', + displayName: 'Input Source Type', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 10, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'], + validValues: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] + }, + value: 0 + }, + { + UUID: '000000D6-0000-1000-8000-0026BB765291', + constructorName: 'IsConfigured', + displayName: 'Is Configured', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr', 'pw'], + validValues: [0, 1] + }, + value: 0 + }, + { + UUID: '00000023-0000-1000-8000-0026BB765291', + constructorName: 'Name', + displayName: 'Name', + eventOnlyCharacteristic: false, + props: { + format: 'string', + maxLen: 64, + perms: ['pr'] + }, + value: 'Unnamed Service' + }, + { + UUID: '00000135-0000-1000-8000-0026BB765291', + constructorName: 'CurrentVisibilityState', + displayName: 'Current Visibility State', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'], + validValues: [0, 1] + }, + value: 0 + } + ], + constructorName: 'InputSource', + displayName: 'InputSource', + hiddenService: false, + optionalCharacteristics: [ + { + UUID: '000000E6-0000-1000-8000-0026BB765291', + constructorName: 'Identifier', + displayName: 'Identifier', + eventOnlyCharacteristic: false, + props: { + format: 'uint32', + perms: ['pr'] + }, + value: 0 + }, + { + UUID: '000000DC-0000-1000-8000-0026BB765291', + constructorName: 'InputDeviceType', + displayName: 'Input Device Type', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 6, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'], + validValues: [0, 1, 2, 3, 4, 5, 6] + }, + value: 0 + }, + { + UUID: '00000134-0000-1000-8000-0026BB765291', + constructorName: 'TargetVisibilityState', + displayName: 'Target Visibility State', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr', 'pw'], + validValues: [0, 1] + }, + value: 0 + } + ], + primaryService: false + }, + IrrigationSystem: { + UUID: '000000CF-0000-1000-8000-0026BB765291', + characteristics: [ + { + UUID: '000000B0-0000-1000-8000-0026BB765291', + constructorName: 'Active', + displayName: 'Active', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr', 'pw'], + validValues: [0, 1] + }, + value: 0 + }, + { + UUID: '000000D1-0000-1000-8000-0026BB765291', + constructorName: 'ProgramMode', + displayName: 'Program Mode', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 2, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'], + validValues: [0, 1, 2] + }, + value: 0 + }, + { + UUID: '000000D2-0000-1000-8000-0026BB765291', + constructorName: 'InUse', + displayName: 'In Use', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'], + validValues: [0, 1] + }, + value: 0 + } + ], + constructorName: 'IrrigationSystem', + displayName: 'IrrigationSystem', + hiddenService: false, + optionalCharacteristics: [ + { + UUID: '000000D4-0000-1000-8000-0026BB765291', + constructorName: 'RemainingDuration', + displayName: 'Remaining Duration', + eventOnlyCharacteristic: false, + props: { + format: 'uint32', + maxValue: 3600, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'], + unit: 'seconds' + }, + value: 0 + }, + { + UUID: '00000023-0000-1000-8000-0026BB765291', + constructorName: 'Name', + displayName: 'Name', + eventOnlyCharacteristic: false, + props: { + format: 'string', + maxLen: 64, + perms: ['pr'] + }, + value: '' + }, + { + UUID: '00000077-0000-1000-8000-0026BB765291', + constructorName: 'StatusFault', + displayName: 'Status Fault', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'], + validValues: [0, 1] + }, + value: 0 + } + ], + primaryService: false + }, + LeakSensor: { + UUID: '00000083-0000-1000-8000-0026BB765291', + characteristics: [ + { + UUID: '00000070-0000-1000-8000-0026BB765291', + constructorName: 'LeakDetected', + displayName: 'Leak Detected', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'], + validValues: [0, 1] + }, + value: 0 + } + ], + constructorName: 'LeakSensor', + displayName: 'LeakSensor', + hiddenService: false, + optionalCharacteristics: [ + { + UUID: '00000023-0000-1000-8000-0026BB765291', + constructorName: 'Name', + displayName: 'Name', + eventOnlyCharacteristic: false, + props: { + format: 'string', + maxLen: 64, + perms: ['pr'] + }, + value: '' + }, + { + UUID: '00000075-0000-1000-8000-0026BB765291', + constructorName: 'StatusActive', + displayName: 'Status Active', + eventOnlyCharacteristic: false, + props: { + format: 'bool', + perms: ['ev', 'pr'] + }, + value: false + }, + { + UUID: '00000077-0000-1000-8000-0026BB765291', + constructorName: 'StatusFault', + displayName: 'Status Fault', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'], + validValues: [0, 1] + }, + value: 0 + }, + { + UUID: '00000079-0000-1000-8000-0026BB765291', + constructorName: 'StatusLowBattery', + displayName: 'Status Low Battery', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'], + validValues: [0, 1] + }, + value: 0 + }, + { + UUID: '0000007A-0000-1000-8000-0026BB765291', + constructorName: 'StatusTampered', + displayName: 'Status Tampered', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'], + validValues: [0, 1] + }, + value: 0 + } + ], + primaryService: false + }, + LightSensor: { + UUID: '00000084-0000-1000-8000-0026BB765291', + characteristics: [ + { + UUID: '0000006B-0000-1000-8000-0026BB765291', + constructorName: 'CurrentAmbientLightLevel', + displayName: 'Current Ambient Light Level', + eventOnlyCharacteristic: false, + props: { + format: 'float', + maxValue: 100000, + minValue: 0.0001, + perms: ['ev', 'pr'], + unit: 'lux' + }, + value: 0.0001 + } + ], + constructorName: 'LightSensor', + displayName: 'LightSensor', + hiddenService: false, + optionalCharacteristics: [ + { + UUID: '00000023-0000-1000-8000-0026BB765291', + constructorName: 'Name', + displayName: 'Name', + eventOnlyCharacteristic: false, + props: { + format: 'string', + maxLen: 64, + perms: ['pr'] + }, + value: '' + }, + { + UUID: '00000075-0000-1000-8000-0026BB765291', + constructorName: 'StatusActive', + displayName: 'Status Active', + eventOnlyCharacteristic: false, + props: { + format: 'bool', + perms: ['ev', 'pr'] + }, + value: false + }, + { + UUID: '00000077-0000-1000-8000-0026BB765291', + constructorName: 'StatusFault', + displayName: 'Status Fault', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'], + validValues: [0, 1] + }, + value: 0 + }, + { + UUID: '00000079-0000-1000-8000-0026BB765291', + constructorName: 'StatusLowBattery', + displayName: 'Status Low Battery', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'], + validValues: [0, 1] + }, + value: 0 + }, + { + UUID: '0000007A-0000-1000-8000-0026BB765291', + constructorName: 'StatusTampered', + displayName: 'Status Tampered', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'], + validValues: [0, 1] + }, + value: 0 + } + ], + primaryService: false + }, + Lightbulb: { + UUID: '00000043-0000-1000-8000-0026BB765291', + characteristics: [ + { + UUID: '00000025-0000-1000-8000-0026BB765291', + constructorName: 'On', + displayName: 'On', + eventOnlyCharacteristic: false, + props: { + format: 'bool', + perms: ['ev', 'pr', 'pw'] + }, + value: false + } + ], + constructorName: 'Lightbulb', + displayName: 'Lightbulb', + hiddenService: false, + optionalCharacteristics: [ + { + UUID: '00000008-0000-1000-8000-0026BB765291', + constructorName: 'Brightness', + displayName: 'Brightness', + eventOnlyCharacteristic: false, + props: { + format: 'int', + maxValue: 100, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr', 'pw'], + unit: 'percentage' + }, + value: 0 + }, + { + UUID: '0000024B-0000-1000-8000-0026BB765291', + constructorName: 'CharacteristicValueActiveTransitionCount', + displayName: 'Characteristic Value Active Transition Count', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + perms: ['ev', 'pr'] + }, + value: 0 + }, + { + UUID: '00000143-0000-1000-8000-0026BB765291', + constructorName: 'CharacteristicValueTransitionControl', + displayName: 'Characteristic Value Transition Control', + eventOnlyCharacteristic: false, + props: { + format: 'tlv8', + perms: ['pr', 'pw', 'wr'] + }, + value: '' + }, + { + UUID: '000000CE-0000-1000-8000-0026BB765291', + constructorName: 'ColorTemperature', + displayName: 'Color Temperature', + eventOnlyCharacteristic: false, + props: { + format: 'int', + maxValue: 500, + minStep: 1, + minValue: 140, + perms: ['ev', 'pr', 'pw'] + }, + value: 140 + }, + { + UUID: '00000013-0000-1000-8000-0026BB765291', + constructorName: 'Hue', + displayName: 'Hue', + eventOnlyCharacteristic: false, + props: { + format: 'float', + maxValue: 360, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr', 'pw'], + unit: 'arcdegrees' + }, + value: 0 + }, + { + UUID: '00000023-0000-1000-8000-0026BB765291', + constructorName: 'Name', + displayName: 'Name', + eventOnlyCharacteristic: false, + props: { + format: 'string', + maxLen: 64, + perms: ['pr'] + }, + value: '' + }, + { + UUID: '0000002F-0000-1000-8000-0026BB765291', + constructorName: 'Saturation', + displayName: 'Saturation', + eventOnlyCharacteristic: false, + props: { + format: 'float', + maxValue: 100, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr', 'pw'], + unit: 'percentage' + }, + value: 0 + }, + { + UUID: '00000144-0000-1000-8000-0026BB765291', + constructorName: 'SupportedCharacteristicValueTransitionConfiguration', + displayName: 'Supported Characteristic Value Transition Configuration', + eventOnlyCharacteristic: false, + props: { + format: 'tlv8', + perms: ['pr'] + }, + value: '' + } + ], + primaryService: false + }, + LockManagement: { + UUID: '00000044-0000-1000-8000-0026BB765291', + characteristics: [ + { + UUID: '00000019-0000-1000-8000-0026BB765291', + constructorName: 'LockControlPoint', + displayName: 'Lock Control Point', + eventOnlyCharacteristic: false, + props: { + format: 'tlv8', + perms: ['pw'] + }, + value: '' + }, + { + UUID: '00000037-0000-1000-8000-0026BB765291', + constructorName: 'Version', + displayName: 'Version', + eventOnlyCharacteristic: false, + props: { + format: 'string', + maxLen: 64, + perms: ['pr'] + }, + value: '' + } + ], + constructorName: 'LockManagement', + displayName: 'LockManagement', + hiddenService: false, + optionalCharacteristics: [ + { + UUID: '00000001-0000-1000-8000-0026BB765291', + constructorName: 'AdministratorOnlyAccess', + displayName: 'Administrator Only Access', + eventOnlyCharacteristic: false, + props: { + format: 'bool', + perms: ['ev', 'pr', 'pw'] + }, + value: false + }, + { + UUID: '00000005-0000-1000-8000-0026BB765291', + constructorName: 'AudioFeedback', + displayName: 'Audio Feedback', + eventOnlyCharacteristic: false, + props: { + format: 'bool', + perms: ['ev', 'pr', 'pw'] + }, + value: false + }, + { + UUID: '0000000E-0000-1000-8000-0026BB765291', + constructorName: 'CurrentDoorState', + displayName: 'Current Door State', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 4, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'], + validValues: [0, 1, 2, 3, 4] + }, + value: 0 + }, + { + UUID: '0000001A-0000-1000-8000-0026BB765291', + constructorName: 'LockManagementAutoSecurityTimeout', + displayName: 'Lock Management Auto Security Timeout', + eventOnlyCharacteristic: false, + props: { + format: 'uint32', + perms: ['ev', 'pr', 'pw'], + unit: 'seconds' + }, + value: 0 + }, + { + UUID: '0000001C-0000-1000-8000-0026BB765291', + constructorName: 'LockLastKnownAction', + displayName: 'Lock Last Known Action', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 10, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'], + validValues: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] + }, + value: 0 + }, + { + UUID: '0000001F-0000-1000-8000-0026BB765291', + constructorName: 'Logs', + displayName: 'Logs', + eventOnlyCharacteristic: false, + props: { + format: 'tlv8', + perms: ['ev', 'pr'] + }, + value: '' + }, + { + UUID: '00000022-0000-1000-8000-0026BB765291', + constructorName: 'MotionDetected', + displayName: 'Motion Detected', + eventOnlyCharacteristic: false, + props: { + format: 'bool', + perms: ['ev', 'pr'] + }, + value: false + } + ], + primaryService: false + }, + LockMechanism: { + UUID: '00000045-0000-1000-8000-0026BB765291', + characteristics: [ + { + UUID: '0000001D-0000-1000-8000-0026BB765291', + constructorName: 'LockCurrentState', + displayName: 'Lock Current State', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 3, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'], + validValues: [0, 1, 2, 3] + }, + value: 0 + }, + { + UUID: '0000001E-0000-1000-8000-0026BB765291', + constructorName: 'LockTargetState', + displayName: 'Lock Target State', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr', 'pw'], + validValues: [0, 1] + }, + value: 0 + } + ], + constructorName: 'LockMechanism', + displayName: 'LockMechanism', + hiddenService: false, + optionalCharacteristics: [ + { + UUID: '00000023-0000-1000-8000-0026BB765291', + constructorName: 'Name', + displayName: 'Name', + eventOnlyCharacteristic: false, + props: { + format: 'string', + maxLen: 64, + perms: ['pr'] + }, + value: '' + } + ], + primaryService: false + }, + Microphone: { + UUID: '00000112-0000-1000-8000-0026BB765291', + characteristics: [ + { + UUID: '0000011A-0000-1000-8000-0026BB765291', + constructorName: 'Mute', + displayName: 'Mute', + eventOnlyCharacteristic: false, + props: { + format: 'bool', + perms: ['ev', 'pr', 'pw'] + }, + value: false + } + ], + constructorName: 'Microphone', + displayName: 'Microphone', + hiddenService: false, + optionalCharacteristics: [ + { + UUID: '00000119-0000-1000-8000-0026BB765291', + constructorName: 'Volume', + displayName: 'Volume', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 100, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr', 'pw'], + unit: 'percentage' + }, + value: 0 + } + ], + primaryService: false + }, + MotionSensor: { + UUID: '00000085-0000-1000-8000-0026BB765291', + characteristics: [ + { + UUID: '00000022-0000-1000-8000-0026BB765291', + constructorName: 'MotionDetected', + displayName: 'Motion Detected', + eventOnlyCharacteristic: false, + props: { + format: 'bool', + perms: ['ev', 'pr'] + }, + value: false + } + ], + constructorName: 'MotionSensor', + displayName: 'MotionSensor', + hiddenService: false, + optionalCharacteristics: [ + { + UUID: '00000023-0000-1000-8000-0026BB765291', + constructorName: 'Name', + displayName: 'Name', + eventOnlyCharacteristic: false, + props: { + format: 'string', + maxLen: 64, + perms: ['pr'] + }, + value: '' + }, + { + UUID: '00000075-0000-1000-8000-0026BB765291', + constructorName: 'StatusActive', + displayName: 'Status Active', + eventOnlyCharacteristic: false, + props: { + format: 'bool', + perms: ['ev', 'pr'] + }, + value: false + }, + { + UUID: '00000077-0000-1000-8000-0026BB765291', + constructorName: 'StatusFault', + displayName: 'Status Fault', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'], + validValues: [0, 1] + }, + value: 0 + }, + { + UUID: '00000079-0000-1000-8000-0026BB765291', + constructorName: 'StatusLowBattery', + displayName: 'Status Low Battery', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'], + validValues: [0, 1] + }, + value: 0 + }, + { + UUID: '0000007A-0000-1000-8000-0026BB765291', + constructorName: 'StatusTampered', + displayName: 'Status Tampered', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'], + validValues: [0, 1] + }, + value: 0 + } + ], + primaryService: false + }, + NFCAccess: { + UUID: '00000266-0000-1000-8000-0026BB765291', + characteristics: [ + { + UUID: '00000263-0000-1000-8000-0026BB765291', + constructorName: 'ConfigurationState', + displayName: 'Configuration State', + eventOnlyCharacteristic: false, + props: { + format: 'uint16', + perms: ['ev', 'pr'] + }, + value: 0 + }, + { + UUID: '00000264-0000-1000-8000-0026BB765291', + constructorName: 'NFCAccessControlPoint', + displayName: 'NFC Access Control Point', + eventOnlyCharacteristic: false, + props: { + format: 'tlv8', + perms: ['pr', 'pw', 'wr'] + }, + value: '' + }, + { + UUID: '00000265-0000-1000-8000-0026BB765291', + constructorName: 'NFCAccessSupportedConfiguration', + displayName: 'NFC Access Supported Configuration', + eventOnlyCharacteristic: false, + props: { + format: 'tlv8', + perms: ['pr'] + }, + value: '' + } + ], + constructorName: 'NFCAccess', + displayName: 'NFCAccess', + hiddenService: false, + optionalCharacteristics: [], + primaryService: false + }, + OccupancySensor: { + UUID: '00000086-0000-1000-8000-0026BB765291', + characteristics: [ + { + UUID: '00000071-0000-1000-8000-0026BB765291', + constructorName: 'OccupancyDetected', + displayName: 'Occupancy Detected', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'], + validValues: [0, 1] + }, + value: 0 + } + ], + constructorName: 'OccupancySensor', + displayName: 'OccupancySensor', + hiddenService: false, + optionalCharacteristics: [ + { + UUID: '00000023-0000-1000-8000-0026BB765291', + constructorName: 'Name', + displayName: 'Name', + eventOnlyCharacteristic: false, + props: { + format: 'string', + maxLen: 64, + perms: ['pr'] + }, + value: '' + }, + { + UUID: '00000075-0000-1000-8000-0026BB765291', + constructorName: 'StatusActive', + displayName: 'Status Active', + eventOnlyCharacteristic: false, + props: { + format: 'bool', + perms: ['ev', 'pr'] + }, + value: false + }, + { + UUID: '00000077-0000-1000-8000-0026BB765291', + constructorName: 'StatusFault', + displayName: 'Status Fault', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'], + validValues: [0, 1] + }, + value: 0 + }, + { + UUID: '00000079-0000-1000-8000-0026BB765291', + constructorName: 'StatusLowBattery', + displayName: 'Status Low Battery', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'], + validValues: [0, 1] + }, + value: 0 + }, + { + UUID: '0000007A-0000-1000-8000-0026BB765291', + constructorName: 'StatusTampered', + displayName: 'Status Tampered', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'], + validValues: [0, 1] + }, + value: 0 + } + ], + primaryService: false + }, + Outlet: { + UUID: '00000047-0000-1000-8000-0026BB765291', + characteristics: [ + { + UUID: '00000025-0000-1000-8000-0026BB765291', + constructorName: 'On', + displayName: 'On', + eventOnlyCharacteristic: false, + props: { + format: 'bool', + perms: ['ev', 'pr', 'pw'] + }, + value: false + } + ], + constructorName: 'Outlet', + displayName: 'Outlet', + hiddenService: false, + optionalCharacteristics: [ + { + UUID: '00000023-0000-1000-8000-0026BB765291', + constructorName: 'Name', + displayName: 'Name', + eventOnlyCharacteristic: false, + props: { + format: 'string', + maxLen: 64, + perms: ['pr'] + }, + value: '' + }, + { + UUID: '00000026-0000-1000-8000-0026BB765291', + constructorName: 'OutletInUse', + displayName: 'Outlet In Use', + eventOnlyCharacteristic: false, + props: { + format: 'bool', + perms: ['ev', 'pr'] + }, + value: false + } + ], + primaryService: false + }, + Pairing: { + UUID: '00000055-0000-1000-8000-0026BB765291', + characteristics: [ + { + UUID: '00000050-0000-1000-8000-0026BB765291', + constructorName: 'ListPairings', + displayName: 'List Pairings', + eventOnlyCharacteristic: false, + props: { + format: 'tlv8', + perms: ['pr', 'pw'] + }, + value: '' + }, + { + UUID: '0000004C-0000-1000-8000-0026BB765291', + constructorName: 'PairSetup', + displayName: 'Pair Setup', + eventOnlyCharacteristic: false, + props: { + format: 'tlv8', + perms: ['pr', 'pw'] + }, + value: '' + }, + { + UUID: '0000004E-0000-1000-8000-0026BB765291', + constructorName: 'PairVerify', + displayName: 'Pair Verify', + eventOnlyCharacteristic: false, + props: { + format: 'tlv8', + perms: ['pr', 'pw'] + }, + value: '' + }, + { + UUID: '0000004F-0000-1000-8000-0026BB765291', + constructorName: 'PairingFeatures', + displayName: 'Pairing Features', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + perms: ['pr'] + }, + value: 0 + } + ], + constructorName: 'Pairing', + displayName: 'Pairing', + hiddenService: false, + optionalCharacteristics: [], + primaryService: false + }, + PowerManagement: { + UUID: '00000221-0000-1000-8000-0026BB765291', + characteristics: [ + { + UUID: '00000222-0000-1000-8000-0026BB765291', + constructorName: 'WakeConfiguration', + displayName: 'Wake Configuration', + eventOnlyCharacteristic: false, + props: { + format: 'tlv8', + perms: ['pr'] + }, + value: '' + } + ], + constructorName: 'PowerManagement', + displayName: 'PowerManagement', + hiddenService: false, + optionalCharacteristics: [ + { + UUID: '00000252-0000-1000-8000-0026BB765291', + constructorName: 'SelectedSleepConfiguration', + displayName: 'Selected Sleep Configuration', + eventOnlyCharacteristic: false, + props: { + format: 'tlv8', + perms: ['ev', 'pr', 'pw', 'wr'] + }, + value: '' + }, + { + UUID: '00000251-0000-1000-8000-0026BB765291', + constructorName: 'SupportedSleepConfiguration', + displayName: 'Supported Sleep Configuration', + eventOnlyCharacteristic: false, + props: { + format: 'tlv8', + perms: ['pr'] + }, + value: '' + } + ], + primaryService: false + }, + ProtocolInformation: { + UUID: '000000A2-0000-1000-8000-0026BB765291', + characteristics: [ + { + UUID: '00000037-0000-1000-8000-0026BB765291', + constructorName: 'Version', + displayName: 'Version', + eventOnlyCharacteristic: false, + props: { + format: 'string', + maxLen: 64, + perms: ['pr'] + }, + value: '' + } + ], + constructorName: 'ProtocolInformation', + displayName: 'ProtocolInformation', + hiddenService: false, + optionalCharacteristics: [], + primaryService: false + }, + Relay: { + nrchkbDisabledText: 'Relay (deprecated, replaced by CloudRelay)' + }, + SecuritySystem: { + UUID: '0000007E-0000-1000-8000-0026BB765291', + characteristics: [ + { + UUID: '00000066-0000-1000-8000-0026BB765291', + constructorName: 'SecuritySystemCurrentState', + displayName: 'Security System Current State', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 4, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'], + validValues: [0, 1, 2, 3, 4] + }, + value: 0 + }, + { + UUID: '00000067-0000-1000-8000-0026BB765291', + constructorName: 'SecuritySystemTargetState', + displayName: 'Security System Target State', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 3, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr', 'pw'], + validValues: [0, 1, 2, 3] + }, + value: 0 + } + ], + constructorName: 'SecuritySystem', + displayName: 'SecuritySystem', + hiddenService: false, + optionalCharacteristics: [ + { + UUID: '00000023-0000-1000-8000-0026BB765291', + constructorName: 'Name', + displayName: 'Name', + eventOnlyCharacteristic: false, + props: { + format: 'string', + maxLen: 64, + perms: ['pr'] + }, + value: '' + }, + { + UUID: '0000008E-0000-1000-8000-0026BB765291', + constructorName: 'SecuritySystemAlarmType', + displayName: 'Security System Alarm Type', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + validValues: [0, 1], + perms: ['ev', 'pr'] + }, + value: 0 + }, + { + UUID: '00000077-0000-1000-8000-0026BB765291', + constructorName: 'StatusFault', + displayName: 'Status Fault', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'], + validValues: [0, 1] + }, + value: 0 + }, + { + UUID: '0000007A-0000-1000-8000-0026BB765291', + constructorName: 'StatusTampered', + displayName: 'Status Tampered', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'], + validValues: [0, 1] + }, + value: 0 + } + ], + primaryService: false + }, + ServiceLabel: { + UUID: '000000CC-0000-1000-8000-0026BB765291', + characteristics: [ + { + UUID: '000000CD-0000-1000-8000-0026BB765291', + constructorName: 'ServiceLabelNamespace', + displayName: 'Service Label Namespace', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['pr'], + validValues: [0, 1] + }, + value: 0 + } + ], + constructorName: 'ServiceLabel', + displayName: 'ServiceLabel', + hiddenService: false, + optionalCharacteristics: [], + primaryService: false + }, + Siri: { + UUID: '00000133-0000-1000-8000-0026BB765291', + characteristics: [ + { + UUID: '00000132-0000-1000-8000-0026BB765291', + constructorName: 'SiriInputType', + displayName: 'Siri Input Type', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 0, + minValue: 0, + perms: ['pr'], + validValues: [0] + }, + value: 0 + } + ], + constructorName: 'Siri', + displayName: 'Siri', + hiddenService: false, + optionalCharacteristics: [ + { + UUID: '0000026B-0000-1000-8000-0026BB765291', + constructorName: 'MultifunctionButton', + displayName: 'Multifunction Button', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minValue: 0, + perms: ['ev', 'pr'] + }, + value: 0 + }, + { + UUID: '00000255-0000-1000-8000-0026BB765291', + constructorName: 'SiriEnable', + displayName: 'Siri Enable', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minValue: 0, + perms: ['ev', 'pr', 'pw'] + }, + value: 0 + }, + { + UUID: '0000025A-0000-1000-8000-0026BB765291', + constructorName: 'SiriEngineVersion', + displayName: 'Siri Engine Version', + eventOnlyCharacteristic: false, + props: { + format: 'string', + perms: ['pr'] + }, + value: '' + }, + { + UUID: '00000258-0000-1000-8000-0026BB765291', + constructorName: 'SiriLightOnUse', + displayName: 'Siri Light On Use', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minValue: 0, + perms: ['ev', 'pr', 'pw'] + }, + value: 0 + }, + { + UUID: '00000256-0000-1000-8000-0026BB765291', + constructorName: 'SiriListening', + displayName: 'Siri Listening', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minValue: 0, + perms: ['ev', 'pr', 'pw'] + }, + value: 0 + }, + { + UUID: '00000257-0000-1000-8000-0026BB765291', + constructorName: 'SiriTouchToUse', + displayName: 'Siri Touch To Use', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minValue: 0, + perms: ['ev', 'pr', 'pw'] + }, + value: 0 + } + ], + primaryService: false + }, + SiriEndpoint: { + UUID: '00000253-0000-1000-8000-0026BB765291', + characteristics: [ + { + UUID: '00000254-0000-1000-8000-0026BB765291', + constructorName: 'SiriEndpointSessionStatus', + displayName: 'Siri Endpoint Session Status', + eventOnlyCharacteristic: false, + props: { + format: 'tlv8', + perms: ['ev', 'pr'] + }, + value: '' + }, + { + UUID: '00000037-0000-1000-8000-0026BB765291', + constructorName: 'Version', + displayName: 'Version', + eventOnlyCharacteristic: false, + props: { + format: 'string', + maxLen: 64, + perms: ['pr'] + }, + value: '' + } + ], + constructorName: 'SiriEndpoint', + displayName: 'SiriEndpoint', + hiddenService: false, + optionalCharacteristics: [ + { + UUID: '000000E7-0000-1000-8000-0026BB765291', + constructorName: 'ActiveIdentifier', + displayName: 'Active Identifier', + eventOnlyCharacteristic: false, + props: { + format: 'uint32', + perms: ['ev', 'pr', 'pw'] + }, + value: 0 + }, + { + UUID: '00000227-0000-1000-8000-0026BB765291', + constructorName: 'ManuallyDisabled', + displayName: 'Manually Disabled', + eventOnlyCharacteristic: false, + props: { + format: 'bool', + perms: ['ev', 'pr'] + }, + value: false + } + ], + primaryService: false + }, + Slat: { + nrchkbDisabledText: 'Slat (deprecated, replaced by Slats)' + }, + Slats: { + UUID: '000000B9-0000-1000-8000-0026BB765291', + characteristics: [ + { + UUID: '000000AA-0000-1000-8000-0026BB765291', + constructorName: 'CurrentSlatState', + displayName: 'Current Slat State', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 2, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'], + validValues: [0, 1, 2] + }, + value: 0 + }, + { + UUID: '000000C0-0000-1000-8000-0026BB765291', + constructorName: 'SlatType', + displayName: 'Slat Type', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['pr'], + validValues: [0, 1] + }, + value: 0 + } + ], + constructorName: 'Slats', + displayName: 'Slats', + hiddenService: false, + optionalCharacteristics: [ + { + UUID: '00000023-0000-1000-8000-0026BB765291', + constructorName: 'Name', + displayName: 'Name', + eventOnlyCharacteristic: false, + props: { + format: 'string', + maxLen: 64, + perms: ['pr'] + }, + value: '' + }, + { + UUID: '000000B6-0000-1000-8000-0026BB765291', + constructorName: 'SwingMode', + displayName: 'Swing Mode', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr', 'pw'], + validValues: [0, 1] + }, + value: 0 + }, + { + UUID: '000000C1-0000-1000-8000-0026BB765291', + constructorName: 'CurrentTiltAngle', + displayName: 'Current Tilt Angle', + eventOnlyCharacteristic: false, + props: { + format: 'int', + maxValue: 90, + minStep: 1, + minValue: -90, + perms: ['ev', 'pr'], + unit: 'arcdegrees' + }, + value: -90 + }, + { + UUID: '000000C2-0000-1000-8000-0026BB765291', + constructorName: 'TargetTiltAngle', + displayName: 'Target Tilt Angle', + eventOnlyCharacteristic: false, + props: { + format: 'int', + maxValue: 90, + minStep: 1, + minValue: -90, + perms: ['ev', 'pr', 'pw'], + unit: 'arcdegrees' + }, + value: -90 + } + ], + primaryService: false + }, + SmartSpeaker: { + UUID: '00000228-0000-1000-8000-0026BB765291', + characteristics: [ + { + UUID: '000000E0-0000-1000-8000-0026BB765291', + constructorName: 'CurrentMediaState', + displayName: 'Current Media State', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 5, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'], + validValues: [0, 1, 2, 4, 5] + }, + value: 0 + }, + { + UUID: '00000137-0000-1000-8000-0026BB765291', + constructorName: 'TargetMediaState', + displayName: 'Target Media State', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 2, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr', 'pw'], + validValues: [0, 1, 2] + }, + value: 0 + } + ], + constructorName: 'SmartSpeaker', + displayName: 'SmartSpeaker', + hiddenService: false, + optionalCharacteristics: [ + { + UUID: '0000025B-0000-1000-8000-0026BB765291', + constructorName: 'AirPlayEnable', + displayName: 'AirPlay Enable', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minValue: 0, + perms: ['ev', 'pr', 'pw'] + }, + value: 0 + }, + { + UUID: '000000E3-0000-1000-8000-0026BB765291', + constructorName: 'ConfiguredName', + displayName: 'Configured Name', + eventOnlyCharacteristic: false, + props: { + format: 'string', + perms: ['ev', 'pr', 'pw'] + }, + value: '' + }, + { + UUID: '0000011A-0000-1000-8000-0026BB765291', + constructorName: 'Mute', + displayName: 'Mute', + eventOnlyCharacteristic: false, + props: { + format: 'bool', + perms: ['ev', 'pr', 'pw'] + }, + value: false + }, + { + UUID: '00000023-0000-1000-8000-0026BB765291', + constructorName: 'Name', + displayName: 'Name', + eventOnlyCharacteristic: false, + props: { + format: 'string', + maxLen: 64, + perms: ['pr'] + }, + value: '' + }, + { + UUID: '00000119-0000-1000-8000-0026BB765291', + constructorName: 'Volume', + displayName: 'Volume', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 100, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr', 'pw'], + unit: 'percentage' + }, + value: 0 + } + ], + primaryService: false + }, + SmokeSensor: { + UUID: '00000087-0000-1000-8000-0026BB765291', + characteristics: [ + { + UUID: '00000076-0000-1000-8000-0026BB765291', + constructorName: 'SmokeDetected', + displayName: 'Smoke Detected', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'], + validValues: [0, 1] + }, + value: 0 + } + ], + constructorName: 'SmokeSensor', + displayName: 'SmokeSensor', + hiddenService: false, + optionalCharacteristics: [ + { + UUID: '00000023-0000-1000-8000-0026BB765291', + constructorName: 'Name', + displayName: 'Name', + eventOnlyCharacteristic: false, + props: { + format: 'string', + maxLen: 64, + perms: ['pr'] + }, + value: '' + }, + { + UUID: '00000075-0000-1000-8000-0026BB765291', + constructorName: 'StatusActive', + displayName: 'Status Active', + eventOnlyCharacteristic: false, + props: { + format: 'bool', + perms: ['ev', 'pr'] + }, + value: false + }, + { + UUID: '00000077-0000-1000-8000-0026BB765291', + constructorName: 'StatusFault', + displayName: 'Status Fault', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'], + validValues: [0, 1] + }, + value: 0 + }, + { + UUID: '00000079-0000-1000-8000-0026BB765291', + constructorName: 'StatusLowBattery', + displayName: 'Status Low Battery', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'], + validValues: [0, 1] + }, + value: 0 + }, + { + UUID: '0000007A-0000-1000-8000-0026BB765291', + constructorName: 'StatusTampered', + displayName: 'Status Tampered', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'], + validValues: [0, 1] + }, + value: 0 + } + ], + primaryService: false + }, + Speaker: { + UUID: '00000113-0000-1000-8000-0026BB765291', + characteristics: [ + { + UUID: '0000011A-0000-1000-8000-0026BB765291', + constructorName: 'Mute', + displayName: 'Mute', + eventOnlyCharacteristic: false, + props: { + format: 'bool', + perms: ['ev', 'pr', 'pw'] + }, + value: false + } + ], + constructorName: 'Speaker', + displayName: 'Speaker', + hiddenService: false, + optionalCharacteristics: [ + { + UUID: '000000B0-0000-1000-8000-0026BB765291', + constructorName: 'Active', + displayName: 'Active', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr', 'pw'], + validValues: [0, 1] + }, + value: 0 + }, + { + UUID: '00000119-0000-1000-8000-0026BB765291', + constructorName: 'Volume', + displayName: 'Volume', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 100, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr', 'pw'], + unit: 'percentage' + }, + value: 0 + } + ], + primaryService: false + }, + StatefulProgrammableSwitch: { + UUID: '00000088-0000-1000-8000-0026BB765291', + characteristics: [ + { + UUID: '00000073-0000-1000-8000-0026BB765291', + constructorName: 'ProgrammableSwitchEvent', + displayName: 'Programmable Switch Event', + eventOnlyCharacteristic: true, + props: { + format: 'uint8', + maxValue: 2, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'], + validValues: [0, 1, 2] + }, + value: 0 + }, + { + UUID: '00000074-0000-1000-8000-0026BB765291', + constructorName: 'ProgrammableSwitchOutputState', + displayName: 'Programmable Switch Output State', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr', 'pw'] + }, + value: 0 + } + ], + constructorName: 'StatefulProgrammableSwitch', + displayName: 'StatefulProgrammableSwitch', + hiddenService: false, + optionalCharacteristics: [ + { + UUID: '00000023-0000-1000-8000-0026BB765291', + constructorName: 'Name', + displayName: 'Name', + eventOnlyCharacteristic: false, + props: { + format: 'string', + maxLen: 64, + perms: ['pr'] + }, + value: '' + } + ], + primaryService: false + }, + StatelessProgrammableSwitch: { + UUID: '00000089-0000-1000-8000-0026BB765291', + characteristics: [ + { + UUID: '00000073-0000-1000-8000-0026BB765291', + constructorName: 'ProgrammableSwitchEvent', + displayName: 'Programmable Switch Event', + eventOnlyCharacteristic: true, + props: { + format: 'uint8', + maxValue: 2, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'], + validValues: [0, 1, 2] + }, + value: 0 + } + ], + constructorName: 'StatelessProgrammableSwitch', + displayName: 'StatelessProgrammableSwitch', + hiddenService: false, + optionalCharacteristics: [ + { + UUID: '00000023-0000-1000-8000-0026BB765291', + constructorName: 'Name', + displayName: 'Name', + eventOnlyCharacteristic: false, + props: { + format: 'string', + maxLen: 64, + perms: ['pr'] + }, + value: '' + }, + { + UUID: '000000CB-0000-1000-8000-0026BB765291', + constructorName: 'ServiceLabelIndex', + displayName: 'Service Label Index', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 255, + minStep: 1, + minValue: 1, + perms: ['pr'] + }, + value: 1 + } + ], + primaryService: false + }, + Switch: { + UUID: '00000049-0000-1000-8000-0026BB765291', + characteristics: [ + { + UUID: '00000025-0000-1000-8000-0026BB765291', + constructorName: 'On', + displayName: 'On', + eventOnlyCharacteristic: false, + props: { + format: 'bool', + perms: ['ev', 'pr', 'pw'] + }, + value: false + } + ], + constructorName: 'Switch', + displayName: 'Switch', + hiddenService: false, + optionalCharacteristics: [ + { + UUID: '00000023-0000-1000-8000-0026BB765291', + constructorName: 'Name', + displayName: 'Name', + eventOnlyCharacteristic: false, + props: { + format: 'string', + maxLen: 64, + perms: ['pr'] + }, + value: '' + } + ], + primaryService: false + }, + TapManagement: { + UUID: '0000022E-0000-1000-8000-0026BB765291', + characteristics: [ + { + UUID: '000000B0-0000-1000-8000-0026BB765291', + constructorName: 'Active', + displayName: 'Active', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr', 'pw'], + validValues: [0, 1] + }, + value: 0 + }, + { + UUID: '00000250-0000-1000-8000-0026BB765291', + constructorName: 'CryptoHash', + displayName: 'Crypto Hash', + eventOnlyCharacteristic: false, + props: { + format: 'tlv8', + perms: ['pw', 'wr'] + }, + value: '' + }, + { + UUID: '0000022F-0000-1000-8000-0026BB765291', + constructorName: 'TapType', + displayName: 'Tap Type', + eventOnlyCharacteristic: false, + props: { + format: 'uint16', + perms: ['pr'] + }, + value: 0 + }, + { + UUID: '00000231-0000-1000-8000-0026BB765291', + constructorName: 'Token', + displayName: 'Token', + eventOnlyCharacteristic: false, + props: { + format: 'data', + perms: ['pw'] + }, + value: '' + } + ], + constructorName: 'TapManagement', + displayName: 'TapManagement', + hiddenService: false, + optionalCharacteristics: [], + primaryService: false + }, + TargetControl: { + UUID: '00000125-0000-1000-8000-0026BB765291', + characteristics: [ + { + UUID: '000000B0-0000-1000-8000-0026BB765291', + constructorName: 'Active', + displayName: 'Active', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr', 'pw'], + validValues: [0, 1] + }, + value: 0 + }, + { + UUID: '000000E7-0000-1000-8000-0026BB765291', + constructorName: 'ActiveIdentifier', + displayName: 'Active Identifier', + eventOnlyCharacteristic: false, + props: { + format: 'uint32', + perms: ['ev', 'pr', 'pw'] + }, + value: 0 + }, + { + UUID: '00000126-0000-1000-8000-0026BB765291', + constructorName: 'ButtonEvent', + displayName: 'Button Event', + eventOnlyCharacteristic: false, + props: { + adminOnlyAccess: [2], + format: 'tlv8', + perms: ['ev', 'pr'] + }, + value: '' + } + ], + constructorName: 'TargetControl', + displayName: 'TargetControl', + hiddenService: false, + optionalCharacteristics: [ + { + UUID: '00000023-0000-1000-8000-0026BB765291', + constructorName: 'Name', + displayName: 'Name', + eventOnlyCharacteristic: false, + props: { + format: 'string', + maxLen: 64, + perms: ['pr'] + }, + value: '' + } + ], + primaryService: false + }, + TargetControlManagement: { + UUID: '00000122-0000-1000-8000-0026BB765291', + characteristics: [ + { + UUID: '00000123-0000-1000-8000-0026BB765291', + constructorName: 'TargetControlSupportedConfiguration', + displayName: 'Target Control Supported Configuration', + eventOnlyCharacteristic: false, + props: { + format: 'tlv8', + perms: ['pr'] + }, + value: '' + }, + { + UUID: '00000124-0000-1000-8000-0026BB765291', + constructorName: 'TargetControlList', + displayName: 'Target Control List', + eventOnlyCharacteristic: false, + props: { + adminOnlyAccess: [0, 1], + format: 'tlv8', + perms: ['pr', 'pw', 'wr'] + }, + value: '' + } + ], + constructorName: 'TargetControlManagement', + displayName: 'TargetControlManagement', + hiddenService: false, + optionalCharacteristics: [], + primaryService: false + }, + Television: { + UUID: '000000D8-0000-1000-8000-0026BB765291', + characteristics: [ + { + UUID: '000000B0-0000-1000-8000-0026BB765291', + constructorName: 'Active', + displayName: 'Active', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr', 'pw'], + validValues: [0, 1] + }, + value: 0 + }, + { + UUID: '000000E7-0000-1000-8000-0026BB765291', + constructorName: 'ActiveIdentifier', + displayName: 'Active Identifier', + eventOnlyCharacteristic: false, + props: { + format: 'uint32', + perms: ['ev', 'pr', 'pw'] + }, + value: 0 + }, + { + UUID: '000000E3-0000-1000-8000-0026BB765291', + constructorName: 'ConfiguredName', + displayName: 'Configured Name', + eventOnlyCharacteristic: false, + props: { + format: 'string', + perms: ['ev', 'pr', 'pw'] + }, + value: '' + }, + { + UUID: '000000E1-0000-1000-8000-0026BB765291', + constructorName: 'RemoteKey', + displayName: 'Remote Key', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 16, + minStep: 1, + minValue: 0, + perms: ['pw'], + validValues: [ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 + ] + }, + value: 0 + }, + { + UUID: '000000E8-0000-1000-8000-0026BB765291', + constructorName: 'SleepDiscoveryMode', + displayName: 'Sleep Discovery Mode', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'], + validValues: [0, 1] + }, + value: 0 + } + ], + constructorName: 'Television', + displayName: 'Television', + hiddenService: false, + optionalCharacteristics: [ + { + UUID: '00000008-0000-1000-8000-0026BB765291', + constructorName: 'Brightness', + displayName: 'Brightness', + eventOnlyCharacteristic: false, + props: { + format: 'int', + maxValue: 100, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr', 'pw'], + unit: 'percentage' + }, + value: 0 + }, + { + UUID: '000000DD-0000-1000-8000-0026BB765291', + constructorName: 'ClosedCaptions', + displayName: 'Closed Captions', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr', 'pw'], + validValues: [0, 1] + }, + value: 0 + }, + { + UUID: '00000136-0000-1000-8000-0026BB765291', + constructorName: 'DisplayOrder', + displayName: 'Display Order', + eventOnlyCharacteristic: false, + props: { + format: 'tlv8', + perms: ['ev', 'pr', 'pw'] + }, + value: '' + }, + { + UUID: '000000E0-0000-1000-8000-0026BB765291', + constructorName: 'CurrentMediaState', + displayName: 'Current Media State', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 5, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'], + validValues: [0, 1, 2, 4, 5] + }, + value: 0 + }, + { + UUID: '00000137-0000-1000-8000-0026BB765291', + constructorName: 'TargetMediaState', + displayName: 'Target Media State', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 2, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr', 'pw'], + validValues: [0, 1, 2] + }, + value: 0 + }, + { + UUID: '00000023-0000-1000-8000-0026BB765291', + constructorName: 'Name', + displayName: 'Name', + eventOnlyCharacteristic: false, + props: { + format: 'string', + maxLen: 64, + perms: ['pr'] + }, + value: '' + }, + { + UUID: '000000E2-0000-1000-8000-0026BB765291', + constructorName: 'PictureMode', + displayName: 'Picture Mode', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 13, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr', 'pw'], + validValues: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13] + }, + value: 0 + }, + { + UUID: '000000DF-0000-1000-8000-0026BB765291', + constructorName: 'PowerModeSelection', + displayName: 'Power Mode Selection', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['pw'], + validValues: [0, 1] + }, + value: 0 + } + ], + primaryService: false + }, + TelevisionSpeaker: { + UUID: '00000113-0000-1000-8000-0026BB765291', + characteristics: [ + { + UUID: '0000011A-0000-1000-8000-0026BB765291', + constructorName: 'Mute', + displayName: 'Mute', + eventOnlyCharacteristic: false, + props: { + format: 'bool', + perms: ['ev', 'pr', 'pw'] + }, + value: false + } + ], + constructorName: 'TelevisionSpeaker', + displayName: 'TelevisionSpeaker', + hiddenService: false, + optionalCharacteristics: [ + { + UUID: '000000B0-0000-1000-8000-0026BB765291', + constructorName: 'Active', + displayName: 'Active', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr', 'pw'], + validValues: [0, 1] + }, + value: 0 + }, + { + UUID: '00000119-0000-1000-8000-0026BB765291', + constructorName: 'Volume', + displayName: 'Volume', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 100, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr', 'pw'], + unit: 'percentage' + }, + value: 0 + }, + { + UUID: '000000E9-0000-1000-8000-0026BB765291', + constructorName: 'VolumeControlType', + displayName: 'Volume Control Type', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 3, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'], + validValues: [0, 1, 2, 3] + }, + value: 0 + }, + { + UUID: '000000EA-0000-1000-8000-0026BB765291', + constructorName: 'VolumeSelector', + displayName: 'Volume Selector', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['pw'], + validValues: [0, 1] + }, + value: 0 + } + ], + primaryService: false + }, + TemperatureSensor: { + UUID: '0000008A-0000-1000-8000-0026BB765291', + characteristics: [ + { + UUID: '00000011-0000-1000-8000-0026BB765291', + constructorName: 'CurrentTemperature', + displayName: 'Current Temperature', + eventOnlyCharacteristic: false, + props: { + format: 'float', + maxValue: 100, + minStep: 0.1, + minValue: -270, + perms: ['ev', 'pr'], + unit: 'celsius' + }, + value: 0 + } + ], + constructorName: 'TemperatureSensor', + displayName: 'TemperatureSensor', + hiddenService: false, + optionalCharacteristics: [ + { + UUID: '00000023-0000-1000-8000-0026BB765291', + constructorName: 'Name', + displayName: 'Name', + eventOnlyCharacteristic: false, + props: { + format: 'string', + maxLen: 64, + perms: ['pr'] + }, + value: '' + }, + { + UUID: '00000075-0000-1000-8000-0026BB765291', + constructorName: 'StatusActive', + displayName: 'Status Active', + eventOnlyCharacteristic: false, + props: { + format: 'bool', + perms: ['ev', 'pr'] + }, + value: false + }, + { + UUID: '00000077-0000-1000-8000-0026BB765291', + constructorName: 'StatusFault', + displayName: 'Status Fault', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'], + validValues: [0, 1] + }, + value: 0 + }, + { + UUID: '00000079-0000-1000-8000-0026BB765291', + constructorName: 'StatusLowBattery', + displayName: 'Status Low Battery', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'], + validValues: [0, 1] + }, + value: 0 + }, + { + UUID: '0000007A-0000-1000-8000-0026BB765291', + constructorName: 'StatusTampered', + displayName: 'Status Tampered', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'], + validValues: [0, 1] + }, + value: 0 + } + ], + primaryService: false + }, + Thermostat: { + UUID: '0000004A-0000-1000-8000-0026BB765291', + characteristics: [ + { + UUID: '0000000F-0000-1000-8000-0026BB765291', + constructorName: 'CurrentHeatingCoolingState', + displayName: 'Current Heating Cooling State', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 2, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'], + validValues: [0, 1, 2] + }, + value: 0 + }, + { + UUID: '00000033-0000-1000-8000-0026BB765291', + constructorName: 'TargetHeatingCoolingState', + displayName: 'Target Heating Cooling State', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 3, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr', 'pw'], + validValues: [0, 1, 2, 3] + }, + value: 0 + }, + { + UUID: '00000011-0000-1000-8000-0026BB765291', + constructorName: 'CurrentTemperature', + displayName: 'Current Temperature', + eventOnlyCharacteristic: false, + props: { + format: 'float', + maxValue: 100, + minStep: 0.1, + minValue: -270, + perms: ['ev', 'pr'], + unit: 'celsius' + }, + value: 0 + }, + { + UUID: '00000035-0000-1000-8000-0026BB765291', + constructorName: 'TargetTemperature', + displayName: 'Target Temperature', + eventOnlyCharacteristic: false, + props: { + format: 'float', + maxValue: 38, + minStep: 0.1, + minValue: 10, + perms: ['ev', 'pr', 'pw'], + unit: 'celsius' + }, + value: 10 + }, + { + UUID: '00000036-0000-1000-8000-0026BB765291', + constructorName: 'TemperatureDisplayUnits', + displayName: 'Temperature Display Units', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr', 'pw'], + validValues: [0, 1] + }, + value: 0 + } + ], + constructorName: 'Thermostat', + displayName: 'Thermostat', + hiddenService: false, + optionalCharacteristics: [ + { + UUID: '00000023-0000-1000-8000-0026BB765291', + constructorName: 'Name', + displayName: 'Name', + eventOnlyCharacteristic: false, + props: { + format: 'string', + maxLen: 64, + perms: ['pr'] + }, + value: '' + }, + { + UUID: '00000010-0000-1000-8000-0026BB765291', + constructorName: 'CurrentRelativeHumidity', + displayName: 'Current Relative Humidity', + eventOnlyCharacteristic: false, + props: { + format: 'float', + maxValue: 100, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'], + unit: 'percentage' + }, + value: 0 + }, + { + UUID: '00000034-0000-1000-8000-0026BB765291', + constructorName: 'TargetRelativeHumidity', + displayName: 'Target Relative Humidity', + eventOnlyCharacteristic: false, + props: { + format: 'float', + maxValue: 100, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr', 'pw'], + unit: 'percentage' + }, + value: 0 + }, + { + UUID: '0000000D-0000-1000-8000-0026BB765291', + constructorName: 'CoolingThresholdTemperature', + displayName: 'Cooling Threshold Temperature', + eventOnlyCharacteristic: false, + props: { + format: 'float', + maxValue: 35, + minStep: 0.1, + minValue: 10, + perms: ['ev', 'pr', 'pw'], + unit: 'celsius' + }, + value: 10 + }, + { + UUID: '00000012-0000-1000-8000-0026BB765291', + constructorName: 'HeatingThresholdTemperature', + displayName: 'Heating Threshold Temperature', + eventOnlyCharacteristic: false, + props: { + format: 'float', + maxValue: 25, + minStep: 0.1, + minValue: 0, + perms: ['ev', 'pr', 'pw'], + unit: 'celsius' + }, + value: 0 + } + ], + primaryService: false + }, + ThreadTransport: { + UUID: '00000701-0000-1000-8000-0026BB765291', + characteristics: [ + { + UUID: '0000022B-0000-1000-8000-0026BB765291', + constructorName: 'CurrentTransport', + displayName: 'Current Transport', + eventOnlyCharacteristic: false, + props: { + format: 'bool', + perms: ['pr'] + }, + value: false + }, + { + UUID: '00000704-0000-1000-8000-0026BB765291', + constructorName: 'ThreadControlPoint', + displayName: 'Thread Control Point', + eventOnlyCharacteristic: false, + props: { + format: 'tlv8', + perms: ['pw'] + }, + value: '' + }, + { + UUID: '00000702-0000-1000-8000-0026BB765291', + constructorName: 'ThreadNodeCapabilities', + displayName: 'Thread Node Capabilities', + eventOnlyCharacteristic: false, + props: { + format: 'uint16', + maxValue: 31, + minStep: 1, + minValue: 0, + perms: ['pr'] + }, + value: 0 + }, + { + UUID: '00000703-0000-1000-8000-0026BB765291', + constructorName: 'ThreadStatus', + displayName: 'Thread Status', + eventOnlyCharacteristic: false, + props: { + format: 'uint16', + maxValue: 6, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'] + }, + value: 0 + } + ], + constructorName: 'ThreadTransport', + displayName: 'ThreadTransport', + hiddenService: false, + optionalCharacteristics: [ + { + UUID: '00000246-0000-1000-8000-0026BB765291', + constructorName: 'CCAEnergyDetectThreshold', + displayName: 'CCA Energy Detect Threshold', + eventOnlyCharacteristic: false, + props: { + format: 'int', + perms: ['pr'] + }, + value: 0 + }, + { + UUID: '00000245-0000-1000-8000-0026BB765291', + constructorName: 'CCASignalDetectThreshold', + displayName: 'CCA Signal Detect Threshold', + eventOnlyCharacteristic: false, + props: { + format: 'int', + perms: ['pr'] + }, + value: 0 + }, + { + UUID: '0000023D-0000-1000-8000-0026BB765291', + constructorName: 'EventRetransmissionMaximum', + displayName: 'Event Retransmission Maximum', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + perms: ['pr'] + }, + value: 0 + }, + { + UUID: '0000023E-0000-1000-8000-0026BB765291', + constructorName: 'EventTransmissionCounters', + displayName: 'Event Transmission Counters', + eventOnlyCharacteristic: false, + props: { + format: 'uint32', + perms: ['pr'] + }, + value: 0 + }, + { + UUID: '00000247-0000-1000-8000-0026BB765291', + constructorName: 'MACRetransmissionMaximum', + displayName: 'MAC Retransmission Maximum', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + perms: ['pr'] + }, + value: 0 + }, + { + UUID: '00000248-0000-1000-8000-0026BB765291', + constructorName: 'MACTransmissionCounters', + displayName: 'MAC Transmission Counters', + eventOnlyCharacteristic: false, + props: { + format: 'data', + perms: ['pr'] + }, + value: '' + }, + { + UUID: '00000244-0000-1000-8000-0026BB765291', + constructorName: 'ReceiverSensitivity', + displayName: 'Receiver Sensitivity', + eventOnlyCharacteristic: false, + props: { + format: 'int', + perms: ['pr'] + }, + value: 0 + }, + { + UUID: '0000023F-0000-1000-8000-0026BB765291', + constructorName: 'ReceivedSignalStrengthIndication', + displayName: 'Received Signal Strength Indication', + eventOnlyCharacteristic: false, + props: { + format: 'int', + perms: ['pr'] + }, + value: 0 + }, + { + UUID: '00000241-0000-1000-8000-0026BB765291', + constructorName: 'SignalToNoiseRatio', + displayName: 'Signal To Noise Ratio', + eventOnlyCharacteristic: false, + props: { + format: 'int', + perms: ['pr'] + }, + value: 0 + }, + { + UUID: '00000706-0000-1000-8000-0026BB765291', + constructorName: 'ThreadOpenThreadVersion', + displayName: 'Thread OpenThread Version', + eventOnlyCharacteristic: false, + props: { + format: 'string', + perms: ['pr'] + }, + value: '' + }, + { + UUID: '00000242-0000-1000-8000-0026BB765291', + constructorName: 'TransmitPower', + displayName: 'Transmit Power', + eventOnlyCharacteristic: false, + props: { + format: 'int', + perms: ['pr'] + }, + value: 0 + }, + { + UUID: '00000243-0000-1000-8000-0026BB765291', + constructorName: 'MaximumTransmitPower', + displayName: 'Maximum Transmit Power', + eventOnlyCharacteristic: false, + props: { + format: 'int', + perms: ['pr'] + }, + value: 0 + } + ], + primaryService: false + }, + TimeInformation: { + nrchkbDisabledText: 'TimeInformation (deprecated, unused)' + }, + TransferTransportManagement: { + UUID: '00000203-0000-1000-8000-0026BB765291', + characteristics: [ + { + UUID: '00000202-0000-1000-8000-0026BB765291', + constructorName: 'SupportedTransferTransportConfiguration', + displayName: 'Supported Transfer Transport Configuration', + eventOnlyCharacteristic: false, + props: { + format: 'tlv8', + perms: ['pr'] + }, + value: '' + }, + { + UUID: '00000201-0000-1000-8000-0026BB765291', + constructorName: 'SetupTransferTransport', + displayName: 'Setup Transfer Transport', + eventOnlyCharacteristic: false, + props: { + format: 'tlv8', + perms: ['pw', 'wr'] + }, + value: '' + } + ], + constructorName: 'TransferTransportManagement', + displayName: 'TransferTransportManagement', + hiddenService: false, + optionalCharacteristics: [], + primaryService: false + }, + Tunnel: { + UUID: '00000056-0000-1000-8000-0026BB765291', + characteristics: [ + { + UUID: '00000057-0000-1000-8000-0026BB765291', + constructorName: 'AccessoryIdentifier', + displayName: 'Accessory Identifier', + eventOnlyCharacteristic: false, + props: { + format: 'string', + perms: ['pr'] + }, + value: '' + }, + { + UUID: '00000061-0000-1000-8000-0026BB765291', + constructorName: 'TunnelConnectionTimeout', + displayName: 'Tunnel Connection Timeout', + eventOnlyCharacteristic: false, + props: { + format: 'int', + perms: ['ev', 'pr', 'pw'] + }, + value: 0 + }, + { + UUID: '00000060-0000-1000-8000-0026BB765291', + constructorName: 'TunneledAccessoryAdvertising', + displayName: 'Tunneled Accessory Advertising', + eventOnlyCharacteristic: false, + props: { + format: 'bool', + perms: ['ev', 'pr', 'pw'] + }, + value: false + }, + { + UUID: '00000059-0000-1000-8000-0026BB765291', + constructorName: 'TunneledAccessoryConnected', + displayName: 'Tunneled Accessory Connected', + eventOnlyCharacteristic: false, + props: { + format: 'bool', + perms: ['ev', 'pr', 'pw'] + }, + value: false + }, + { + UUID: '00000058-0000-1000-8000-0026BB765291', + constructorName: 'TunneledAccessoryStateNumber', + displayName: 'Tunneled Accessory State Number', + eventOnlyCharacteristic: false, + props: { + format: 'int', + perms: ['ev', 'pr'] + }, + value: 0 + } + ], + constructorName: 'Tunnel', + displayName: 'Tunnel', + hiddenService: false, + optionalCharacteristics: [], + primaryService: false + }, + TunneledBTLEAccessoryService: { + nrchkbDisabledText: + 'TunneledBTLEAccessoryService (deprecated, replaced by Tunnel)' + }, + Valve: { + UUID: '000000D0-0000-1000-8000-0026BB765291', + characteristics: [ + { + UUID: '000000B0-0000-1000-8000-0026BB765291', + constructorName: 'Active', + displayName: 'Active', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr', 'pw'], + validValues: [0, 1] + }, + value: 0 + }, + { + UUID: '000000D2-0000-1000-8000-0026BB765291', + constructorName: 'InUse', + displayName: 'In Use', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'], + validValues: [0, 1] + }, + value: 0 + }, + { + UUID: '000000D5-0000-1000-8000-0026BB765291', + constructorName: 'ValveType', + displayName: 'Valve Type', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 3, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'], + validValues: [0, 1, 2, 3] + }, + value: 0 + } + ], + constructorName: 'Valve', + displayName: 'Valve', + hiddenService: false, + optionalCharacteristics: [ + { + UUID: '000000D6-0000-1000-8000-0026BB765291', + constructorName: 'IsConfigured', + displayName: 'Is Configured', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr', 'pw'], + validValues: [0, 1] + }, + value: 0 + }, + { + UUID: '00000023-0000-1000-8000-0026BB765291', + constructorName: 'Name', + displayName: 'Name', + eventOnlyCharacteristic: false, + props: { + format: 'string', + maxLen: 64, + perms: ['pr'] + }, + value: '' + }, + { + UUID: '000000D4-0000-1000-8000-0026BB765291', + constructorName: 'RemainingDuration', + displayName: 'Remaining Duration', + eventOnlyCharacteristic: false, + props: { + format: 'uint32', + maxValue: 3600, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'], + unit: 'seconds' + }, + value: 0 + }, + { + UUID: '000000CB-0000-1000-8000-0026BB765291', + constructorName: 'ServiceLabelIndex', + displayName: 'Service Label Index', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 255, + minStep: 1, + minValue: 1, + perms: ['pr'] + }, + value: 1 + }, + { + UUID: '000000D3-0000-1000-8000-0026BB765291', + constructorName: 'SetDuration', + displayName: 'Set Duration', + eventOnlyCharacteristic: false, + props: { + format: 'uint32', + maxValue: 3600, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr', 'pw'], + unit: 'seconds' + }, + value: 0 + }, + { + UUID: '00000077-0000-1000-8000-0026BB765291', + constructorName: 'StatusFault', + displayName: 'Status Fault', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'], + validValues: [0, 1] + }, + value: 0 + } + ], + primaryService: false + }, + WiFiRouter: { + UUID: '0000020A-0000-1000-8000-0026BB765291', + characteristics: [ + { + UUID: '000000E3-0000-1000-8000-0026BB765291', + constructorName: 'ConfiguredName', + displayName: 'Configured Name', + eventOnlyCharacteristic: false, + props: { + format: 'string', + perms: ['ev', 'pr', 'pw'] + }, + value: '' + }, + { + UUID: '00000215-0000-1000-8000-0026BB765291', + constructorName: 'ManagedNetworkEnable', + displayName: 'Managed Network Enable', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minValue: 0, + perms: ['ev', 'pr', 'pw', 'tw'], + validValues: [0, 1] + }, + value: 0 + }, + { + UUID: '0000021F-0000-1000-8000-0026BB765291', + constructorName: 'NetworkAccessViolationControl', + displayName: 'Network Access Violation Control', + eventOnlyCharacteristic: false, + props: { + format: 'tlv8', + perms: ['ev', 'pr', 'pw', 'tw', 'wr'] + }, + value: '' + }, + { + UUID: '0000020C-0000-1000-8000-0026BB765291', + constructorName: 'NetworkClientProfileControl', + displayName: 'Network Client Profile Control', + eventOnlyCharacteristic: false, + props: { + format: 'tlv8', + perms: ['ev', 'pr', 'pw', 'tw', 'wr'] + }, + value: '' + }, + { + UUID: '0000020D-0000-1000-8000-0026BB765291', + constructorName: 'NetworkClientStatusControl', + displayName: 'Network Client Status Control', + eventOnlyCharacteristic: false, + props: { + format: 'tlv8', + perms: ['pr', 'pw', 'wr'] + }, + value: '' + }, + { + UUID: '0000020E-0000-1000-8000-0026BB765291', + constructorName: 'RouterStatus', + displayName: 'Router Status', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 1, + minValue: 0, + perms: ['ev', 'pr'], + validValues: [0, 1] + }, + value: 0 + }, + { + UUID: '00000210-0000-1000-8000-0026BB765291', + constructorName: 'SupportedRouterConfiguration', + displayName: 'Supported Router Configuration', + eventOnlyCharacteristic: false, + props: { + format: 'tlv8', + perms: ['pr'] + }, + value: '' + }, + { + UUID: '00000211-0000-1000-8000-0026BB765291', + constructorName: 'WANConfigurationList', + displayName: 'WAN Configuration List', + eventOnlyCharacteristic: false, + props: { + format: 'tlv8', + perms: ['ev', 'pr'] + }, + value: '' + }, + { + UUID: '00000212-0000-1000-8000-0026BB765291', + constructorName: 'WANStatusList', + displayName: 'WAN Status List', + eventOnlyCharacteristic: false, + props: { + format: 'tlv8', + perms: ['ev', 'pr'] + }, + value: '' + } + ], + constructorName: 'WiFiRouter', + displayName: 'WiFiRouter', + hiddenService: false, + optionalCharacteristics: [], + primaryService: false + }, + WiFiSatellite: { + UUID: '0000020F-0000-1000-8000-0026BB765291', + characteristics: [ + { + UUID: '0000021E-0000-1000-8000-0026BB765291', + constructorName: 'WiFiSatelliteStatus', + displayName: 'Wi-Fi Satellite Status', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 2, + minValue: 0, + perms: ['ev', 'pr'], + validValues: [0, 1, 2] + }, + value: 0 + } + ], + constructorName: 'WiFiSatellite', + displayName: 'WiFiSatellite', + hiddenService: false, + optionalCharacteristics: [], + primaryService: false + }, + WiFiTransport: { + UUID: '0000022A-0000-1000-8000-0026BB765291', + characteristics: [ + { + UUID: '0000022B-0000-1000-8000-0026BB765291', + constructorName: 'CurrentTransport', + displayName: 'Current Transport', + eventOnlyCharacteristic: false, + props: { + format: 'bool', + perms: ['pr'] + }, + value: false + }, + { + UUID: '0000022C-0000-1000-8000-0026BB765291', + constructorName: 'WiFiCapabilities', + displayName: 'Wi-Fi Capabilities', + eventOnlyCharacteristic: false, + props: { + format: 'uint32', + perms: ['pr'] + }, + value: 0 + } + ], + constructorName: 'WiFiTransport', + displayName: 'WiFiTransport', + hiddenService: false, + optionalCharacteristics: [ + { + UUID: '0000022D-0000-1000-8000-0026BB765291', + constructorName: 'WiFiConfigurationControl', + displayName: 'Wi-Fi Configuration Control', + eventOnlyCharacteristic: false, + props: { + format: 'tlv8', + perms: ['ev', 'pr', 'pw', 'tw', 'wr'] + }, + value: '' + } + ], + primaryService: false + }, + Window: { + UUID: '0000008B-0000-1000-8000-0026BB765291', + characteristics: [ + { + UUID: '0000006D-0000-1000-8000-0026BB765291', + constructorName: 'CurrentPosition', + displayName: 'Current Position', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 100, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'], + unit: 'percentage' + }, + value: 0 + }, + { + UUID: '00000072-0000-1000-8000-0026BB765291', + constructorName: 'PositionState', + displayName: 'Position State', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 2, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'], + validValues: [0, 1, 2] + }, + value: 0 + }, + { + UUID: '0000007C-0000-1000-8000-0026BB765291', + constructorName: 'TargetPosition', + displayName: 'Target Position', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 100, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr', 'pw'], + unit: 'percentage' + }, + value: 0 + } + ], + constructorName: 'Window', + displayName: 'Window', + hiddenService: false, + optionalCharacteristics: [ + { + UUID: '00000023-0000-1000-8000-0026BB765291', + constructorName: 'Name', + displayName: 'Name', + eventOnlyCharacteristic: false, + props: { + format: 'string', + maxLen: 64, + perms: ['pr'] + }, + value: '' + }, + { + UUID: '00000024-0000-1000-8000-0026BB765291', + constructorName: 'ObstructionDetected', + displayName: 'Obstruction Detected', + eventOnlyCharacteristic: false, + props: { + format: 'bool', + perms: ['ev', 'pr'] + }, + value: false + }, + { + UUID: '0000006F-0000-1000-8000-0026BB765291', + constructorName: 'HoldPosition', + displayName: 'Hold Position', + eventOnlyCharacteristic: false, + props: { + format: 'bool', + perms: ['pw'] + }, + value: false + } + ], + primaryService: false + }, + WindowCovering: { + UUID: '0000008C-0000-1000-8000-0026BB765291', + characteristics: [ + { + UUID: '0000006D-0000-1000-8000-0026BB765291', + constructorName: 'CurrentPosition', + displayName: 'Current Position', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 100, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'], + unit: 'percentage' + }, + value: 0 + }, + { + UUID: '00000072-0000-1000-8000-0026BB765291', + constructorName: 'PositionState', + displayName: 'Position State', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 2, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr'], + validValues: [0, 1, 2] + }, + value: 0 + }, + { + UUID: '0000007C-0000-1000-8000-0026BB765291', + constructorName: 'TargetPosition', + displayName: 'Target Position', + eventOnlyCharacteristic: false, + props: { + format: 'uint8', + maxValue: 100, + minStep: 1, + minValue: 0, + perms: ['ev', 'pr', 'pw'], + unit: 'percentage' + }, + value: 0 + } + ], + constructorName: 'WindowCovering', + displayName: 'WindowCovering', + hiddenService: false, + optionalCharacteristics: [ + { + UUID: '0000006C-0000-1000-8000-0026BB765291', + constructorName: 'CurrentHorizontalTiltAngle', + displayName: 'Current Horizontal Tilt Angle', + eventOnlyCharacteristic: false, + props: { + format: 'int', + maxValue: 90, + minStep: 1, + minValue: -90, + perms: ['ev', 'pr'], + unit: 'arcdegrees' + }, + value: -90 + }, + { + UUID: '0000007B-0000-1000-8000-0026BB765291', + constructorName: 'TargetHorizontalTiltAngle', + displayName: 'Target Horizontal Tilt Angle', + eventOnlyCharacteristic: false, + props: { + format: 'int', + maxValue: 90, + minStep: 1, + minValue: -90, + perms: ['ev', 'pr', 'pw'], + unit: 'arcdegrees' + }, + value: -90 + }, + { + UUID: '00000023-0000-1000-8000-0026BB765291', + constructorName: 'Name', + displayName: 'Name', + eventOnlyCharacteristic: false, + props: { + format: 'string', + maxLen: 64, + perms: ['pr'] + }, + value: '' + }, + { + UUID: '00000024-0000-1000-8000-0026BB765291', + constructorName: 'ObstructionDetected', + displayName: 'Obstruction Detected', + eventOnlyCharacteristic: false, + props: { + format: 'bool', + perms: ['ev', 'pr'] + }, + value: false + }, + { + UUID: '0000006F-0000-1000-8000-0026BB765291', + constructorName: 'HoldPosition', + displayName: 'Hold Position', + eventOnlyCharacteristic: false, + props: { + format: 'bool', + perms: ['pw'] + }, + value: false + }, + { + UUID: '0000006E-0000-1000-8000-0026BB765291', + constructorName: 'CurrentVerticalTiltAngle', + displayName: 'Current Vertical Tilt Angle', + eventOnlyCharacteristic: false, + props: { + format: 'int', + maxValue: 90, + minStep: 1, + minValue: -90, + perms: ['ev', 'pr'], + unit: 'arcdegrees' + }, + value: -90 + }, + { + UUID: '0000007D-0000-1000-8000-0026BB765291', + constructorName: 'TargetVerticalTiltAngle', + displayName: 'Target Vertical Tilt Angle', + eventOnlyCharacteristic: false, + props: { + format: 'int', + maxValue: 90, + minStep: 1, + minValue: -90, + perms: ['ev', 'pr', 'pw'], + unit: 'arcdegrees' + }, + value: -90 + } + ], + primaryService: false + } } diff --git a/src/test/test-utils/data/switch.service.bridge.flow.ts b/src/test/test-utils/data/switch.service.bridge.flow.ts index 87ef7cbc..49590980 100644 --- a/src/test/test-utils/data/switch.service.bridge.flow.ts +++ b/src/test/test-utils/data/switch.service.bridge.flow.ts @@ -1,86 +1,86 @@ import helper from 'node-red-node-test-helper' export const switchServiceBridgeFlow = () => { - const serviceId = `s1.${Date.now()}` - const bridgeId = `b1.${Date.now()}` - const flowId = `f1.${Date.now()}` + const serviceId = `s1.${Date.now()}` + const bridgeId = `b1.${Date.now()}` + const flowId = `f1.${Date.now()}` - return { - serviceId, - bridgeId, - flowId, - flow: [ - { - id: serviceId, - type: 'homekit-service', - z: flowId, - isParent: true, - hostType: '0', - bridge: bridgeId, - accessoryId: '', - parentService: '', - name: 'Example Switch', - serviceName: 'Switch', - topic: '', - filter: false, - manufacturer: 'NRCHKB', - model: '0.130.7', - serialNo: 'Default Serial Number', - firmwareRev: '0.130.7', - hardwareRev: '0.130.7', - softwareRev: '0.130.7', - cameraConfigVideoProcessor: 'ffmpeg', - cameraConfigSource: '', - cameraConfigStillImageSource: '', - cameraConfigMaxStreams: 2, - cameraConfigMaxWidth: 1280, - cameraConfigMaxHeight: 720, - cameraConfigMaxFPS: 10, - cameraConfigMaxBitrate: 300, - cameraConfigVideoCodec: 'libx264', - cameraConfigAudioCodec: 'libfdk_aac', - cameraConfigAudio: false, - cameraConfigPacketSize: 1316, - cameraConfigVerticalFlip: false, - cameraConfigHorizontalFlip: false, - cameraConfigMapVideo: '0:0', - cameraConfigMapAudio: '0:1', - cameraConfigVideoFilter: 'scale=1280:720', - cameraConfigAdditionalCommandLine: '-tune zerolatency', - cameraConfigDebug: false, - cameraConfigSnapshotOutput: 'disabled', - cameraConfigInterfaceName: '', - characteristicProperties: '{}', - waitForSetupMsg: false, - outputs: 2, - x: 350, - y: 240, - wires: [['h1'], ['h1']], - }, - { - id: bridgeId, - type: 'homekit-bridge', - bridgeName: 'Example Bridge', - pinCode: '1111-1111', - port: '', - allowInsecureRequest: false, - manufacturer: 'NRCHKB', - model: '0.130.7', - serialNo: 'Default Serial Number', - firmwareRev: '0.130.7', - hardwareRev: '0.130.7', - softwareRev: '0.130.7', - customMdnsConfig: false, - mdnsMulticast: true, - mdnsInterface: '', - mdnsPort: '', - mdnsIp: '', - mdnsTtl: '', - mdnsLoopback: true, - mdnsReuseAddr: true, - allowMessagePassthrough: true, - }, - { id: 'h1', type: 'helper' }, - ] as helper.TestFlows, - } + return { + serviceId, + bridgeId, + flowId, + flow: [ + { + id: serviceId, + type: 'homekit-service', + z: flowId, + isParent: true, + hostType: '0', + bridge: bridgeId, + accessoryId: '', + parentService: '', + name: 'Example Switch', + serviceName: 'Switch', + topic: '', + filter: false, + manufacturer: 'NRCHKB', + model: '0.130.7', + serialNo: 'Default Serial Number', + firmwareRev: '0.130.7', + hardwareRev: '0.130.7', + softwareRev: '0.130.7', + cameraConfigVideoProcessor: 'ffmpeg', + cameraConfigSource: '', + cameraConfigStillImageSource: '', + cameraConfigMaxStreams: 2, + cameraConfigMaxWidth: 1280, + cameraConfigMaxHeight: 720, + cameraConfigMaxFPS: 10, + cameraConfigMaxBitrate: 300, + cameraConfigVideoCodec: 'libx264', + cameraConfigAudioCodec: 'libfdk_aac', + cameraConfigAudio: false, + cameraConfigPacketSize: 1316, + cameraConfigVerticalFlip: false, + cameraConfigHorizontalFlip: false, + cameraConfigMapVideo: '0:0', + cameraConfigMapAudio: '0:1', + cameraConfigVideoFilter: 'scale=1280:720', + cameraConfigAdditionalCommandLine: '-tune zerolatency', + cameraConfigDebug: false, + cameraConfigSnapshotOutput: 'disabled', + cameraConfigInterfaceName: '', + characteristicProperties: '{}', + waitForSetupMsg: false, + outputs: 2, + x: 350, + y: 240, + wires: [['h1'], ['h1']] + }, + { + id: bridgeId, + type: 'homekit-bridge', + bridgeName: 'Example Bridge', + pinCode: '1111-1111', + port: '', + allowInsecureRequest: false, + manufacturer: 'NRCHKB', + model: '0.130.7', + serialNo: 'Default Serial Number', + firmwareRev: '0.130.7', + hardwareRev: '0.130.7', + softwareRev: '0.130.7', + customMdnsConfig: false, + mdnsMulticast: true, + mdnsInterface: '', + mdnsPort: '', + mdnsIp: '', + mdnsTtl: '', + mdnsLoopback: true, + mdnsReuseAddr: true, + allowMessagePassthrough: true + }, + { id: 'h1', type: 'helper' } + ] as helper.TestFlows + } } diff --git a/src/test/test-utils/data/switch.service2.bridge.flow.ts b/src/test/test-utils/data/switch.service2.bridge.flow.ts index 7307d7b3..8a1b92d2 100644 --- a/src/test/test-utils/data/switch.service2.bridge.flow.ts +++ b/src/test/test-utils/data/switch.service2.bridge.flow.ts @@ -1,87 +1,87 @@ import helper from 'node-red-node-test-helper' export const switchService2BridgeFlow = () => { - const serviceId = `s1.${Date.now()}` - const bridgeId = `b1.${Date.now()}` - const flowId = `f1.${Date.now()}` + const serviceId = `s1.${Date.now()}` + const bridgeId = `b1.${Date.now()}` + const flowId = `f1.${Date.now()}` - return { - serviceId, - bridgeId, - flowId, - flow: [ - { - id: serviceId, - type: 'homekit-service2', - z: flowId, - isParent: true, - hostType: '0', - bridge: bridgeId, - accessoryId: '', - parentService: '', - name: 'Example Switch', - serviceName: 'Switch', - topic: '', - filter: false, - manufacturer: 'NRCHKB', - model: '1.4.3', - serialNo: 'Default Serial Number', - firmwareRev: '1.4.3', - hardwareRev: '1.4.3', - softwareRev: '1.4.3', - cameraConfigVideoProcessor: 'ffmpeg', - cameraConfigSource: '', - cameraConfigStillImageSource: '', - cameraConfigMaxStreams: 2, - cameraConfigMaxWidth: 1280, - cameraConfigMaxHeight: 720, - cameraConfigMaxFPS: 10, - cameraConfigMaxBitrate: 300, - cameraConfigVideoCodec: 'libx264', - cameraConfigAudioCodec: 'libfdk_aac', - cameraConfigAudio: false, - cameraConfigPacketSize: 1316, - cameraConfigVerticalFlip: false, - cameraConfigHorizontalFlip: false, - cameraConfigMapVideo: '0:0', - cameraConfigMapAudio: '0:1', - cameraConfigVideoFilter: 'scale=1280:720', - cameraConfigAdditionalCommandLine: '-tune zerolatency', - cameraConfigDebug: false, - cameraConfigSnapshotOutput: 'disabled', - cameraConfigInterfaceName: '', - characteristicProperties: '{}', - waitForSetupMsg: false, - useEventCallback: false, - outputs: 1, - x: 1290, - y: 340, - wires: [['h1'], ['h1']], - }, - { - id: bridgeId, - type: 'homekit-bridge', - bridgeName: 'Example Bridge', - pinCode: '1111-1111', - port: '', - allowInsecureRequest: false, - manufacturer: 'NRCHKB', - model: '0.130.7', - serialNo: 'Default Serial Number', - firmwareRev: '0.130.7', - hardwareRev: '0.130.7', - softwareRev: '0.130.7', - customMdnsConfig: false, - mdnsMulticast: true, - mdnsInterface: '', - mdnsPort: '', - mdnsIp: '', - mdnsTtl: '', - mdnsLoopback: true, - mdnsReuseAddr: true, - allowMessagePassthrough: true, - }, - { id: 'h1', type: 'helper' }, - ] as helper.TestFlows, - } + return { + serviceId, + bridgeId, + flowId, + flow: [ + { + id: serviceId, + type: 'homekit-service2', + z: flowId, + isParent: true, + hostType: '0', + bridge: bridgeId, + accessoryId: '', + parentService: '', + name: 'Example Switch', + serviceName: 'Switch', + topic: '', + filter: false, + manufacturer: 'NRCHKB', + model: '1.4.3', + serialNo: 'Default Serial Number', + firmwareRev: '1.4.3', + hardwareRev: '1.4.3', + softwareRev: '1.4.3', + cameraConfigVideoProcessor: 'ffmpeg', + cameraConfigSource: '', + cameraConfigStillImageSource: '', + cameraConfigMaxStreams: 2, + cameraConfigMaxWidth: 1280, + cameraConfigMaxHeight: 720, + cameraConfigMaxFPS: 10, + cameraConfigMaxBitrate: 300, + cameraConfigVideoCodec: 'libx264', + cameraConfigAudioCodec: 'libfdk_aac', + cameraConfigAudio: false, + cameraConfigPacketSize: 1316, + cameraConfigVerticalFlip: false, + cameraConfigHorizontalFlip: false, + cameraConfigMapVideo: '0:0', + cameraConfigMapAudio: '0:1', + cameraConfigVideoFilter: 'scale=1280:720', + cameraConfigAdditionalCommandLine: '-tune zerolatency', + cameraConfigDebug: false, + cameraConfigSnapshotOutput: 'disabled', + cameraConfigInterfaceName: '', + characteristicProperties: '{}', + waitForSetupMsg: false, + useEventCallback: false, + outputs: 1, + x: 1290, + y: 340, + wires: [['h1'], ['h1']] + }, + { + id: bridgeId, + type: 'homekit-bridge', + bridgeName: 'Example Bridge', + pinCode: '1111-1111', + port: '', + allowInsecureRequest: false, + manufacturer: 'NRCHKB', + model: '0.130.7', + serialNo: 'Default Serial Number', + firmwareRev: '0.130.7', + hardwareRev: '0.130.7', + softwareRev: '0.130.7', + customMdnsConfig: false, + mdnsMulticast: true, + mdnsInterface: '', + mdnsPort: '', + mdnsIp: '', + mdnsTtl: '', + mdnsLoopback: true, + mdnsReuseAddr: true, + allowMessagePassthrough: true + }, + { id: 'h1', type: 'helper' } + ] as helper.TestFlows + } } diff --git a/tsconfig.json b/tsconfig.json index a819d3b8..29c5b94a 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -2,9 +2,7 @@ "compilerOptions": { "target": "es6", "module": "commonjs", - "lib": [ - "es2020.string" - ], + "lib": ["es2020.string"], "skipLibCheck": true, "allowJs": true, "checkJs": false, @@ -28,12 +26,6 @@ "resolveJsonModule": true, "declaration": true }, - "include": [ - "src" - ], - "exclude": [ - "node_modules", - "**/test/*", - "build" - ] + "include": ["src"], + "exclude": ["node_modules", "**/test/*", "build"] } From 102afeabe5ca627b1f16e893b5803aef19e1f85d Mon Sep 17 00:00:00 2001 From: Shaquu Date: Sun, 23 Nov 2025 23:56:31 +0100 Subject: [PATCH 05/14] General code cleanup after biome migration --- .github/workflows/tests.yml | 2 +- biome.json | 19 +- package.json | 3 +- src/lib/HAPHostNode.ts | 118 +++++----- src/lib/HAPServiceNode.ts | 205 +++++++++-------- src/lib/HAPServiceNode2.ts | 209 +++++++++--------- src/lib/Storage.ts | 13 +- src/lib/api.ts | 30 ++- src/lib/hap/HAPCharacteristic.ts | 2 +- src/lib/hap/HAPService.ts | 2 +- src/lib/hap/eve-app/EveCharacteristics.ts | 2 +- src/lib/types/CustomCharacteristicType.ts | 2 +- src/lib/types/HAPHostConfigType.ts | 8 +- src/lib/types/HAPHostNodeType.ts | 8 +- src/lib/types/HAPService2ConfigType.ts | 4 +- src/lib/types/HAPService2NodeType.ts | 6 +- src/lib/types/HAPServiceConfigType.ts | 6 +- src/lib/types/HAPServiceNodeType.ts | 20 +- src/lib/types/HAPStatusConfigType.ts | 2 +- src/lib/types/HAPStatusNodeType.ts | 10 +- src/lib/types/NodeType.ts | 2 +- src/lib/types/storage/SerializedHostType.ts | 4 +- src/lib/utils/AccessoryUtils.ts | 32 +-- src/lib/utils/BridgeUtils.ts | 11 +- src/lib/utils/CharacteristicUtils.ts | 22 +- src/lib/utils/CharacteristicUtils2.ts | 22 +- src/lib/utils/NodeStatusUtils.ts | 8 +- src/lib/utils/ServiceUtils.ts | 62 +++--- src/lib/utils/ServiceUtils2.ts | 69 +++--- src/lib/utils/index.ts | 4 +- src/nodes/bridge.ts | 2 +- src/nodes/nrchkb.ts | 6 +- src/nodes/service.ts | 2 +- src/nodes/service2.ts | 2 +- src/nodes/standalone.ts | 2 +- src/nodes/status.ts | 35 ++- src/test/lib/HAPBridgeNode.test.ts | 10 +- src/test/lib/NodeStatusUtils.test.ts | 22 +- src/test/lib/api.test.ts | 24 +- src/test/nodes/service.test.ts | 29 ++- src/test/nodes/service2.test.ts | 29 ++- .../data/switch.service.bridge.flow.ts | 2 +- .../data/switch.service2.bridge.flow.ts | 2 +- tsconfig.json | 2 +- 44 files changed, 535 insertions(+), 541 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index adfca9ec..323038e8 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -17,7 +17,7 @@ jobs: - name: build and test run: | npm ci - biome ci + npm run lint npm run build npm run test env: diff --git a/biome.json b/biome.json index cb2bf71f..2da45fb7 100644 --- a/biome.json +++ b/biome.json @@ -6,7 +6,16 @@ "useIgnoreFile": true }, "files": { - "ignoreUnknown": false + "ignoreUnknown": false, + "includes": [ + "src/**", + "examples/**", + "docs/**", + "*.md", + "*.json", + "*.yml", + ".husky/**" + ] }, "formatter": { "enabled": true, @@ -15,7 +24,13 @@ "linter": { "enabled": true, "rules": { - "recommended": true + "recommended": true, + "suspicious": { + "noExplicitAny": "off" + }, + "complexity": { + "useArrowFunction": "warn" + } } }, "javascript": { diff --git a/package.json b/package.json index 41fc4c9a..01238f55 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,8 @@ "clean": "del-cli \"build/lib\" \"build/**/*.js\"", "test": "vitest run", "test:watch": "vitest", - "format": "biome format --write", + "format": "npx @biomejs/biome check --write", + "lint": "npx @biomejs/biome check", "prepare": "husky install" }, "repository": { diff --git a/src/lib/HAPHostNode.ts b/src/lib/HAPHostNode.ts index a3e37418..91729bf6 100644 --- a/src/lib/HAPHostNode.ts +++ b/src/lib/HAPHostNode.ts @@ -1,33 +1,32 @@ import { Accessory, Bridge, - Categories, + type Categories, Characteristic, MDNSAdvertiser, Service, uuid } from '@homebridge/hap-nodejs' import { logger } from '@nrchkb/logger' -import { NodeAPI } from 'node-red' +import type { NodeAPI } from 'node-red' import { SemVer } from 'semver' import semver from 'semver/preload' import NRCHKBError from './NRCHKBError' -import HapCategories from './types/hap-nodejs/HapCategories' -import HAPHostConfigType from './types/HAPHostConfigType' -import HAPHostNodeType from './types/HAPHostNodeType' +import type HAPHostConfigType from './types/HAPHostConfigType' +import type HAPHostNodeType from './types/HAPHostNodeType' import HostType from './types/HostType' +import HapCategories from './types/hap-nodejs/HapCategories' module.exports = (RED: NodeAPI, hostType: HostType) => { const init = function (this: HAPHostNodeType, config: HAPHostConfigType) { - const self = this - const log = logger('NRCHKB', 'HAPHostNode', config.bridgeName, self) + const log = logger('NRCHKB', 'HAPHostNode', config.bridgeName, this) - self.hostType = hostType - RED.nodes.createNode(self, config) + this.hostType = hostType + RED.nodes.createNode(this, config) - self.config = config - self.name = config.bridgeName + this.config = config + this.name = config.bridgeName if (!hostNameValidator(config.bridgeName)) { log.error('Host name is incorrect', false) @@ -38,101 +37,107 @@ module.exports = (RED: NodeAPI, hostType: HostType) => { config.firmwareRev = new SemVer('0.0.0') } - self.accessoryCategory = (self.hostType == HostType.BRIDGE + // biome-ignore lint/suspicious/noDoubleEquals: hostType can be a string or a number + this.accessoryCategory = (this.hostType == HostType.BRIDGE ? HapCategories.BRIDGE - : self.config.accessoryCategory) as unknown as Categories + : this.config.accessoryCategory) as unknown as Categories - self.published = false + this.published = false try { - self.bridgeUsername = macify(self.id) + this.bridgeUsername = macify(this.id) } catch (error: any) { log.error(error) return error } - const hostUUID = uuid.generate(self.id) + const hostUUID = uuid.generate(this.id) const hostTypeName = - self.hostType == HostType.BRIDGE ? 'Bridge' : 'Standalone Accessory' + // biome-ignore lint/suspicious/noDoubleEquals: hostType can be a string or a number + this.hostType == HostType.BRIDGE ? 'Bridge' : 'Standalone Accessory' log.debug(`Creating ${hostTypeName} with UUID ${hostUUID}`) - if (self.hostType == HostType.BRIDGE) { - self.host = new Bridge(self.name, hostUUID) + // biome-ignore lint/suspicious/noDoubleEquals: hostType can be a string or a number + if (this.hostType == HostType.BRIDGE) { + this.host = new Bridge(this.name, hostUUID) } else { - self.host = new Accessory(self.name, hostUUID) + this.host = new Accessory(this.name, hostUUID) } - self.publish = function () { - if (self.hostType == HostType.BRIDGE) { + this.publish = () => { + // biome-ignore lint/suspicious/noDoubleEquals: hostType can be a string or a number + if (this.hostType == HostType.BRIDGE) { log.debug( - `Publishing ${hostTypeName} with pin code ${self.config.pinCode} and ${self.host.bridgedAccessories.length} accessories` + `Publishing ${hostTypeName} with pin code ${this.config.pinCode} and ${this.host.bridgedAccessories.length} accessories` ) } else { log.debug( - `Publishing ${hostTypeName} with pin code ${self.config.pinCode}` + `Publishing ${hostTypeName} with pin code ${this.config.pinCode}` ) } - if (self.config.port && self.config.port == 1880) { + if (this.config.port === 1880) { log.error( `Cannot publish on ${hostTypeName} port 1880 as it is reserved for node-red` ) - self.published = false + this.published = false return false } // As HAP-Nodejs cannot understand new pin code format yet, we need to adjust new to old one - let oldPinCode = self.config.pinCode + let oldPinCode = this.config.pinCode - if ((oldPinCode.match(/-/g) || []).length == 1) { + if ((oldPinCode.match(/-/g) || []).length === 1) { oldPinCode = oldPinCode.replace(/-/g, '') oldPinCode = `${oldPinCode.slice(0, 3)}-${oldPinCode.slice(3, 5)}-${oldPinCode.slice(5, 8)}` } - let bind - if (self.config.bind?.length && self.config.bindType) { - if (self.config.bindType == 'str') { - bind = self.config.bind - } else if (self.config.bindType == 'json') { - bind = JSON.parse(self.config.bind) + let bind: string | undefined + if (this.config.bind?.length && this.config.bindType) { + if (this.config.bindType === 'str') { + bind = this.config.bind + } else if (this.config.bindType === 'json') { + bind = JSON.parse(this.config.bind) } } - self.host.publish( + this.host.publish( { - username: self.bridgeUsername, + username: this.bridgeUsername, port: - self.config.port && !isNaN(self.config.port) ? self.config.port : 0, + this.config.port && !Number.isNaN(this.config.port) + ? this.config.port + : 0, pincode: oldPinCode, - category: self.accessoryCategory, + category: this.accessoryCategory, bind: bind, - advertiser: self.config.advertiser ?? MDNSAdvertiser.BONJOUR + advertiser: this.config.advertiser ?? MDNSAdvertiser.BONJOUR }, - self.config.allowInsecureRequest + this.config.allowInsecureRequest ) - self.published = true + this.published = true return true } - self.on('close', async function (removed: any, done: () => any) { + this.on('close', async (removed: any, done: () => any) => { if (removed) { log.debug('This node has been deleted') - await self.host.destroy() + await this.host.destroy() } else { log.debug('This node is being restarted') - await self.host.unpublish() + await this.host.unpublish() } - self.published = false + this.published = false done() }) - self.host.on('identify', function (paired: any, callback: () => any) { + this.host.on('identify', (paired: any, callback: () => any) => { if (paired) { log.debug(`Identify called on paired ${hostTypeName}`) } else { @@ -144,24 +149,24 @@ module.exports = (RED: NodeAPI, hostType: HostType) => { // Service.AccessoryInformation created on Host creation const accessoryInformationService = - self.host.getService(Service.AccessoryInformation) || - self.host.addService(Service.AccessoryInformation) + this.host.getService(Service.AccessoryInformation) || + this.host.addService(Service.AccessoryInformation) accessoryInformationService - .setCharacteristic(Characteristic.Manufacturer, self.config.manufacturer) - .setCharacteristic(Characteristic.SerialNumber, self.config.serialNo) - .setCharacteristic(Characteristic.Model, self.config.model) + .setCharacteristic(Characteristic.Manufacturer, this.config.manufacturer) + .setCharacteristic(Characteristic.SerialNumber, this.config.serialNo) + .setCharacteristic(Characteristic.Model, this.config.model) .setCharacteristic( Characteristic.FirmwareRevision, - self.config.firmwareRev?.toString() + this.config.firmwareRev?.toString() ) .setCharacteristic( Characteristic.HardwareRevision, - self.config.hardwareRev?.toString() + this.config.hardwareRev?.toString() ) .setCharacteristic( Characteristic.SoftwareRevision, - self.config.softwareRev?.toString() + this.config.softwareRev?.toString() ) } @@ -184,9 +189,8 @@ module.exports = (RED: NodeAPI, hostType: HostType) => { } } - const hostNameValidator = function (hostName: string) { - return hostName ? /^[^.]{1,64}$/.test(hostName) : false - } + const hostNameValidator = (hostName: string) => + hostName ? /^[^.]{1,64}$/.test(hostName) : false return { init, diff --git a/src/lib/HAPServiceNode.ts b/src/lib/HAPServiceNode.ts index abab25d1..cd0b0709 100644 --- a/src/lib/HAPServiceNode.ts +++ b/src/lib/HAPServiceNode.ts @@ -1,11 +1,11 @@ import { uuid } from '@homebridge/hap-nodejs' import { logger } from '@nrchkb/logger' -import { NodeAPI } from 'node-red' +import type { NodeAPI } from 'node-red' import NRCHKBError from './NRCHKBError' -import HAPHostNodeType from './types/HAPHostNodeType' -import HAPServiceConfigType from './types/HAPServiceConfigType' -import HAPServiceNodeType from './types/HAPServiceNodeType' +import type HAPHostNodeType from './types/HAPHostNodeType' +import type HAPServiceConfigType from './types/HAPServiceConfigType' +import type HAPServiceNodeType from './types/HAPServiceNodeType' import HostType from './types/HostType' import { NodeStatusUtils } from './utils/NodeStatusUtils' @@ -16,24 +16,22 @@ module.exports = (RED: NodeAPI) => { const nrchkbConfigCompatibilityOverride = function ( this: HAPServiceNodeType ) { - const self = this + const log = logger('NRCHKB', 'HAPServiceNode', this.config.name, this) - const log = logger('NRCHKB', 'HAPServiceNode', self.config.name, self) - - if (self.config.isParent === undefined) { + if (this.config.isParent === undefined) { log.trace( - `nrchkbConfigCompatibilityOverride => self.config.isParent=${self.config.isParent} value changed to true` + `nrchkbConfigCompatibilityOverride => self.config.isParent=${this.config.isParent} value changed to true` ) // Services created in pre linked services era where working in 1.2 but due to more typescript in 1.3+ it started to cause some errors - self.config.isParent = true + this.config.isParent = true } - if (self.config.hostType === undefined) { + if (this.config.hostType === undefined) { // When moving from 1.2 to 1.3 hostType is not defined on homekit-service log.trace( - `nrchkbConfigCompatibilityOverride => self.config.hostType=${self.config.hostType} value changed to HostType.BRIDGE` + `nrchkbConfigCompatibilityOverride => self.config.hostType=${this.config.hostType} value changed to HostType.BRIDGE` ) - self.config.hostType = HostType.BRIDGE + this.config.hostType = HostType.BRIDGE } } @@ -41,45 +39,44 @@ module.exports = (RED: NodeAPI) => { this: HAPServiceNodeType, config: HAPServiceConfigType ) { - const self = this - self.nodeStatusUtils = new NodeStatusUtils(self) + this.nodeStatusUtils = new NodeStatusUtils(this) - self.config = config - self.name = self.config.name + this.config = config + this.name = this.config.name - const log = logger('NRCHKB', 'HAPServiceNode', self.config.name, self) + const log = logger('NRCHKB', 'HAPServiceNode', this.config.name, this) - self.RED = RED - self.publishTimers = {} + this.RED = RED + this.publishTimers = {} - nrchkbConfigCompatibilityOverride.call(self) - RED.nodes.createNode(self, self.config) + nrchkbConfigCompatibilityOverride.call(this) + RED.nodes.createNode(this, this.config) - const ServiceUtils = require('./utils/ServiceUtils')(self) + const ServiceUtils = require('./utils/ServiceUtils')(this) new Promise((resolve) => { - if (self.config.waitForSetupMsg) { + if (this.config.waitForSetupMsg) { log.debug( 'Waiting for Setup message. It should be of format {"payload":{"nrchkb":{"setup":{}}}}' ) - self.setupDone = false + this.setupDone = false - self.nodeStatusUtils.setStatus({ + this.nodeStatusUtils.setStatus({ fill: 'blue', shape: 'dot', text: 'Waiting for Setup' }) - self.handleWaitForSetup = (msg: Record) => - ServiceUtils.handleWaitForSetup(self.config, msg, resolve) - self.on('input', self.handleWaitForSetup) + this.handleWaitForSetup = (msg: Record) => + ServiceUtils.handleWaitForSetup(this.config, msg, resolve) + this.on('input', this.handleWaitForSetup) } else { - resolve(self.config) + resolve(this.config) } }) .then((newConfig) => { - init.call(self, newConfig) + init.call(this, newConfig) }) .catch((error: any) => { log.error(`Error while starting Service due to ${error}`) @@ -90,18 +87,17 @@ module.exports = (RED: NodeAPI) => { this: HAPServiceNodeType, config: HAPServiceConfigType ) { - const self = this - self.config = config + this.config = config - const log = logger('NRCHKB', 'HAPServiceNode', self.config.name, self) + const log = logger('NRCHKB', 'HAPServiceNode', this.config.name, this) - const ServiceUtils = require('./utils/ServiceUtils')(self) + const ServiceUtils = require('./utils/ServiceUtils')(this) - if (self.config.isParent) { + if (this.config.isParent) { log.debug('Starting Parent Service') - configure.call(self) - self.configured = true - self.reachable = true + configure.call(this) + this.configured = true + this.reachable = true } else { const serviceType = config.serviceName === 'CameraControl' ? 'Camera' : 'Linked' @@ -109,8 +105,8 @@ module.exports = (RED: NodeAPI) => { ServiceUtils.waitForParent() .then(() => { log.debug(`Starting ${serviceType} Service`) - configure.call(self) - self.configured = true + configure.call(this) + this.configured = true }) .catch((error: any) => { log.error( @@ -121,11 +117,9 @@ module.exports = (RED: NodeAPI) => { } const configure = function (this: HAPServiceNodeType) { - const self = this - - const log = logger('NRCHKB', 'HAPServiceNode', self.config.name, self) + const log = logger('NRCHKB', 'HAPServiceNode', this.config.name, this) - const Utils = require('./utils')(self) + const Utils = require('./utils')(this) const AccessoryUtils = Utils.AccessoryUtils const BridgeUtils = Utils.BridgeUtils const CharacteristicUtils = Utils.CharacteristicUtils @@ -133,26 +127,28 @@ module.exports = (RED: NodeAPI) => { let parentNode: HAPServiceNodeType - if (self.config.isParent) { + if (this.config.isParent) { const hostId = - self.config.hostType == HostType.BRIDGE - ? self.config.bridge - : self.config.accessoryId + // biome-ignore lint/suspicious/noDoubleEquals: hostType can be a string or a number + this.config.hostType == HostType.BRIDGE + ? this.config.bridge + : this.config.accessoryId - self.hostNode = RED.nodes.getNode(hostId) as HAPHostNodeType + this.hostNode = RED.nodes.getNode(hostId) as HAPHostNodeType - if (!self.hostNode) { - const message = `Host node ${self.config.hostType == HostType.BRIDGE ? 'Bridge' : 'Standalone Accessory'} ${hostId} not found` + if (!this.hostNode) { + // biome-ignore lint/suspicious/noDoubleEquals: hostType can be a string or a number + const message = `Host node ${this.config.hostType == HostType.BRIDGE ? 'Bridge' : 'Standalone Accessory'} ${hostId} not found` log.error(message, false) throw new NRCHKBError(message) } - self.childNodes = [] - self.childNodes.push(self) + this.childNodes = [] + this.childNodes.push(this) } else { // Retrieve parent service node parentNode = RED.nodes.getNode( - self.config.parentService + this.config.parentService ) as HAPServiceNodeType if (!parentNode) { @@ -160,44 +156,45 @@ module.exports = (RED: NodeAPI) => { throw new NRCHKBError('Parent Node not assigned') } - self.parentNode = parentNode - self.parentService = self.parentNode.service + this.parentNode = parentNode + this.parentService = this.parentNode.service - if (!self.parentService) { + if (!this.parentService) { log.error('Parent Service not assigned', false) throw new NRCHKBError('Parent Service not assigned') } - self.hostNode = self.parentNode.hostNode - self.parentNode.childNodes?.push(self) + this.hostNode = this.parentNode.hostNode + this.parentNode.childNodes?.push(this) - self.accessory = self.parentNode.accessory + this.accessory = this.parentNode.accessory } // Service node properties - self.name = self.config.name + this.name = this.config.name // Find a unique identifier for the current service if ( - self.hasOwnProperty('_flow') && - self.hasOwnProperty('_alias') && - self._flow?.hasOwnProperty('TYPE') && - self._flow.TYPE === 'subflow' + Object.hasOwn(this, '_flow') && + Object.hasOwn(this, '_alias') && + (this._flow ? Object(this._flow).hasOwn('TYPE') : false) && + this._flow?.TYPE === 'subflow' ) { // For subflows, use the service node identifier from the subflow template // plus the full path from the subflow node identifier to the subflow. - self.uniqueIdentifier = self._alias + '/' + self._flow.path + this.uniqueIdentifier = `${this._alias}/${this._flow.path}` } else { // For top level flows, use the node identifier - self.uniqueIdentifier = self.id + this.uniqueIdentifier = this.id } // Generate UUID from unique identifier - const subtypeUUID = uuid.generate(self.uniqueIdentifier) + const subtypeUUID = uuid.generate(this.uniqueIdentifier) // Look for existing Accessory or create a new one - if (self.config.hostType == HostType.BRIDGE) { - if (self.config.isParent) { + // biome-ignore lint/suspicious/noDoubleEquals: hostType can be a string or a number + if (this.config.hostType == HostType.BRIDGE) { + if (this.config.isParent) { // According to the HomeKit Accessory Protocol Specification the value // of the fields Name, Manufacturer, Serial Number and Model must not // change throughout the lifetime of an accessory. Because of that the @@ -206,67 +203,67 @@ module.exports = (RED: NodeAPI) => { // changes. const accessoryUUID = uuid.generate( 'A' + - self.uniqueIdentifier + - self.name + - self.config.manufacturer + - self.config.serialNo + - self.config.model + this.uniqueIdentifier + + this.name + + this.config.manufacturer + + this.config.serialNo + + this.config.model ) - self.accessory = AccessoryUtils.getOrCreate( - self.hostNode.host, + this.accessory = AccessoryUtils.getOrCreate( + this.hostNode.host, { - name: self.name, + name: this.name, UUID: accessoryUUID, - manufacturer: self.config.manufacturer, - serialNo: self.config.serialNo, - model: self.config.model, - firmwareRev: self.config.firmwareRev, - hardwareRev: self.config.hardwareRev, - softwareRev: self.config.softwareRev + manufacturer: this.config.manufacturer, + serialNo: this.config.serialNo, + model: this.config.model, + firmwareRev: this.config.firmwareRev, + hardwareRev: this.config.hardwareRev, + softwareRev: this.config.softwareRev }, subtypeUUID // subtype of the primary service for identification ) //Respond to identify - self.onIdentify = AccessoryUtils.onIdentify - self.accessory.on('identify', self.onIdentify) + this.onIdentify = AccessoryUtils.onIdentify + this.accessory.on('identify', this.onIdentify) } } else { // We are using Standalone Accessory mode so no need to create new Accessory as we have "host" already log.debug('Binding Service accessory as Standalone Accessory') - self.accessory = self.hostNode.host + this.accessory = this.hostNode.host } // Look for existing Service or create a new one - self.service = ServiceUtils.getOrCreate( - self.accessory, + this.service = ServiceUtils.getOrCreate( + this.accessory, { - name: self.name, + name: this.name, UUID: subtypeUUID, - serviceName: self.config.serviceName, - config: self.config + serviceName: this.config.serviceName, + config: this.config }, - self.parentService + this.parentService ) - self.characteristicProperties = CharacteristicUtils.load( - self.service, - self.config + this.characteristicProperties = CharacteristicUtils.load( + this.service, + this.config ) ServiceUtils.configureAdaptiveLightning() - if (self.config.isParent) { - BridgeUtils.delayedPublish(self) + if (this.config.isParent) { + BridgeUtils.delayedPublish(this) } // The pinCode should be shown to the user until interaction with iOS // client starts - self.nodeStatusUtils.setStatus({ + this.nodeStatusUtils.setStatus({ fill: 'yellow', shape: 'ring', - text: self.hostNode.config.pinCode + text: this.hostNode.config.pinCode }) // Emit message when value changes @@ -274,12 +271,12 @@ module.exports = (RED: NodeAPI) => { // Subscribe to set and get on characteristics for that service and get // list of all supported - self.supported = CharacteristicUtils.subscribeAndGetSupported(self.service) + this.supported = CharacteristicUtils.subscribeAndGetSupported(this.service) // Respond to inputs - self.on('input', ServiceUtils.onInput) + this.on('input', ServiceUtils.onInput) - self.on('close', ServiceUtils.onClose) + this.on('close', ServiceUtils.onClose) } return { diff --git a/src/lib/HAPServiceNode2.ts b/src/lib/HAPServiceNode2.ts index e858a7d6..0175fd4c 100644 --- a/src/lib/HAPServiceNode2.ts +++ b/src/lib/HAPServiceNode2.ts @@ -1,11 +1,11 @@ import { uuid } from '@homebridge/hap-nodejs' import { logger } from '@nrchkb/logger' -import { NodeAPI } from 'node-red' +import type { NodeAPI } from 'node-red' import NRCHKBError from './NRCHKBError' -import HAPHostNodeType from './types/HAPHostNodeType' -import HAPService2ConfigType from './types/HAPService2ConfigType' -import HAPService2NodeType from './types/HAPService2NodeType' +import type HAPHostNodeType from './types/HAPHostNodeType' +import type HAPService2ConfigType from './types/HAPService2ConfigType' +import type HAPService2NodeType from './types/HAPService2NodeType' import HostType from './types/HostType' import { NodeStatusUtils } from './utils/NodeStatusUtils' @@ -16,24 +16,22 @@ module.exports = (RED: NodeAPI) => { const nrchkbConfigCompatibilityOverride = function ( this: HAPService2NodeType ) { - const self = this + const log = logger('NRCHKB', 'HAPServiceNode2', this.config.name, this) - const log = logger('NRCHKB', 'HAPServiceNode2', self.config.name, self) - - if (self.config.isParent === undefined) { + if (this.config.isParent === undefined) { log.trace( - `nrchkbConfigCompatibilityOverride => self.config.isParent=${self.config.isParent} value changed to true` + `nrchkbConfigCompatibilityOverride => self.config.isParent=${this.config.isParent} value changed to true` ) // Services created in pre linked services era where working in 1.2 but due to more typescript in 1.3+ it started to cause some errors - self.config.isParent = true + this.config.isParent = true } - if (self.config.hostType === undefined) { + if (this.config.hostType === undefined) { // When moving from 1.2 to 1.3 hostType is not defined on homekit-service log.trace( - `nrchkbConfigCompatibilityOverride => self.config.hostType=${self.config.hostType} value changed to HostType.BRIDGE` + `nrchkbConfigCompatibilityOverride => self.config.hostType=${this.config.hostType} value changed to HostType.BRIDGE` ) - self.config.hostType = HostType.BRIDGE + this.config.hostType = HostType.BRIDGE } } @@ -41,45 +39,44 @@ module.exports = (RED: NodeAPI) => { this: HAPService2NodeType, config: HAPService2ConfigType ) { - const self = this - self.nodeStatusUtils = new NodeStatusUtils(self) + this.nodeStatusUtils = new NodeStatusUtils(this) - self.config = config - self.name = self.config.name + this.config = config + this.name = this.config.name - const log = logger('NRCHKB', 'HAPServiceNode2', self.config.name, self) + const log = logger('NRCHKB', 'HAPServiceNode2', this.config.name, this) - self.RED = RED - self.publishTimers = {} + this.RED = RED + this.publishTimers = {} - nrchkbConfigCompatibilityOverride.call(self) - RED.nodes.createNode(self, self.config) + nrchkbConfigCompatibilityOverride.call(this) + RED.nodes.createNode(this, this.config) - const ServiceUtils = require('./utils/ServiceUtils2')(self) + const ServiceUtils = require('./utils/ServiceUtils2')(this) new Promise((resolve) => { - if (self.config.waitForSetupMsg) { + if (this.config.waitForSetupMsg) { log.debug( 'Waiting for Setup message. It should be of format {"payload":{"nrchkb":{"setup":{}}}}' ) - self.setupDone = false + this.setupDone = false - self.nodeStatusUtils.setStatus({ + this.nodeStatusUtils.setStatus({ fill: 'blue', shape: 'dot', text: 'Waiting for Setup' }) - self.handleWaitForSetup = (msg: Record) => - ServiceUtils.handleWaitForSetup(self.config, msg, resolve) - self.on('input', self.handleWaitForSetup) + this.handleWaitForSetup = (msg: Record) => + ServiceUtils.handleWaitForSetup(this.config, msg, resolve) + this.on('input', this.handleWaitForSetup) } else { - resolve(self.config) + resolve(this.config) } }) .then((newConfig) => { - init.call(self, newConfig) + init.call(this, newConfig) }) .catch((error: any) => { log.error(`Error while starting Service due to ${error}`) @@ -90,18 +87,17 @@ module.exports = (RED: NodeAPI) => { this: HAPService2NodeType, config: HAPService2ConfigType ) { - const self = this - self.config = config + this.config = config - const log = logger('NRCHKB', 'HAPServiceNode2', self.config.name, self) + const log = logger('NRCHKB', 'HAPServiceNode2', this.config.name, this) - const ServiceUtils = require('./utils/ServiceUtils2')(self) + const ServiceUtils = require('./utils/ServiceUtils2')(this) - if (self.config.isParent) { + if (this.config.isParent) { log.debug('Starting Parent Service') - configure.call(self) - self.configured = true - self.reachable = true + configure.call(this) + this.configured = true + this.reachable = true } else { const serviceType = config.serviceName === 'CameraControl' ? 'Camera' : 'Linked' @@ -109,8 +105,8 @@ module.exports = (RED: NodeAPI) => { ServiceUtils.waitForParent() .then(() => { log.debug(`Starting ${serviceType} Service`) - configure.call(self) - self.configured = true + configure.call(this) + this.configured = true }) .catch((error: any) => { log.error( @@ -121,38 +117,38 @@ module.exports = (RED: NodeAPI) => { } const configure = function (this: HAPService2NodeType) { - const self = this - - const log = logger('NRCHKB', 'HAPServiceNode2', self.config.name, self) + const log = logger('NRCHKB', 'HAPServiceNode2', this.config.name, this) - const Utils = require('./utils')(self) + const Utils = require('./utils')(this) const AccessoryUtils = Utils.AccessoryUtils const BridgeUtils = Utils.BridgeUtils - const CharacteristicUtils = require('./utils/CharacteristicUtils2')(self) - const ServiceUtils = require('./utils/ServiceUtils2')(self) + const CharacteristicUtils = require('./utils/CharacteristicUtils2')(this) + const ServiceUtils = require('./utils/ServiceUtils2')(this) let parentNode: HAPService2NodeType - if (self.config.isParent) { + if (this.config.isParent) { const hostId = - self.config.hostType == HostType.BRIDGE - ? self.config.bridge - : self.config.accessoryId + // biome-ignore lint/suspicious/noDoubleEquals: hostType can be a string or a number + this.config.hostType == HostType.BRIDGE + ? this.config.bridge + : this.config.accessoryId - self.hostNode = RED.nodes.getNode(hostId) as HAPHostNodeType + this.hostNode = RED.nodes.getNode(hostId) as HAPHostNodeType - if (!self.hostNode) { - const message = `Host node ${self.config.hostType == HostType.BRIDGE ? 'Bridge' : 'Standalone Accessory'} ${hostId} not found` + if (!this.hostNode) { + // biome-ignore lint/suspicious/noDoubleEquals: hostType can be a string or a number + const message = `Host node ${this.config.hostType == HostType.BRIDGE ? 'Bridge' : 'Standalone Accessory'} ${hostId} not found` log.error(message, false) throw new NRCHKBError(message) } - self.childNodes = [] - self.childNodes.push(self) + this.childNodes = [] + this.childNodes.push(this) } else { // Retrieve parent service node parentNode = RED.nodes.getNode( - self.config.parentService + this.config.parentService ) as HAPService2NodeType if (!parentNode) { @@ -160,44 +156,45 @@ module.exports = (RED: NodeAPI) => { throw new NRCHKBError('Parent Node not assigned') } - self.parentNode = parentNode - self.parentService = self.parentNode.service + this.parentNode = parentNode + this.parentService = this.parentNode.service - if (!self.parentService) { + if (!this.parentService) { log.error('Parent Service not assigned', false) throw new NRCHKBError('Parent Service not assigned') } - self.hostNode = self.parentNode.hostNode - self.parentNode.childNodes?.push(self) + this.hostNode = this.parentNode.hostNode + this.parentNode.childNodes?.push(this) - self.accessory = self.parentNode.accessory + this.accessory = this.parentNode.accessory } // Service node properties - self.name = self.config.name + this.name = this.config.name // Find a unique identifier for the current service if ( - self.hasOwnProperty('_flow') && - self.hasOwnProperty('_alias') && - self._flow?.hasOwnProperty('TYPE') && - self._flow.TYPE === 'subflow' + Object.hasOwn(this, '_flow') && + Object.hasOwn(this, '_alias') && + (this._flow ? Object(this._flow).hasOwn('TYPE') : false) && + this._flow?.TYPE === 'subflow' ) { // For subflows, use the service node identifier from the subflow template // plus the full path from the subflow node identifier to the subflow. - self.uniqueIdentifier = self._alias + '/' + self._flow.path + this.uniqueIdentifier = `${this._alias}/${this._flow.path}` } else { // For top level flows, use the node identifier - self.uniqueIdentifier = self.id + this.uniqueIdentifier = this.id } // Generate UUID from unique identifier - const subtypeUUID = uuid.generate(self.uniqueIdentifier) + const subtypeUUID = uuid.generate(this.uniqueIdentifier) // Look for existing Accessory or create a new one - if (self.config.hostType == HostType.BRIDGE) { - if (self.config.isParent) { + // biome-ignore lint/suspicious/noDoubleEquals: hostType can be a string or a number + if (this.config.hostType == HostType.BRIDGE) { + if (this.config.isParent) { // According to the HomeKit Accessory Protocol Specification the value // of the fields Name, Manufacturer, Serial Number and Model must not // change throughout the lifetime of an accessory. Because of that the @@ -206,67 +203,67 @@ module.exports = (RED: NodeAPI) => { // changes. const accessoryUUID = uuid.generate( 'A' + - self.uniqueIdentifier + - self.name + - self.config.manufacturer + - self.config.serialNo + - self.config.model + this.uniqueIdentifier + + this.name + + this.config.manufacturer + + this.config.serialNo + + this.config.model ) - self.accessory = AccessoryUtils.getOrCreate( - self.hostNode.host, + this.accessory = AccessoryUtils.getOrCreate( + this.hostNode.host, { - name: self.name, + name: this.name, UUID: accessoryUUID, - manufacturer: self.config.manufacturer, - serialNo: self.config.serialNo, - model: self.config.model, - firmwareRev: self.config.firmwareRev, - hardwareRev: self.config.hardwareRev, - softwareRev: self.config.softwareRev + manufacturer: this.config.manufacturer, + serialNo: this.config.serialNo, + model: this.config.model, + firmwareRev: this.config.firmwareRev, + hardwareRev: this.config.hardwareRev, + softwareRev: this.config.softwareRev }, subtypeUUID // subtype of the primary service for identification ) //Respond to identify - self.onIdentify = AccessoryUtils.onIdentify - self.accessory.on('identify', self.onIdentify) + this.onIdentify = AccessoryUtils.onIdentify + this.accessory.on('identify', this.onIdentify) } } else { // We are using Standalone Accessory mode so no need to create new Accessory as we have "host" already log.debug('Binding Service accessory as Standalone Accessory') - self.accessory = self.hostNode.host + this.accessory = this.hostNode.host } // Look for existing Service or create a new one - self.service = ServiceUtils.getOrCreate( - self.accessory, + this.service = ServiceUtils.getOrCreate( + this.accessory, { - name: self.name, + name: this.name, UUID: subtypeUUID, - serviceName: self.config.serviceName, - config: self.config + serviceName: this.config.serviceName, + config: this.config }, - self.parentService + this.parentService ) - self.characteristicProperties = CharacteristicUtils.load( - self.service, - self.config + this.characteristicProperties = CharacteristicUtils.load( + this.service, + this.config ) ServiceUtils.configureAdaptiveLightning() - if (self.config.isParent) { - BridgeUtils.delayedPublish(self) + if (this.config.isParent) { + BridgeUtils.delayedPublish(this) } // The pinCode should be shown to the user until interaction with iOS // client starts - self.nodeStatusUtils.setStatus({ + this.nodeStatusUtils.setStatus({ fill: 'yellow', shape: 'ring', - text: self.hostNode.config.pinCode + text: this.hostNode.config.pinCode }) // Emit message when value changes @@ -274,12 +271,12 @@ module.exports = (RED: NodeAPI) => { // Subscribe to set and get on characteristics for that service and get // list of all supported - self.supported = CharacteristicUtils.subscribeAndGetSupported(self.service) + this.supported = CharacteristicUtils.subscribeAndGetSupported(this.service) // Respond to inputs - self.on('input', ServiceUtils.onInput) + this.on('input', ServiceUtils.onInput) - self.on('close', ServiceUtils.onClose) + this.on('close', ServiceUtils.onClose) } return { diff --git a/src/lib/Storage.ts b/src/lib/Storage.ts index 2802330d..ebafa5dc 100644 --- a/src/lib/Storage.ts +++ b/src/lib/Storage.ts @@ -1,19 +1,19 @@ -import { +import path from 'node:path' +import type { CharacteristicEventTypes, SerializedAccessory, SerializedService } from '@homebridge/hap-nodejs' import { logger } from '@nrchkb/logger' -import storage, { InitOptions } from 'node-persist' -import path from 'path' +import storage, { type InitOptions } from 'node-persist' import { - v4 as uuidv4, validate as uuidValidate, - version as uuidVersion + version as uuidVersion, + v4 as uuidv4 } from 'uuid' import NRCHKBError from './NRCHKBError' -import { SerializedHostType } from './types/storage/SerializedHostType' +import type { SerializedHostType } from './types/storage/SerializedHostType' import { StorageType } from './types/storage/StorageType' type EventCallback = { @@ -21,6 +21,7 @@ type EventCallback = { callback: (value?: any) => void } +// biome-ignore lint/complexity/noStaticOnlyClass: Storage is a static class export class Storage { private static customStoragePath: string private static storageInitialized = false diff --git a/src/lib/api.ts b/src/lib/api.ts index 9e83ef96..39494a08 100644 --- a/src/lib/api.ts +++ b/src/lib/api.ts @@ -1,23 +1,23 @@ import { Characteristic, Perms, - SerializedService, + type SerializedService, Service } from '@homebridge/hap-nodejs' import { logger } from '@nrchkb/logger' -import express from 'express' -import { NodeAPI } from 'node-red' +import type express from 'express' +import type { NodeAPI } from 'node-red' import EveCharacteristics from './hap/eve-app/EveCharacteristics' import { Storage } from './Storage' -import CustomCharacteristicType from './types/CustomCharacteristicType' +import type CustomCharacteristicType from './types/CustomCharacteristicType' +import type HAPServiceConfigType from './types/HAPServiceConfigType' +import type HAPServiceNodeType from './types/HAPServiceNodeType' import HapCategories from './types/hap-nodejs/HapCategories' -import HAPServiceConfigType from './types/HAPServiceConfigType' -import HAPServiceNodeType from './types/HAPServiceNodeType' const version = require('../../package.json').version.trim() -module.exports = function (RED: NodeAPI) { +module.exports = (RED: NodeAPI) => { const log = logger('NRCHKB', 'API') // Service API @@ -187,7 +187,7 @@ module.exports = function (RED: NodeAPI) { const toNumber = (value: any, optional = undefined) => { const num = Number(value) - if (isNaN(num)) { + if (Number.isNaN(num)) { return optional } else return num } @@ -236,9 +236,11 @@ module.exports = function (RED: NodeAPI) { } class CustomCharacteristic extends Characteristic { + // biome-ignore lint/style/noNonNullAssertion: UUID is not null static readonly UUID: string = UUID! constructor() { + // biome-ignore lint/style/noNonNullAssertion: name is not null super(name!, CustomCharacteristic.UUID, { ...validatedProps, perms: validatedProps.perms ?? [ @@ -291,15 +293,11 @@ module.exports = function (RED: NodeAPI) { serviceNodeConfig.id ) as HAPServiceNodeType - if ( - serviceNode && - serviceNode.characteristicProperties && - serviceNode.service - ) { + if (serviceNode?.characteristicProperties && serviceNode.service) { for (const key in serviceNode.characteristicProperties) { if (customCharacteristicKeys.includes(key)) { const characteristic = serviceNode.service - // @ts-ignore + // @ts-expect-error .getCharacteristic(Characteristic[key]) .setProps(serviceNode.characteristicProperties[key]) serviceNode.supported.push(key) @@ -358,7 +356,7 @@ module.exports = function (RED: NodeAPI) { } // Accessory API - const _initAccessoryAPI = function () { + const _initAccessoryAPI = () => { log.debug('Initialize Accessory API') // Accessory Categories API response data @@ -369,7 +367,7 @@ module.exports = function (RED: NodeAPI) { // Prepare Accessory data once Object.keys(HapCategories) .sort() - .filter((x) => parseInt(x) >= 0) + .filter((x) => parseInt(x, 10) >= 0) .forEach((key) => { const keyNumber = key as unknown as number accessoryCategoriesData[keyNumber] = HapCategories[keyNumber] diff --git a/src/lib/hap/HAPCharacteristic.ts b/src/lib/hap/HAPCharacteristic.ts index 4101a734..148daf7f 100644 --- a/src/lib/hap/HAPCharacteristic.ts +++ b/src/lib/hap/HAPCharacteristic.ts @@ -1,6 +1,6 @@ import { Characteristic } from '@homebridge/hap-nodejs' -import { +import type { EveS2R1, EveS2R2, EveS2W1, diff --git a/src/lib/hap/HAPService.ts b/src/lib/hap/HAPService.ts index 7c84ddad..6cb8b4db 100644 --- a/src/lib/hap/HAPService.ts +++ b/src/lib/hap/HAPService.ts @@ -1,6 +1,6 @@ import { Service } from '@homebridge/hap-nodejs' -import { EveHistoryData } from './eve-app/EveServices' +import type { EveHistoryData } from './eve-app/EveServices' class HAPService extends Service { static EveHistoryData: typeof EveHistoryData diff --git a/src/lib/hap/eve-app/EveCharacteristics.ts b/src/lib/hap/eve-app/EveCharacteristics.ts index acabbe97..54962bf6 100644 --- a/src/lib/hap/eve-app/EveCharacteristics.ts +++ b/src/lib/hap/eve-app/EveCharacteristics.ts @@ -1,6 +1,6 @@ import { Formats, Perms } from '@homebridge/hap-nodejs/dist/lib/Characteristic' -import CustomCharacteristicType from '../../types/CustomCharacteristicType' +import type CustomCharacteristicType from '../../types/CustomCharacteristicType' import HAPCharacteristic from '../HAPCharacteristic' /** diff --git a/src/lib/types/CustomCharacteristicType.ts b/src/lib/types/CustomCharacteristicType.ts index a5171108..12bc9a75 100644 --- a/src/lib/types/CustomCharacteristicType.ts +++ b/src/lib/types/CustomCharacteristicType.ts @@ -1,4 +1,4 @@ -import { CharacteristicProps } from '@homebridge/hap-nodejs' +import type { CharacteristicProps } from '@homebridge/hap-nodejs' type CustomCharacteristicType = CharacteristicProps & { UUID?: string diff --git a/src/lib/types/HAPHostConfigType.ts b/src/lib/types/HAPHostConfigType.ts index 4be5fc89..6a4b8143 100644 --- a/src/lib/types/HAPHostConfigType.ts +++ b/src/lib/types/HAPHostConfigType.ts @@ -1,8 +1,8 @@ -import { MDNSAdvertiser } from '@homebridge/hap-nodejs' -import { NodeDef } from 'node-red' -import { SemVer } from 'semver' +import type { MDNSAdvertiser } from '@homebridge/hap-nodejs' +import type { NodeDef } from 'node-red' +import type { SemVer } from 'semver' -import HapCategories from './hap-nodejs/HapCategories' +import type HapCategories from './hap-nodejs/HapCategories' type HAPHostConfigType = NodeDef & { bridgeName: string diff --git a/src/lib/types/HAPHostNodeType.ts b/src/lib/types/HAPHostNodeType.ts index d34c2b4f..a348453e 100644 --- a/src/lib/types/HAPHostNodeType.ts +++ b/src/lib/types/HAPHostNodeType.ts @@ -1,8 +1,8 @@ -import { Accessory, Categories } from '@homebridge/hap-nodejs' +import type { Accessory, Categories } from '@homebridge/hap-nodejs' -import HAPHostConfigType from './HAPHostConfigType' -import HostType from './HostType' -import NodeType from './NodeType' +import type HAPHostConfigType from './HAPHostConfigType' +import type HostType from './HostType' +import type NodeType from './NodeType' type HAPHostNodeType = NodeType & { config: HAPHostConfigType diff --git a/src/lib/types/HAPService2ConfigType.ts b/src/lib/types/HAPService2ConfigType.ts index 59212fd2..63984e43 100644 --- a/src/lib/types/HAPService2ConfigType.ts +++ b/src/lib/types/HAPService2ConfigType.ts @@ -1,6 +1,6 @@ -import { NodeDef } from 'node-red' +import type { NodeDef } from 'node-red' -import HAPServiceConfigType from './HAPServiceConfigType' +import type HAPServiceConfigType from './HAPServiceConfigType' type HAPService2ConfigType = NodeDef & HAPServiceConfigType & { diff --git a/src/lib/types/HAPService2NodeType.ts b/src/lib/types/HAPService2NodeType.ts index b270f115..39a2da16 100644 --- a/src/lib/types/HAPService2NodeType.ts +++ b/src/lib/types/HAPService2NodeType.ts @@ -1,6 +1,6 @@ -import HAPService2ConfigType from './HAPService2ConfigType' -import HAPServiceNodeType from './HAPServiceNodeType' -import NodeType from './NodeType' +import type HAPService2ConfigType from './HAPService2ConfigType' +import type HAPServiceNodeType from './HAPServiceNodeType' +import type NodeType from './NodeType' type HAPService2NodeType = NodeType & HAPServiceNodeType & { diff --git a/src/lib/types/HAPServiceConfigType.ts b/src/lib/types/HAPServiceConfigType.ts index 2c18c47e..d88ea4f8 100644 --- a/src/lib/types/HAPServiceConfigType.ts +++ b/src/lib/types/HAPServiceConfigType.ts @@ -1,7 +1,7 @@ -import { AdaptiveLightingControllerMode } from '@homebridge/hap-nodejs/dist/lib/controller/AdaptiveLightingController' -import { NodeDef } from 'node-red' +import type { AdaptiveLightingControllerMode } from '@homebridge/hap-nodejs/dist/lib/controller/AdaptiveLightingController' +import type { NodeDef } from 'node-red' -import CameraConfigType from './CameraConfigType' +import type CameraConfigType from './CameraConfigType' type HAPServiceConfigType = NodeDef & { isParent: boolean diff --git a/src/lib/types/HAPServiceNodeType.ts b/src/lib/types/HAPServiceNodeType.ts index 12f5fa27..2c827a27 100644 --- a/src/lib/types/HAPServiceNodeType.ts +++ b/src/lib/types/HAPServiceNodeType.ts @@ -1,4 +1,4 @@ -import { +import type { Accessory, AdaptiveLightingController, Characteristic, @@ -9,16 +9,16 @@ import { CharacteristicValue, Service } from '@homebridge/hap-nodejs' -import { CharacteristicContext } from '@homebridge/hap-nodejs/dist/lib/Characteristic' -import { HAPConnection } from '@homebridge/hap-nodejs/dist/lib/util/eventedhttp' -import { NodeAPI } from 'node-red' +import type { CharacteristicContext } from '@homebridge/hap-nodejs/dist/lib/Characteristic' +import type { HAPConnection } from '@homebridge/hap-nodejs/dist/lib/util/eventedhttp' +import type { NodeAPI } from 'node-red' -import { NodeStatusUtils } from '../utils/NodeStatusUtils' -import HAPHostNodeType from './HAPHostNodeType' -import HAPService2NodeType from './HAPService2NodeType' -import HAPServiceConfigType from './HAPServiceConfigType' -import NodeType from './NodeType' -import PublishTimersType from './PublishTimersType' +import type { NodeStatusUtils } from '../utils/NodeStatusUtils' +import type HAPHostNodeType from './HAPHostNodeType' +import type HAPService2NodeType from './HAPService2NodeType' +import type HAPServiceConfigType from './HAPServiceConfigType' +import type NodeType from './NodeType' +import type PublishTimersType from './PublishTimersType' type HAPServiceNodeType = NodeType & { config: HAPServiceConfigType diff --git a/src/lib/types/HAPStatusConfigType.ts b/src/lib/types/HAPStatusConfigType.ts index a67cfd93..5267e2c0 100644 --- a/src/lib/types/HAPStatusConfigType.ts +++ b/src/lib/types/HAPStatusConfigType.ts @@ -1,4 +1,4 @@ -import { NodeDef } from 'node-red' +import type { NodeDef } from 'node-red' type HAPStatusConfigType = NodeDef & { serviceNodeId: string diff --git a/src/lib/types/HAPStatusNodeType.ts b/src/lib/types/HAPStatusNodeType.ts index 108fc373..0e1632a7 100644 --- a/src/lib/types/HAPStatusNodeType.ts +++ b/src/lib/types/HAPStatusNodeType.ts @@ -1,9 +1,9 @@ -import { NodeAPI } from 'node-red' +import type { NodeAPI } from 'node-red' -import { NodeStatusUtils } from '../utils/NodeStatusUtils' -import HAPServiceNodeType from './HAPServiceNodeType' -import HAPStatusConfigType from './HAPStatusConfigType' -import NodeType from './NodeType' +import type { NodeStatusUtils } from '../utils/NodeStatusUtils' +import type HAPServiceNodeType from './HAPServiceNodeType' +import type HAPStatusConfigType from './HAPStatusConfigType' +import type NodeType from './NodeType' type HAPStatusNodeType = NodeType & { config: HAPStatusConfigType diff --git a/src/lib/types/NodeType.ts b/src/lib/types/NodeType.ts index cb593854..d3d64e73 100644 --- a/src/lib/types/NodeType.ts +++ b/src/lib/types/NodeType.ts @@ -1,4 +1,4 @@ -import { Node } from 'node-red' +import type { Node } from 'node-red' type NodeType = Node diff --git a/src/lib/types/storage/SerializedHostType.ts b/src/lib/types/storage/SerializedHostType.ts index cea820a0..9d334bd2 100644 --- a/src/lib/types/storage/SerializedHostType.ts +++ b/src/lib/types/storage/SerializedHostType.ts @@ -1,7 +1,7 @@ -import { SerializedAccessory } from '@homebridge/hap-nodejs' +import type { SerializedAccessory } from '@homebridge/hap-nodejs' type SerializedHostType = { _isBridge: boolean } & SerializedAccessory -export { SerializedHostType } +export type { SerializedHostType } diff --git a/src/lib/utils/AccessoryUtils.ts b/src/lib/utils/AccessoryUtils.ts index 1b089435..b6638718 100644 --- a/src/lib/utils/AccessoryUtils.ts +++ b/src/lib/utils/AccessoryUtils.ts @@ -1,10 +1,10 @@ -import { Accessory, Service } from '@homebridge/hap-nodejs' +import type { Accessory, Service } from '@homebridge/hap-nodejs' import { logger } from '@nrchkb/logger' -import AccessoryInformationType from '../types/AccessoryInformationType' -import HAPServiceNodeType from '../types/HAPServiceNodeType' +import type AccessoryInformationType from '../types/AccessoryInformationType' +import type HAPServiceNodeType from '../types/HAPServiceNodeType' -module.exports = function (node: HAPServiceNodeType) { +module.exports = (node: HAPServiceNodeType) => { const HapNodeJS = require('@homebridge/hap-nodejs') const Accessory = HapNodeJS.Accessory const Service = HapNodeJS.Service @@ -12,11 +12,11 @@ module.exports = function (node: HAPServiceNodeType) { const log = logger('NRCHKB', 'AccessoryUtils', node.config.name, node) - const getOrCreate = function ( + const getOrCreate = ( host: Accessory, accessoryInformation: AccessoryInformationType, subtypeUUID: string - ) { + ) => { let accessory: Accessory | undefined const services: Service[] = [] @@ -116,30 +116,21 @@ module.exports = function (node: HAPServiceNodeType) { const revisionRegex = /\d+\.\d+\.\d+/ - if ( - accessoryInformation.firmwareRev && - accessoryInformation.firmwareRev.match(revisionRegex) - ) { + if (accessoryInformation.firmwareRev?.match(revisionRegex)) { accessoryInformationService?.setCharacteristic( Characteristic.FirmwareRevision, accessoryInformation.firmwareRev ) } - if ( - accessoryInformation.hardwareRev && - accessoryInformation.hardwareRev.match(revisionRegex) - ) { + if (accessoryInformation.hardwareRev?.match(revisionRegex)) { accessoryInformationService?.setCharacteristic( Characteristic.HardwareRevision, accessoryInformation.hardwareRev ) } - if ( - accessoryInformation.softwareRev && - accessoryInformation.softwareRev.match(revisionRegex) - ) { + if (accessoryInformation.softwareRev?.match(revisionRegex)) { accessoryInformationService?.setCharacteristic( Characteristic.SoftwareRevision, accessoryInformation.softwareRev @@ -147,6 +138,7 @@ module.exports = function (node: HAPServiceNodeType) { } // Adding new accessory to the bridge. + // biome-ignore lint/style/noNonNullAssertion: accessory is not null here host.addBridgedAccessories([accessory!]) } else { accessoryInformationService = @@ -164,7 +156,7 @@ module.exports = function (node: HAPServiceNodeType) { return accessory } - const onIdentify = function (paired: boolean, callback: () => any) { + const onIdentify = (paired: boolean, callback: () => any) => { if (paired) { log.debug( `Identify called on paired Accessory ${node.accessory.displayName}` @@ -193,7 +185,7 @@ module.exports = function (node: HAPServiceNodeType) { text: 'Identify : 1' }) - setTimeout(function () { + setTimeout(() => { nodes[i].nodeStatusUtils.clearStatus(statusId) }, 3000) diff --git a/src/lib/utils/BridgeUtils.ts b/src/lib/utils/BridgeUtils.ts index 70405c15..6bb81534 100644 --- a/src/lib/utils/BridgeUtils.ts +++ b/src/lib/utils/BridgeUtils.ts @@ -1,15 +1,15 @@ import { logger } from '@nrchkb/logger' -import HAPServiceNodeType from '../types/HAPServiceNodeType' +import type HAPServiceNodeType from '../types/HAPServiceNodeType' import HostType from '../types/HostType' -module.exports = function () { +module.exports = () => { // Publish accessory after the service has been added // BUT ONLY after 5 seconds with no new service have passed // otherwise, our bridge would get published too early during startup and // services being added after that point would be seen as "new" in iOS, // removing all parameters set (Rooms, Groups, Scenes...) - const delayedPublish = function (node: HAPServiceNodeType) { + const delayedPublish = (node: HAPServiceNodeType) => { const log = logger('NRCHKB', 'BridgeUtils', node.config.name, node) if (!node.hostNode.published) { @@ -18,11 +18,12 @@ module.exports = function () { } const hostTypeName = + // biome-ignore lint/suspicious/noDoubleEquals: hostType can be a string or a number node.hostNode.hostType == HostType.BRIDGE ? 'Bridge' : 'Standalone Accessory' - node.publishTimers[node.hostNode.id] = setTimeout(function () { + node.publishTimers[node.hostNode.id] = setTimeout(() => { try { if (!node.hostNode.published) { const published = node.hostNode.publish() @@ -39,7 +40,7 @@ module.exports = function () { node.nodeStatusUtils.setStatus({ fill: 'red', shape: 'ring', - text: 'Error while publishing ' + hostTypeName + text: `Error while publishing ${hostTypeName}` }) } }, 5000) diff --git a/src/lib/utils/CharacteristicUtils.ts b/src/lib/utils/CharacteristicUtils.ts index c7c494ae..bafec9ac 100644 --- a/src/lib/utils/CharacteristicUtils.ts +++ b/src/lib/utils/CharacteristicUtils.ts @@ -1,21 +1,21 @@ import { Characteristic, - CharacteristicProps, - Service + type CharacteristicProps, + type Service } from '@homebridge/hap-nodejs' import { logger } from '@nrchkb/logger' -import HAPServiceConfigType from '../types/HAPServiceConfigType' -import HAPServiceNodeType from '../types/HAPServiceNodeType' +import type HAPServiceConfigType from '../types/HAPServiceConfigType' +import type HAPServiceNodeType from '../types/HAPServiceNodeType' -module.exports = function (node: HAPServiceNodeType) { +module.exports = (node: HAPServiceNodeType) => { const log = logger('NRCHKB', 'CharacteristicUtils', node.config.name, node) const ServiceUtils = require('./ServiceUtils')(node) - const load = function ( + const load = ( service: Service, config: HAPServiceConfigType - ): { [key: string]: CharacteristicProps } { + ): { [key: string]: CharacteristicProps } => { let characteristicProperties: { [key: string]: CharacteristicProps } = {} @@ -37,10 +37,10 @@ module.exports = function (node: HAPServiceNodeType) { // Configure custom characteristic properties for (const key in characteristicProperties) { - if (!characteristicProperties.hasOwnProperty(key)) continue + if (!Object.hasOwn(characteristicProperties, key)) continue const characteristic = service.getCharacteristic( - // @ts-ignore + // @ts-expect-error Characteristic[key] ) @@ -54,7 +54,7 @@ module.exports = function (node: HAPServiceNodeType) { return characteristicProperties } - const subscribeAndGetSupported = function (service: Service) { + const subscribeAndGetSupported = (service: Service) => { const supported: string[] = [] const allCharacteristics = service.characteristics.concat( @@ -71,7 +71,7 @@ module.exports = function (node: HAPServiceNodeType) { service.characteristics ) - allCharacteristics.map((characteristic) => { + allCharacteristics.forEach((characteristic) => { const cKey = characteristic.constructor.name supported.push(cKey) diff --git a/src/lib/utils/CharacteristicUtils2.ts b/src/lib/utils/CharacteristicUtils2.ts index b01e7f78..43be4c36 100644 --- a/src/lib/utils/CharacteristicUtils2.ts +++ b/src/lib/utils/CharacteristicUtils2.ts @@ -1,21 +1,21 @@ import { Characteristic, - CharacteristicProps, - Service + type CharacteristicProps, + type Service } from '@homebridge/hap-nodejs' import { logger } from '@nrchkb/logger' -import HAPService2ConfigType from '../types/HAPService2ConfigType' -import HAPService2NodeType from '../types/HAPService2NodeType' +import type HAPService2ConfigType from '../types/HAPService2ConfigType' +import type HAPService2NodeType from '../types/HAPService2NodeType' -module.exports = function (node: HAPService2NodeType) { +module.exports = (node: HAPService2NodeType) => { const log = logger('NRCHKB', 'CharacteristicUtils', node.config.name, node) const ServiceUtils = require('./ServiceUtils2')(node) - const load = function ( + const load = ( service: Service, config: HAPService2ConfigType - ): { [key: string]: CharacteristicProps } { + ): { [key: string]: CharacteristicProps } => { let characteristicProperties: { [key: string]: CharacteristicProps } = {} @@ -37,10 +37,10 @@ module.exports = function (node: HAPService2NodeType) { // Configure custom characteristic properties for (const key in characteristicProperties) { - if (!characteristicProperties.hasOwnProperty(key)) continue + if (!Object.hasOwn(characteristicProperties, key)) continue const characteristic = service.getCharacteristic( - // @ts-ignore + // @ts-expect-error Characteristic[key] ) @@ -54,7 +54,7 @@ module.exports = function (node: HAPService2NodeType) { return characteristicProperties } - const subscribeAndGetSupported = function (service: Service) { + const subscribeAndGetSupported = (service: Service) => { const supported: string[] = [] const allCharacteristics = service.characteristics.concat( @@ -73,7 +73,7 @@ module.exports = function (node: HAPService2NodeType) { service.characteristics ) - allCharacteristics.map((characteristic) => { + allCharacteristics.forEach((characteristic) => { const cKey = characteristic.constructor.name supported.push(cKey) diff --git a/src/lib/utils/NodeStatusUtils.ts b/src/lib/utils/NodeStatusUtils.ts index 269a109f..bb8c3e0d 100644 --- a/src/lib/utils/NodeStatusUtils.ts +++ b/src/lib/utils/NodeStatusUtils.ts @@ -1,6 +1,6 @@ -import { NodeStatus } from '@node-red/registry' +import type { NodeStatus } from '@node-red/registry' -import NodeType from '../types/NodeType' +import type NodeType from '../types/NodeType' /** * NO_RESPONSE for NO_RESPONSE @@ -31,7 +31,7 @@ export class NodeStatusUtils { setStatus(status: Status, timeout?: number): number { this.node.status(status) - const newStatusId = new Date().getTime() + const newStatusId = Date.now() this.lastStatusId = newStatusId if (typeof status !== 'string') { @@ -67,7 +67,7 @@ export class NodeStatusUtils { if (statusId === this.lastStatusId) { if (timeout) { setTimeout( - function (nodeStatusUtil: NodeStatusUtils) { + (nodeStatusUtil: NodeStatusUtils) => { nodeStatusUtil.clearStatus(statusId) }, timeout, diff --git a/src/lib/utils/ServiceUtils.ts b/src/lib/utils/ServiceUtils.ts index 1d19a2f8..eb706610 100644 --- a/src/lib/utils/ServiceUtils.ts +++ b/src/lib/utils/ServiceUtils.ts @@ -1,28 +1,28 @@ import * as util from 'node:util' import { - Accessory, - ActiveAdaptiveLightingTransition, + type Accessory, + type ActiveAdaptiveLightingTransition, AdaptiveLightingController, AdaptiveLightingControllerMode, - AdaptiveLightingOptions, - Characteristic, - CharacteristicChange, - CharacteristicGetCallback, - CharacteristicSetCallback, - CharacteristicValue, + type AdaptiveLightingOptions, + type Characteristic, + type CharacteristicChange, + type CharacteristicGetCallback, + type CharacteristicSetCallback, + type CharacteristicValue, HAPStatus, HapStatusError, - Service + type Service } from '@homebridge/hap-nodejs' -import { HAPConnection } from '@homebridge/hap-nodejs/dist/lib/util/eventedhttp' +import type { HAPConnection } from '@homebridge/hap-nodejs/dist/lib/util/eventedhttp' import { logger } from '@nrchkb/logger' import NRCHKBError from '../NRCHKBError' -import HAPServiceConfigType from '../types/HAPServiceConfigType' -import HAPServiceNodeType from '../types/HAPServiceNodeType' +import type HAPServiceConfigType from '../types/HAPServiceConfigType' +import type HAPServiceNodeType from '../types/HAPServiceNodeType' -module.exports = function (node: HAPServiceNodeType) { +module.exports = (node: HAPServiceNodeType) => { const log = logger('NRCHKB', 'ServiceUtils', node.config.name, node) const HapNodeJS = require('@homebridge/hap-nodejs') @@ -116,14 +116,14 @@ module.exports = function (node: HAPServiceNodeType) { msg.hap.reachable = node.reachable ?? node.parentNode?.reachable if (msg.hap.reachable === false) { - ;[node, ...(node.childNodes ?? [])].forEach((n) => + ;[node, ...(node.childNodes ?? [])].forEach((n) => { n.nodeStatusUtils.setStatus({ fill: 'red', shape: 'ring', text: 'Not reachable', type: 'NO_RESPONSE' }) - ) + }) } else { msg.hap.newValue = newValue @@ -131,14 +131,14 @@ module.exports = function (node: HAPServiceNodeType) { { fill: 'yellow', shape: 'dot', - text: key + ': ' + newValue + text: `${key}: ${newValue}` }, 3000 ) - node.childNodes?.forEach((n) => + node.childNodes?.forEach((n) => { n.nodeStatusUtils.clearStatusByType('NO_RESPONSE') - ) + }) node.parentNode?.nodeStatusUtils.clearStatusByType('NO_RESPONSE') } @@ -205,7 +205,7 @@ module.exports = function (node: HAPServiceNodeType) { )} on connection ${originator?.sessionID}` ) - if (oldValue != newValue) { + if (oldValue !== newValue) { onValueChange.call( this, allCharacteristics, @@ -220,7 +220,7 @@ module.exports = function (node: HAPServiceNodeType) { } } - const onInput = function (msg: Record) { + const onInput = (msg: Record) => { if (msg.payload) { // payload must be an object const type = typeof msg.payload @@ -250,7 +250,7 @@ module.exports = function (node: HAPServiceNodeType) { node.topic_in = msg.topic ?? '' - Object.keys(msg.payload).map((key: string) => { + Object.keys(msg.payload).forEach((key: string) => { if (node.supported.indexOf(key) < 0) { if ( key === 'AdaptiveLightingController' && @@ -288,12 +288,12 @@ module.exports = function (node: HAPServiceNodeType) { }) } - const onClose = function (removed: boolean, done: () => void) { + const onClose = (removed: boolean, done: () => void) => { const characteristics = node.service.characteristics.concat( node.service.optionalCharacteristics ) - characteristics.forEach(function (characteristic) { + characteristics.forEach((characteristic) => { // cleanup all node specific listeners characteristic.removeListener('get', node.onCharacteristicGet) characteristic.removeListener('set', node.onCharacteristicSet) @@ -321,7 +321,7 @@ module.exports = function (node: HAPServiceNodeType) { done() } - const getOrCreate = function ( + const getOrCreate = ( accessory: Accessory, serviceInformation: { name: string @@ -330,7 +330,7 @@ module.exports = function (node: HAPServiceNodeType) { config: HAPServiceConfigType }, parentService: Service - ) { + ) => { const newService = new Service[serviceInformation.serviceName]( serviceInformation.name, serviceInformation.UUID @@ -385,11 +385,11 @@ module.exports = function (node: HAPServiceNodeType) { return service } - const configureCameraSource = function ( + const configureCameraSource = ( _accessory: Accessory, _service: Service, config: HAPServiceConfigType - ) { + ) => { if (config.cameraConfigSource) { log.debug('Configuring Camera Source') @@ -424,7 +424,7 @@ module.exports = function (node: HAPServiceNodeType) { node.config.parentService ) as HAPServiceNodeType - if (parentNode && parentNode.configured) { + if (parentNode?.configured) { resolve(parentNode) } else { setTimeout(checkAndWait, 1000) @@ -447,9 +447,9 @@ module.exports = function (node: HAPServiceNodeType) { } if ( - msg.hasOwnProperty('payload') && - msg.payload.hasOwnProperty('nrchkb') && - msg.payload.nrchkb.hasOwnProperty('setup') + Object.hasOwn(msg, 'payload') && + Object.hasOwn(msg.payload, 'nrchkb') && + Object.hasOwn(msg.payload.nrchkb, 'setup') ) { node.setupDone = true diff --git a/src/lib/utils/ServiceUtils2.ts b/src/lib/utils/ServiceUtils2.ts index cbc0ac5f..dea49704 100644 --- a/src/lib/utils/ServiceUtils2.ts +++ b/src/lib/utils/ServiceUtils2.ts @@ -1,28 +1,28 @@ import { - Accessory, - Characteristic, - CharacteristicChange, + type Accessory, + type Characteristic, + type CharacteristicChange, CharacteristicEventTypes, - CharacteristicGetCallback, - CharacteristicSetCallback, - CharacteristicValue, + type CharacteristicGetCallback, + type CharacteristicSetCallback, + type CharacteristicValue, HAPStatus, HapStatusError, - Service + type Service } from '@homebridge/hap-nodejs' -import { +import type { HAPConnection, HAPUsername } from '@homebridge/hap-nodejs/dist/lib/util/eventedhttp' -import { SessionIdentifier } from '@homebridge/hap-nodejs/dist/types' +import type { SessionIdentifier } from '@homebridge/hap-nodejs/dist/types' import { logger } from '@nrchkb/logger' import NRCHKBError from '../NRCHKBError' import { Storage } from '../Storage' -import HAPService2ConfigType from '../types/HAPService2ConfigType' -import HAPService2NodeType from '../types/HAPService2NodeType' +import type HAPService2ConfigType from '../types/HAPService2ConfigType' +import type HAPService2NodeType from '../types/HAPService2NodeType' -module.exports = function (node: HAPService2NodeType) { +module.exports = (node: HAPService2NodeType) => { const log = logger('NRCHKB', 'ServiceUtils2', node.config.name, node) const ServiceUtilsLegacy = require('./ServiceUtils')(node) @@ -98,14 +98,14 @@ module.exports = function (node: HAPService2NodeType) { msg.hap.reachable = node.reachable ?? node.parentNode?.reachable if (msg.hap.reachable === false) { - ;[node, ...(node.childNodes ?? [])].forEach((n) => + ;[node, ...(node.childNodes ?? [])].forEach((n) => { n.nodeStatusUtils.setStatus({ fill: 'red', shape: 'ring', text: 'Not reachable', type: 'NO_RESPONSE' }) - ) + }) } else { msg.hap.newValue = newValue @@ -114,15 +114,15 @@ module.exports = function (node: HAPService2NodeType) { fill: 'yellow', shape: 'dot', text: `[${eventObject.name}] ${key}${ - newValue != undefined ? `: ${newValue}` : '' + newValue !== undefined ? `: ${newValue}` : '' }` }, 3000 ) - node.childNodes?.forEach((n) => + node.childNodes?.forEach((n) => { n.nodeStatusUtils.clearStatusByType('NO_RESPONSE') - ) + }) node.parentNode?.nodeStatusUtils.clearStatusByType('NO_RESPONSE') } @@ -152,11 +152,10 @@ module.exports = function (node: HAPService2NodeType) { _context: any, connection?: HAPConnection ) { - const characteristic = this - const oldValue = characteristic.value + const oldValue = this.value const delayedCallback = (value?: any) => { - const newValue = value ?? characteristic.value + const newValue = value ?? this.value if (callback) { try { callback( @@ -169,7 +168,7 @@ module.exports = function (node: HAPService2NodeType) { } output.call( - characteristic, + this, allCharacteristics, { name: CharacteristicEventTypes.GET, @@ -187,7 +186,7 @@ module.exports = function (node: HAPService2NodeType) { }) log.debug( - `Registered callback ${callbackID} for Characteristic ${characteristic.displayName}` + `Registered callback ${callbackID} for Characteristic ${this.displayName}` ) output.call( @@ -239,7 +238,7 @@ module.exports = function (node: HAPService2NodeType) { function (this: Characteristic, change: CharacteristicChange) { const { oldValue, newValue, context, originator, reason } = change - if (oldValue != newValue) { + if (oldValue !== newValue) { output.call( this, allCharacteristics, @@ -253,7 +252,7 @@ module.exports = function (node: HAPService2NodeType) { } } - const onInput = function (msg: HAPServiceMessage) { + const onInput = (msg: HAPServiceMessage) => { if (msg.payload) { // payload must be an object const type = typeof msg.payload @@ -283,7 +282,7 @@ module.exports = function (node: HAPService2NodeType) { node.topic_in = msg.topic ?? '' - Object.keys(msg.payload).map((key: string) => { + Object.keys(msg.payload).forEach((key: string) => { if (node.supported.indexOf(key) < 0) { if (node.config.useEventCallback && Storage.uuid4Validate(key)) { const callbackID = key @@ -332,12 +331,12 @@ module.exports = function (node: HAPService2NodeType) { }) } - const onClose = function (removed: boolean, done: () => void) { + const onClose = (removed: boolean, done: () => void) => { const characteristics = node.service.characteristics.concat( node.service.optionalCharacteristics ) - characteristics.forEach(function (characteristic) { + characteristics.forEach((characteristic) => { // cleanup all node specific listeners characteristic.removeListener('get', node.onCharacteristicGet) characteristic.removeListener('set', node.onCharacteristicSet) @@ -365,7 +364,7 @@ module.exports = function (node: HAPService2NodeType) { done() } - const getOrCreate = function ( + const getOrCreate = ( accessory: Accessory, serviceInformation: { name: string @@ -374,7 +373,7 @@ module.exports = function (node: HAPService2NodeType) { config: HAPService2ConfigType }, parentService: Service - ) { + ) => { const newService = new Service[serviceInformation.serviceName]( serviceInformation.name, serviceInformation.UUID @@ -429,11 +428,11 @@ module.exports = function (node: HAPService2NodeType) { return service } - const configureCameraSource = function ( + const configureCameraSource = ( _accessory: Accessory, _service: Service, config: HAPService2ConfigType - ) { + ) => { if (config.cameraConfigSource) { log.debug('Configuring Camera Source') @@ -468,7 +467,7 @@ module.exports = function (node: HAPService2NodeType) { node.config.parentService ) as HAPService2NodeType - if (parentNode && parentNode.configured) { + if (parentNode?.configured) { resolve(parentNode) } else { setTimeout(checkAndWait, 1000) @@ -491,9 +490,9 @@ module.exports = function (node: HAPService2NodeType) { } if ( - msg.hasOwnProperty('payload') && - msg.payload.hasOwnProperty('nrchkb') && - msg.payload.nrchkb.hasOwnProperty('setup') + Object.hasOwn(msg, 'payload') && + Object.hasOwn(msg.payload, 'nrchkb') && + Object.hasOwn(msg.payload.nrchkb, 'setup') ) { node.setupDone = true diff --git a/src/lib/utils/index.ts b/src/lib/utils/index.ts index 7a09bfb6..c6c8c544 100644 --- a/src/lib/utils/index.ts +++ b/src/lib/utils/index.ts @@ -1,6 +1,6 @@ -import HAPServiceNodeType from '../types/HAPServiceNodeType' +import type HAPServiceNodeType from '../types/HAPServiceNodeType' -module.exports = function (node: HAPServiceNodeType) { +module.exports = (node: HAPServiceNodeType) => { const ServiceUtils = require('./ServiceUtils')(node) const BridgeUtils = require('./BridgeUtils')() const AccessoryUtils = require('./AccessoryUtils')(node) diff --git a/src/nodes/bridge.ts b/src/nodes/bridge.ts index 3a74566e..bfe391ef 100644 --- a/src/nodes/bridge.ts +++ b/src/nodes/bridge.ts @@ -1,5 +1,5 @@ import { logger } from '@nrchkb/logger' -import { NodeAPI } from 'node-red' +import type { NodeAPI } from 'node-red' import HostType from '../lib/types/HostType' diff --git a/src/nodes/nrchkb.ts b/src/nodes/nrchkb.ts index 0e60eb21..b735fc53 100644 --- a/src/nodes/nrchkb.ts +++ b/src/nodes/nrchkb.ts @@ -1,7 +1,7 @@ +import * as path from 'node:path' import { HAPStorage } from '@homebridge/hap-nodejs' import { logger, loggerSetup } from '@nrchkb/logger' -import { NodeAPI } from 'node-red' -import * as path from 'path' +import type { NodeAPI } from 'node-red' import semver from 'semver' import { Storage } from '../lib/Storage' @@ -46,7 +46,7 @@ module.exports = (RED: NodeAPI) => { rootFolder = RED.settings.userDir } else { log.error('RED settings not available') - rootFolder = path.join(require('os').homedir(), '.node-red') + rootFolder = path.join(require('node:os').homedir(), '.node-red') } Storage.init(rootFolder, 'nrchkb').then(() => { diff --git a/src/nodes/service.ts b/src/nodes/service.ts index 9b6ea289..3ae2b44a 100644 --- a/src/nodes/service.ts +++ b/src/nodes/service.ts @@ -1,5 +1,5 @@ import { logger } from '@nrchkb/logger' -import { NodeAPI } from 'node-red' +import type { NodeAPI } from 'node-red' const log = logger('NRCHKB', 'HAPServiceNode') diff --git a/src/nodes/service2.ts b/src/nodes/service2.ts index 02e21666..20c4d914 100644 --- a/src/nodes/service2.ts +++ b/src/nodes/service2.ts @@ -1,5 +1,5 @@ import { logger } from '@nrchkb/logger' -import { NodeAPI } from 'node-red' +import type { NodeAPI } from 'node-red' const log = logger('NRCHKB', 'HAPServiceNode2') diff --git a/src/nodes/standalone.ts b/src/nodes/standalone.ts index ff522c54..7d78ba2c 100644 --- a/src/nodes/standalone.ts +++ b/src/nodes/standalone.ts @@ -1,5 +1,5 @@ import { logger } from '@nrchkb/logger' -import { NodeAPI } from 'node-red' +import type { NodeAPI } from 'node-red' import HostType from '../lib/types/HostType' diff --git a/src/nodes/status.ts b/src/nodes/status.ts index 78ce5e10..9bd260d4 100644 --- a/src/nodes/status.ts +++ b/src/nodes/status.ts @@ -1,10 +1,10 @@ import { Service } from '@homebridge/hap-nodejs' import { logger } from '@nrchkb/logger' -import { NodeAPI } from 'node-red' +import type { NodeAPI } from 'node-red' -import HAPServiceNodeType from '../lib/types/HAPServiceNodeType' -import HAPStatusConfigType from '../lib/types/HAPStatusConfigType' -import HAPStatusNodeType from '../lib/types/HAPStatusNodeType' +import type HAPServiceNodeType from '../lib/types/HAPServiceNodeType' +import type HAPStatusConfigType from '../lib/types/HAPStatusConfigType' +import type HAPStatusNodeType from '../lib/types/HAPStatusNodeType' import { NodeStatusUtils } from '../lib/utils/NodeStatusUtils' const log = logger('NRCHKB', 'HAPStatusNode') @@ -14,23 +14,22 @@ module.exports = (RED: NodeAPI) => { RED.nodes.registerType( 'homekit-status', function (this: HAPStatusNodeType, config: HAPStatusConfigType) { - const self = this - self.config = config - RED.nodes.createNode(self, config) + this.config = config + RED.nodes.createNode(this, config) - self.nodeStatusUtils = new NodeStatusUtils(self) + this.nodeStatusUtils = new NodeStatusUtils(this) try { - self.serviceNode = RED.nodes.getNode( - self.config.serviceNodeId + this.serviceNode = RED.nodes.getNode( + this.config.serviceNodeId ) as HAPServiceNodeType } catch (error: any) { log.error(error) } - self.on('input', (_: Record) => { - if (self.serviceNode) { - self.nodeStatusUtils.setStatus( + this.on('input', (_: Record) => { + if (this.serviceNode) { + this.nodeStatusUtils.setStatus( { fill: 'green', shape: 'dot', @@ -38,12 +37,12 @@ module.exports = (RED: NodeAPI) => { }, 3000 ) - const serializedService = Service.serialize(self.serviceNode.service) - self.send({ + const serializedService = Service.serialize(this.serviceNode.service) + this.send({ payload: serializedService }) } else { - self.nodeStatusUtils.setStatus({ + this.nodeStatusUtils.setStatus({ fill: 'red', shape: 'dot', text: 'Check your config' @@ -51,8 +50,8 @@ module.exports = (RED: NodeAPI) => { } }) - self.on('close', (_: boolean, done: () => void) => { - self.serviceNode = undefined + this.on('close', (_: boolean, done: () => void) => { + this.serviceNode = undefined done() }) } diff --git a/src/test/lib/HAPBridgeNode.test.ts b/src/test/lib/HAPBridgeNode.test.ts index 3c82c3b3..792a8c8e 100644 --- a/src/test/lib/HAPBridgeNode.test.ts +++ b/src/test/lib/HAPBridgeNode.test.ts @@ -9,29 +9,29 @@ loggerSetup({ traceEnabled: false }) -describe('HAPHostNode', function () { +describe('HAPHostNode', () => { // allow longer for this suite (configured via package.json vitest.test.testTimeout) - it('string macify should pass', function () { + it('string macify should pass', () => { const stringToMacify = 'BRIDGE NAME' HAPHostNode.macify(stringToMacify) }) - it('null string macify should fail', function () { + it('null string macify should fail', () => { const stringToMacify = null as unknown as string expect(() => { HAPHostNode.macify(stringToMacify) }).toThrow('nodeId cannot be empty in macify process') }) - it('undefined string macify should fail', function () { + it('undefined string macify should fail', () => { const stringToMacify = undefined as unknown as string expect(() => { HAPHostNode.macify(stringToMacify) }).toThrow('nodeId cannot be empty in macify process') }) - it('empty string macify should fail', function () { + it('empty string macify should fail', () => { const stringToMacify = '' expect(() => { HAPHostNode.macify(stringToMacify) diff --git a/src/test/lib/NodeStatusUtils.test.ts b/src/test/lib/NodeStatusUtils.test.ts index e22a4bcc..6c98e04c 100644 --- a/src/test/lib/NodeStatusUtils.test.ts +++ b/src/test/lib/NodeStatusUtils.test.ts @@ -1,4 +1,4 @@ -import { NodeStatus } from '@node-red/registry' +import type { NodeStatus } from '@node-red/registry' import { afterAll, beforeAll, @@ -18,36 +18,36 @@ class NodeWithStatusMock { } } -describe('NodeStatusUtils', function () { +describe('NodeStatusUtils', () => { let node: NodeWithStatusMock let nodeStatusUtils: NodeStatusUtils - beforeAll(function () { + beforeAll(() => { vi.useFakeTimers() }) - afterAll(function () { + afterAll(() => { vi.useRealTimers() }) - beforeEach(function () { + beforeEach(() => { node = new NodeWithStatusMock() nodeStatusUtils = new NodeStatusUtils(node) }) - it('setStatus', function () { + it('setStatus', () => { nodeStatusUtils.setStatus('test') expect(node.currentStatus).toBe('test') }) - it('clearStatus', function () { + it('clearStatus', () => { nodeStatusUtils.setStatus('test') expect(node.currentStatus).toBe('test') nodeStatusUtils.clearStatus() expect(node.currentStatus).toBe('') }) - it('setStatusWithTimeout', function () { + it('setStatusWithTimeout', () => { nodeStatusUtils.setStatus('test', 2000) expect(node.currentStatus).toBe('test') vi.advanceTimersByTime(1000) @@ -56,7 +56,7 @@ describe('NodeStatusUtils', function () { expect(node.currentStatus).toBe('') }) - it('setStatusWithTimeout - should not clear status with different id', function () { + it('setStatusWithTimeout - should not clear status with different id', () => { nodeStatusUtils.setStatus('test', 2000) expect(node.currentStatus).toBe('test') vi.advanceTimersByTime(1000) @@ -68,14 +68,14 @@ describe('NodeStatusUtils', function () { expect(node.currentStatus).toBe('') }) - it('clearStatusByType - should not clear other type', function () { + it('clearStatusByType - should not clear other type', () => { nodeStatusUtils.setStatus({ text: 'test' }) expect(node.currentStatus).toStrictEqual({ text: 'test' }) nodeStatusUtils.clearStatusByType('NO_RESPONSE') expect(node.currentStatus).toStrictEqual({ text: 'test' }) }) - it('clearStatusByType - should clear same type', function () { + it('clearStatusByType - should clear same type', () => { nodeStatusUtils.setStatus({ text: 'test', type: 'NO_RESPONSE' }) expect(node.currentStatus).toStrictEqual({ text: 'test', diff --git a/src/test/lib/api.test.ts b/src/test/lib/api.test.ts index 9223e5cf..b5237f4c 100644 --- a/src/test/lib/api.test.ts +++ b/src/test/lib/api.test.ts @@ -19,20 +19,16 @@ loggerSetup({ traceEnabled: false }) -describe('api', function () { - beforeAll(function () { - return new Promise((resolve) => helper.startServer(resolve)) - }) +describe('api', () => { + beforeAll(() => new Promise((resolve) => helper.startServer(resolve))) - afterAll(function () { - return new Promise((resolve) => helper.stopServer(resolve)) - }) + afterAll(() => new Promise((resolve) => helper.stopServer(resolve))) - afterEach(function () { + afterEach(() => { helper.unload() }) - it('Service API', async function () { + it('Service API', async () => { await helper.load([nrchkb], []) const response = await helper .request() @@ -42,15 +38,15 @@ describe('api', function () { expect(response.body).toStrictEqual(serviceTypesResponse) }) - describe('stringifyVersion', function () { - it('release', function () { + describe('stringifyVersion', () => { + it('release', () => { const input = '1.2.3' const expected = '1.2.3' const result = API.stringifyVersion(input) expect(result).toBe(expected) }) - it('dev', function () { + it('dev', () => { const input = '1.2.3-dev.45' const expected = '0.123.45' const result = API.stringifyVersion(input) @@ -58,7 +54,7 @@ describe('api', function () { }) }) - it('NRCHKB Info API', async function () { + it('NRCHKB Info API', async () => { await helper.load([nrchkb], []) const xyzVersion = API.stringifyVersion(version) @@ -74,7 +70,7 @@ describe('api', function () { }) }) - it('Accessory API', async function () { + it('Accessory API', async () => { await helper.load([nrchkb], []) const response = await helper .request() diff --git a/src/test/nodes/service.test.ts b/src/test/nodes/service.test.ts index c4a0ee22..c5a08bd9 100644 --- a/src/test/nodes/service.test.ts +++ b/src/test/nodes/service.test.ts @@ -11,6 +11,7 @@ import { } from 'vitest' import { switchServiceBridgeFlow } from '../test-utils/data' + const homekitBridgeNode = require('../../../build/nodes/bridge') const nrchkb = require('../../../build/nodes/nrchkb') const homekitServiceNode = require('../../../build/nodes/service') @@ -21,27 +22,23 @@ loggerSetup({ traceEnabled: false }) -describe('Service Node', function () { - beforeAll(function () { - return new Promise((resolve) => helper.startServer(resolve)) - }) +describe('Service Node', () => { + beforeAll(() => new Promise((resolve) => helper.startServer(resolve))) - afterAll(function () { - return new Promise((resolve) => helper.stopServer(resolve)) - }) + afterAll(() => new Promise((resolve) => helper.stopServer(resolve))) - afterEach(function () { + afterEach(() => { helper.unload() }) - it('should be loaded', async function () { + it('should be loaded', async () => { const { serviceId, flow } = switchServiceBridgeFlow() await helper.load([nrchkb, homekitBridgeNode, homekitServiceNode], flow) const s1 = helper.getNode(serviceId) expect(s1).toHaveProperty('type', 'homekit-service') }) - it('should output ON:true payload', async function () { + it('should output ON:true payload', async () => { const { serviceId, flow } = switchServiceBridgeFlow() await helper.load([nrchkb, homekitBridgeNode, homekitServiceNode], flow) const s1 = helper.getNode(serviceId) @@ -56,13 +53,13 @@ describe('Service Node', function () { }) }) - it('should output ON:false payload', async function () { + it('should output ON:false payload', async () => { const { serviceId, flow } = switchServiceBridgeFlow() await helper.load([nrchkb, homekitBridgeNode, homekitServiceNode], flow) const s1 = helper.getNode(serviceId) await new Promise((resolve) => { - s1.on('input', function (msg: any) { + s1.on('input', (msg: any) => { expect(msg.payload).toHaveProperty('On', false) resolve() }) @@ -71,7 +68,7 @@ describe('Service Node', function () { }) }) - it('should output reachable true', async function () { + it('should output reachable true', async () => { const { serviceId, flow } = switchServiceBridgeFlow() await helper.load([nrchkb, homekitBridgeNode, homekitServiceNode], flow) const s1 = helper.getNode(serviceId) @@ -80,7 +77,7 @@ describe('Service Node', function () { let count = 0 await new Promise((resolve) => { - h1.on('input', function (msg: any) { + h1.on('input', (msg: any) => { if (count === 0) { expect(msg.payload).toHaveProperty('On', true) expect(msg.hap).toHaveProperty('newValue', true) @@ -94,7 +91,7 @@ describe('Service Node', function () { }) }) - it('should output reachable false', async function () { + it('should output reachable false', async () => { const { serviceId, flow } = switchServiceBridgeFlow() await helper.load([nrchkb, homekitBridgeNode, homekitServiceNode], flow) const s1 = helper.getNode(serviceId) @@ -106,7 +103,7 @@ describe('Service Node', function () { .spyOn(s1 as any, 'status') .mockImplementation(() => {}) - h1.on('input', function (msg: any) { + h1.on('input', (msg: any) => { try { expect(msg.payload).toHaveProperty('On', false) expect(msg.hap).toHaveProperty('reachable', false) diff --git a/src/test/nodes/service2.test.ts b/src/test/nodes/service2.test.ts index b27159a7..90204464 100644 --- a/src/test/nodes/service2.test.ts +++ b/src/test/nodes/service2.test.ts @@ -11,6 +11,7 @@ import { } from 'vitest' import { switchService2BridgeFlow } from '../test-utils/data' + const homekitBridgeNode = require('../../../build/nodes/bridge') const nrchkb = require('../../../build/nodes/nrchkb') const homekitService2Node = require('../../../build/nodes/service2') @@ -23,27 +24,23 @@ loggerSetup({ traceEnabled: false }) -describe('Service Node', function () { - beforeAll(function () { - return new Promise((resolve) => helper.startServer(resolve)) - }) +describe('Service Node', () => { + beforeAll(() => new Promise((resolve) => helper.startServer(resolve))) - afterAll(function () { - return new Promise((resolve) => helper.stopServer(resolve)) - }) + afterAll(() => new Promise((resolve) => helper.stopServer(resolve))) - afterEach(function () { + afterEach(() => { helper.unload() }) - it('should be loaded', async function () { + it('should be loaded', async () => { const { serviceId, flow } = switchService2BridgeFlow() await helper.load([nrchkb, homekitBridgeNode, homekitService2Node], flow) const s1 = helper.getNode(serviceId) expect(s1).toHaveProperty('type', 'homekit-service2') }) - it('should output ON:true payload', async function () { + it('should output ON:true payload', async () => { const { serviceId, flow } = switchService2BridgeFlow() await helper.load([nrchkb, homekitBridgeNode, homekitService2Node], flow) const s1 = helper.getNode(serviceId) @@ -58,13 +55,13 @@ describe('Service Node', function () { }) }) - it('should output ON:false payload', async function () { + it('should output ON:false payload', async () => { const { serviceId, flow } = switchService2BridgeFlow() await helper.load([nrchkb, homekitBridgeNode, homekitService2Node], flow) const s1 = helper.getNode(serviceId) await new Promise((resolve) => { - s1.on('input', function (msg: any) { + s1.on('input', (msg: any) => { expect(msg.payload).toHaveProperty('On', false) resolve() }) @@ -73,7 +70,7 @@ describe('Service Node', function () { }) }) - it('should output reachable true', async function () { + it('should output reachable true', async () => { const { serviceId, flow } = switchService2BridgeFlow() await helper.load([nrchkb, homekitBridgeNode, homekitService2Node], flow) const s1 = helper.getNode(serviceId) @@ -82,7 +79,7 @@ describe('Service Node', function () { let count = 0 await new Promise((resolve) => { - h1.on('input', function (msg: any) { + h1.on('input', (msg: any) => { if (count === 0) { expect(msg.payload).toHaveProperty('On', true) expect(msg.hap).toHaveProperty('newValue', true) @@ -96,7 +93,7 @@ describe('Service Node', function () { }) }) - it('should output reachable false', async function () { + it('should output reachable false', async () => { const { serviceId, flow } = switchService2BridgeFlow() await helper.load([nrchkb, homekitBridgeNode, homekitService2Node], flow) const s1 = helper.getNode(serviceId) @@ -107,7 +104,7 @@ describe('Service Node', function () { .spyOn(s1 as any, 'status') .mockImplementation(() => {}) - h1.on('input', function (msg: any) { + h1.on('input', (msg: any) => { try { expect(msg.payload).toHaveProperty('On', false) expect(msg.hap).toHaveProperty('reachable', false) diff --git a/src/test/test-utils/data/switch.service.bridge.flow.ts b/src/test/test-utils/data/switch.service.bridge.flow.ts index 49590980..3b490f44 100644 --- a/src/test/test-utils/data/switch.service.bridge.flow.ts +++ b/src/test/test-utils/data/switch.service.bridge.flow.ts @@ -1,4 +1,4 @@ -import helper from 'node-red-node-test-helper' +import type helper from 'node-red-node-test-helper' export const switchServiceBridgeFlow = () => { const serviceId = `s1.${Date.now()}` diff --git a/src/test/test-utils/data/switch.service2.bridge.flow.ts b/src/test/test-utils/data/switch.service2.bridge.flow.ts index 8a1b92d2..34a8009a 100644 --- a/src/test/test-utils/data/switch.service2.bridge.flow.ts +++ b/src/test/test-utils/data/switch.service2.bridge.flow.ts @@ -1,4 +1,4 @@ -import helper from 'node-red-node-test-helper' +import type helper from 'node-red-node-test-helper' export const switchService2BridgeFlow = () => { const serviceId = `s1.${Date.now()}` diff --git a/tsconfig.json b/tsconfig.json index 29c5b94a..0477607c 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -2,7 +2,7 @@ "compilerOptions": { "target": "es6", "module": "commonjs", - "lib": ["es2020.string"], + "lib": ["ES2023"], "skipLibCheck": true, "allowJs": true, "checkJs": false, From 189c951c3bc9a43d5a71971eeb7e85b281dd88e2 Mon Sep 17 00:00:00 2001 From: Shaquu Date: Mon, 24 Nov 2025 00:03:15 +0100 Subject: [PATCH 06/14] Bump version to 2.0.0-dev.2 in package.json --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 01238f55..d428baf8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "node-red-contrib-homekit-bridged", - "version": "2.0.0-dev.1", + "version": "2.0.0-dev.2", "description": "Node-RED nodes to simulate Apple HomeKit devices.", "main": "build/nodes/nrchkb.js", "scripts": { From 65a6a64edf27f2c6011918073591c1f5fd4567f3 Mon Sep 17 00:00:00 2001 From: Shaquu Date: Mon, 24 Nov 2025 00:05:47 +0100 Subject: [PATCH 07/14] Improve adaptive lighting logging --- package-lock.json | 4 ++-- package.json | 2 +- src/lib/utils/ServiceUtils.ts | 3 ++- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 6160aeee..5883358e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "node-red-contrib-homekit-bridged", - "version": "2.0.0-dev.1", + "version": "2.0.0-dev.3", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "node-red-contrib-homekit-bridged", - "version": "2.0.0-dev.1", + "version": "2.0.0-dev.3", "license": "Apache-2.0", "dependencies": { "@homebridge/hap-nodejs": "2.0.2", diff --git a/package.json b/package.json index d428baf8..25a9929d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "node-red-contrib-homekit-bridged", - "version": "2.0.0-dev.2", + "version": "2.0.0-dev.3", "description": "Node-RED nodes to simulate Apple HomeKit devices.", "main": "build/nodes/nrchkb.js", "scripts": { diff --git a/src/lib/utils/ServiceUtils.ts b/src/lib/utils/ServiceUtils.ts index eb706610..976a4a95 100644 --- a/src/lib/utils/ServiceUtils.ts +++ b/src/lib/utils/ServiceUtils.ts @@ -487,7 +487,8 @@ module.exports = (node: HAPServiceNodeType) => { : undefined } - log.trace(`Configuring Adaptive Lighting with options: ${options}`) + log.trace(`Configuring Adaptive Lighting with options:`) + log.trace(JSON.stringify(options)) const adaptiveLightingController = new AdaptiveLightingController( node.service, From f84e90d5d188e8831605a1bf8977d00238e5fc32 Mon Sep 17 00:00:00 2001 From: Shaquu Date: Mon, 24 Nov 2025 00:12:59 +0100 Subject: [PATCH 08/14] Attempt to fix tests run in CI --- .github/workflows/publish-dev.yml | 2 +- .github/workflows/publish.yml | 2 +- .github/workflows/tests.yml | 2 +- package-lock.json | 4 ++-- package.json | 3 ++- 5 files changed, 7 insertions(+), 6 deletions(-) diff --git a/.github/workflows/publish-dev.yml b/.github/workflows/publish-dev.yml index d721b4f5..709a0771 100644 --- a/.github/workflows/publish-dev.yml +++ b/.github/workflows/publish-dev.yml @@ -16,7 +16,7 @@ jobs: - run: | npm ci npm run build - npm run test + npm run test:ci publish-npm: needs: build diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index a9cb6519..9b1a8405 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -16,7 +16,7 @@ jobs: - run: | npm ci npm run build - npm run test + npm run test:ci publish-npm: needs: build diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 323038e8..30d00a96 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -19,6 +19,6 @@ jobs: npm ci npm run lint npm run build - npm run test + npm run test:ci env: CI: true diff --git a/package-lock.json b/package-lock.json index 5883358e..0552f698 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "node-red-contrib-homekit-bridged", - "version": "2.0.0-dev.3", + "version": "2.0.0-dev.4", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "node-red-contrib-homekit-bridged", - "version": "2.0.0-dev.3", + "version": "2.0.0-dev.4", "license": "Apache-2.0", "dependencies": { "@homebridge/hap-nodejs": "2.0.2", diff --git a/package.json b/package.json index 25a9929d..d6d725c0 100644 --- a/package.json +++ b/package.json @@ -1,12 +1,13 @@ { "name": "node-red-contrib-homekit-bridged", - "version": "2.0.0-dev.3", + "version": "2.0.0-dev.4", "description": "Node-RED nodes to simulate Apple HomeKit devices.", "main": "build/nodes/nrchkb.js", "scripts": { "build": "npm run clean && tsc", "clean": "del-cli \"build/lib\" \"build/**/*.js\"", "test": "vitest run", + "test:ci": "vitest run --no-file-parallelism", "test:watch": "vitest", "format": "npx @biomejs/biome check --write", "lint": "npx @biomejs/biome check", From 96a6fafaf2aa4954342484596f59586c9d97ccd3 Mon Sep 17 00:00:00 2001 From: GogoVega <92022724+GogoVega@users.noreply.github.com> Date: Mon, 24 Nov 2025 14:42:50 +0100 Subject: [PATCH 09/14] Fix typo and run test on push --- .github/workflows/tests.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 30d00a96..1db80f0f 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -1,13 +1,15 @@ name: Tests -on: [ pull_request ] +on: + push: + pull_request: jobs: build: runs-on: ${{ matrix.os }} strategy: matrix: - node_version: [ 20, 22, 24 ] + node-version: [ 20, 22, 24 ] os: [ ubuntu-latest, windows-latest, macOS-latest ] steps: - uses: actions/checkout@v4 From c08ad48c7b74bfa1e67366c8ec980d1d2d9bc3e9 Mon Sep 17 00:00:00 2001 From: GogoVega <92022724+GogoVega@users.noreply.github.com> Date: Mon, 24 Nov 2025 15:08:58 +0100 Subject: [PATCH 10/14] Wait for resolution of `afterEach` promises --- src/test/lib/api.test.ts | 2 +- src/test/nodes/service.test.ts | 2 +- src/test/nodes/service2.test.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/test/lib/api.test.ts b/src/test/lib/api.test.ts index b5237f4c..676eb3d2 100644 --- a/src/test/lib/api.test.ts +++ b/src/test/lib/api.test.ts @@ -25,7 +25,7 @@ describe('api', () => { afterAll(() => new Promise((resolve) => helper.stopServer(resolve))) afterEach(() => { - helper.unload() + return helper.unload() }) it('Service API', async () => { diff --git a/src/test/nodes/service.test.ts b/src/test/nodes/service.test.ts index c5a08bd9..7ed82248 100644 --- a/src/test/nodes/service.test.ts +++ b/src/test/nodes/service.test.ts @@ -28,7 +28,7 @@ describe('Service Node', () => { afterAll(() => new Promise((resolve) => helper.stopServer(resolve))) afterEach(() => { - helper.unload() + return helper.unload() }) it('should be loaded', async () => { diff --git a/src/test/nodes/service2.test.ts b/src/test/nodes/service2.test.ts index 90204464..08afb482 100644 --- a/src/test/nodes/service2.test.ts +++ b/src/test/nodes/service2.test.ts @@ -30,7 +30,7 @@ describe('Service Node', () => { afterAll(() => new Promise((resolve) => helper.stopServer(resolve))) afterEach(() => { - helper.unload() + return helper.unload() }) it('should be loaded', async () => { From ad37cb1b168781ed33a38a9142f2fcf8d4dfe150 Mon Sep 17 00:00:00 2001 From: GogoVega <92022724+GogoVega@users.noreply.github.com> Date: Mon, 24 Nov 2025 15:35:52 +0100 Subject: [PATCH 11/14] Disable `fail-fast` --- .github/workflows/tests.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 1db80f0f..a46e5530 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -8,6 +8,7 @@ jobs: build: runs-on: ${{ matrix.os }} strategy: + fail-fast: false matrix: node-version: [ 20, 22, 24 ] os: [ ubuntu-latest, windows-latest, macOS-latest ] From 710af6e1bdc376fbb186402a5fcb2543e54982fb Mon Sep 17 00:00:00 2001 From: GogoVega <92022724+GogoVega@users.noreply.github.com> Date: Mon, 24 Nov 2025 15:46:43 +0100 Subject: [PATCH 12/14] Register `nrchkb` node synchronously --- src/nodes/nrchkb.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/nodes/nrchkb.ts b/src/nodes/nrchkb.ts index b735fc53..49c4e06c 100644 --- a/src/nodes/nrchkb.ts +++ b/src/nodes/nrchkb.ts @@ -63,14 +63,14 @@ module.exports = (RED: NodeAPI) => { log.error('node-red restart highly recommended') log.trace(error) } + }) - // Experimental feature - if (process.env.NRCHKB_EXPERIMENTAL === 'true') { - log.debug('Registering nrchkb type') + // Experimental feature + if (process.env.NRCHKB_EXPERIMENTAL === 'true') { + log.debug('Registering nrchkb type') - RED.nodes.registerType('nrchkb', function (this: any, config) { - RED.nodes.createNode(this, config) - }) - } - }) + RED.nodes.registerType('nrchkb', function (this: any, config) { + RED.nodes.createNode(this, config) + }) + } } From fa9ed839bd6b8ceff9770dc5b14273b49d7f2007 Mon Sep 17 00:00:00 2001 From: Shaquu Date: Mon, 24 Nov 2025 22:58:54 +0100 Subject: [PATCH 13/14] Upgraded husky configuration --- .github/workflows/codeql-analysis.yml | 3 +++ .github/workflows/publish-dev.yml | 3 +++ .github/workflows/publish.yml | 3 +++ .github/workflows/tests.yml | 3 +++ .husky/pre-commit | 10 +--------- package.json | 2 +- 6 files changed, 14 insertions(+), 10 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index ed13afb1..da62bbc1 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -11,6 +11,9 @@ # name: "CodeQL" +env: + HUSKY: 0 + on: push: branches: [ master, dev ] diff --git a/.github/workflows/publish-dev.yml b/.github/workflows/publish-dev.yml index 709a0771..06c3fb79 100644 --- a/.github/workflows/publish-dev.yml +++ b/.github/workflows/publish-dev.yml @@ -1,5 +1,8 @@ name: Dev publish +env: + HUSKY: 0 + on: push: branches: diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 9b1a8405..802a66a8 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -1,5 +1,8 @@ name: Release publish +env: + HUSKY: 0 + on: push: branches: diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index a46e5530..89eddaa2 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -1,5 +1,8 @@ name: Tests +env: + HUSKY: 0 + on: push: pull_request: diff --git a/.husky/pre-commit b/.husky/pre-commit index f6a428cb..ba1caafd 100644 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1,9 +1 @@ -#!/usr/bin/env sh - -# .husky/pre-commit -# ... -[ -n "$CI" ] && exit 0 - -. "$(dirname -- "$0")/_/husky.sh" - -npm run format && npm test +npm run format && npm test \ No newline at end of file diff --git a/package.json b/package.json index d6d725c0..ab653549 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "test:watch": "vitest", "format": "npx @biomejs/biome check --write", "lint": "npx @biomejs/biome check", - "prepare": "husky install" + "prepare": "husky || true" }, "repository": { "type": "git", From f1b48a59b24ea3845715c909e25063ad0301103c Mon Sep 17 00:00:00 2001 From: Shaquu Date: Mon, 24 Nov 2025 23:32:30 +0100 Subject: [PATCH 14/14] New Camera API. --- package-lock.json | 4 +- package.json | 2 +- src/lib/api.ts | 4 +- src/lib/camera/CameraControl.ts | 112 +++++ src/lib/camera/CameraDelegate.ts | 594 +++++++++++++++++++++++++++ src/lib/camera/MP4StreamingServer.ts | 182 ++++++++ src/lib/utils/ServiceUtils.ts | 9 +- src/lib/utils/ServiceUtils2.ts | 9 +- 8 files changed, 903 insertions(+), 13 deletions(-) create mode 100644 src/lib/camera/CameraControl.ts create mode 100644 src/lib/camera/CameraDelegate.ts create mode 100644 src/lib/camera/MP4StreamingServer.ts diff --git a/package-lock.json b/package-lock.json index 0552f698..97c2cca8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "node-red-contrib-homekit-bridged", - "version": "2.0.0-dev.4", + "version": "2.0.0-dev.5", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "node-red-contrib-homekit-bridged", - "version": "2.0.0-dev.4", + "version": "2.0.0-dev.5", "license": "Apache-2.0", "dependencies": { "@homebridge/hap-nodejs": "2.0.2", diff --git a/package.json b/package.json index ab653549..ee656c2d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "node-red-contrib-homekit-bridged", - "version": "2.0.0-dev.4", + "version": "2.0.0-dev.5", "description": "Node-RED nodes to simulate Apple HomeKit devices.", "main": "build/nodes/nrchkb.js", "scripts": { diff --git a/src/lib/api.ts b/src/lib/api.ts index 39494a08..ff8eee0a 100644 --- a/src/lib/api.ts +++ b/src/lib/api.ts @@ -108,7 +108,7 @@ module.exports = (RED: NodeAPI) => { log.debug('Could not match dev version') } } catch (e) { - console.error(e) + log.error(e as any) } } else if (releaseVersionFound) { try { @@ -120,7 +120,7 @@ module.exports = (RED: NodeAPI) => { log.debug('Could not match release version') } } catch (e) { - console.error(e) + log.error(e as any) } } else { log.debug('Bad version format') diff --git a/src/lib/camera/CameraControl.ts b/src/lib/camera/CameraControl.ts new file mode 100644 index 00000000..38b5757f --- /dev/null +++ b/src/lib/camera/CameraControl.ts @@ -0,0 +1,112 @@ +import { + type Accessory, + AudioBitrate, + AudioRecordingCodecType, + AudioRecordingSamplerate, + CameraController, + H264Level, + H264Profile, + MediaContainerType, + SRTPCryptoSuites, + VideoCodecType +} from '@homebridge/hap-nodejs' +import type CameraConfigType from '../types/CameraConfigType' +import { CameraDelegate } from './CameraDelegate' + +export const configureCamera = ( + accessory: Accessory, + config?: CameraConfigType +) => { + const streamDelegate = new CameraDelegate(accessory, config) + + const cameraController = new CameraController({ + cameraStreamCount: Math.max(1, config?.cameraConfigMaxStreams || 2), // default 2 + delegate: streamDelegate, + + streamingOptions: { + // srtp: true, // legacy option which will just enable AES_CM_128_HMAC_SHA1_80 (can still be used though) + + // iOS does not support NONE just there for testing with Wireshark, for example + supportedCryptoSuites: [ + SRTPCryptoSuites.NONE, + SRTPCryptoSuites.AES_CM_128_HMAC_SHA1_80 + ], + video: { + codec: { + profiles: [H264Profile.BASELINE, H264Profile.MAIN, H264Profile.HIGH], + levels: [H264Level.LEVEL3_1, H264Level.LEVEL3_2, H264Level.LEVEL4_0] + }, + resolutions: (() => { + // keep defaults but constrain to configured max width/height/fps if provided + const maxW = config?.cameraConfigMaxWidth + const maxH = config?.cameraConfigMaxHeight + const maxFps = config?.cameraConfigMaxFPS + const defaults: [number, number, number][] = [ + [1920, 1080, 30], + [1280, 960, 30], + [1280, 720, 30], + [1024, 768, 30], + [640, 480, 30], + [640, 360, 30], + [480, 360, 30], + [480, 270, 30], + [320, 240, 30], + [320, 240, 15], + [320, 180, 30] + ] + return defaults + .filter(([w, h]) => (!maxW || w <= maxW) && (!maxH || h <= maxH)) + .map(([w, h, f]) => [w, h, Math.min(f, maxFps || f)]) + })() + } + // audio options intentionally omitted here; delegate will honor config for RTP audio path + }, + recording: { + options: { + prebufferLength: 4000, + mediaContainerConfiguration: { + type: MediaContainerType.FRAGMENTED_MP4, + fragmentLength: 4000 + }, + video: { + type: VideoCodecType.H264, + parameters: { + profiles: [H264Profile.HIGH], + levels: [H264Level.LEVEL4_0] + }, + resolutions: [ + [320, 180, 30], + [320, 240, 15], + [320, 240, 30], + [480, 270, 30], + [480, 360, 30], + [640, 360, 30], + [640, 480, 30], + [1280, 720, 30], + [1280, 960, 30], + [1920, 1080, 30], + [1600, 1200, 30] + ] + }, + audio: { + codecs: { + type: AudioRecordingCodecType.AAC_ELD, + audioChannels: 1, + samplerate: AudioRecordingSamplerate.KHZ_48, + bitrateMode: AudioBitrate.VARIABLE + } + } + }, + + delegate: streamDelegate + }, + + sensors: { + motion: true, + occupancy: true + } + }) + streamDelegate.controller = cameraController + + accessory.configureController(cameraController) +} diff --git a/src/lib/camera/CameraDelegate.ts b/src/lib/camera/CameraDelegate.ts new file mode 100644 index 00000000..5c4ed379 --- /dev/null +++ b/src/lib/camera/CameraDelegate.ts @@ -0,0 +1,594 @@ +// Based on https://github.com/homebridge/HAP-NodeJS/blob/latest/src/accessories/Camera_accessory.ts + +import assert from 'node:assert' +import { type ChildProcess, spawn } from 'node:child_process' +import { + type Accessory, + AudioRecordingCodecType, + AudioRecordingSamplerate, + CameraController, + type CameraRecordingConfiguration, + type CameraRecordingDelegate, + type CameraStreamingDelegate, + Characteristic, + H264Level, + H264Profile, + type HDSProtocolSpecificErrorReason, + type PrepareStreamCallback, + type PrepareStreamRequest, + type PrepareStreamResponse, + type RecordingPacket, + Service, + type SnapshotRequest, + type SnapshotRequestCallback, + SRTPCryptoSuites, + type StreamingRequest, + type StreamRequestCallback, + StreamRequestTypes, + type StreamSessionIdentifier, + VideoCodecType, + type VideoInfo +} from '@homebridge/hap-nodejs' +import { logger } from '@nrchkb/logger' +import type CameraConfigType from '../types/CameraConfigType' +import { MP4StreamingServer } from './MP4StreamingServer' + +type SessionInfo = { + address: string // address of the HAP controller + + videoPort: number // port of the controller + localVideoPort: number + videoCryptoSuite: SRTPCryptoSuites // should be saved if multiple suites are supported + videoSRTP: Buffer // key and salt concatenated + videoSSRC: number // rtp synchronisation source + + /* Won't be saved as audio is not supported by this example + audioPort: number, + audioCryptoSuite: SRTPCryptoSuites, + audioSRTP: Buffer, + audioSSRC: number, + */ +} + +type OngoingSession = { + localVideoPort: number + process: ChildProcess +} + +const FFMPEGH264ProfileNames = ['baseline', 'main', 'high'] +const FFMPEGH264LevelNames = ['3.1', '3.2', '4.0'] + +const ports = new Set() + +function getPort(): number { + for (let i = 5011; ; i++) { + if (!ports.has(i)) { + ports.add(i) + return i + } + } +} + +export class CameraDelegate + implements CameraStreamingDelegate, CameraRecordingDelegate +{ + private ffmpegDebugOutput = false + + private log = logger('NRCHKB', 'CameraDelegate') + + controller?: CameraController + + // keep track of sessions + pendingSessions: Record = {} + ongoingSessions: Record = {} + + // minimal secure video properties. + configuration?: CameraRecordingConfiguration + handlingStreamingRequest = false + server?: MP4StreamingServer + + constructor( + private accessory: Accessory, + private config?: CameraConfigType + ) { + // refine logger with accessory name if available + try { + const name = + accessory?.displayName || accessory?.UUID || 'UnknownAccessory' + this.log = logger('NRCHKB', 'CameraDelegate', name) + } catch (_) { + // keep default logger + } + } + + handleSnapshotRequest( + request: SnapshotRequest, + callback: SnapshotRequestCallback + ): void { + // Prefer configured still image source, else use main source; fallback to testsrc + const ffmpegPath = this.config?.cameraConfigVideoProcessor || 'ffmpeg' + const stillSource = this.config?.cameraConfigStillImageSource?.trim() + const mainSource = this.config?.cameraConfigSource?.trim() + let imageSource: string + if (stillSource) { + imageSource = stillSource + } else if (mainSource) { + imageSource = mainSource + } else { + imageSource = `-f lavfi -i testsrc=s=${request.width}x${request.height}` + } + + const ffmpegCommand = `${imageSource} -t 1 -s ${request.width}x${request.height} -f image2 -` + const ffmpeg = spawn(ffmpegPath, ffmpegCommand.split(' '), { + env: process.env + }) + + const snapshotBuffers: Buffer[] = [] + + ffmpeg.stdout.on('data', (data) => snapshotBuffers.push(data)) + ffmpeg.stderr.on('data', (data) => { + if (this.ffmpegDebugOutput || this.config?.cameraConfigDebug) { + this.log.debug(`SNAPSHOT: ${String(data)}`) + } + }) + + ffmpeg.on('exit', (code, signal) => { + if (signal) { + this.log.error(`Snapshot process was killed with signal: ${signal}`) + callback(new Error(`killed with signal ${signal}`)) + } else if (code === 0) { + this.log.debug( + `Successfully captured snapshot at ${request.width}x${request.height}` + ) + callback(undefined, Buffer.concat(snapshotBuffers)) + } else { + this.log.error(`Snapshot process exited with code ${code}`) + callback(new Error(`Snapshot process exited with code ${code}`)) + } + }) + } + + // called when iOS request rtp setup + prepareStream( + request: PrepareStreamRequest, + callback: PrepareStreamCallback + ): void { + const sessionId: StreamSessionIdentifier = request.sessionID + const targetAddress = request.targetAddress + + const video = request.video + + const videoCryptoSuite = video.srtpCryptoSuite // could be used to support multiple crypto suite (or support no suite for debugging) + const videoSrtpKey = video.srtp_key + const videoSrtpSalt = video.srtp_salt + + const videoSSRC = CameraController.generateSynchronisationSource() + + const localPort = getPort() + + const sessionInfo: SessionInfo = { + address: targetAddress, + + videoPort: video.port, + localVideoPort: localPort, + videoCryptoSuite: videoCryptoSuite, + videoSRTP: Buffer.concat([videoSrtpKey, videoSrtpSalt]), + videoSSRC: videoSSRC + } + + const response: PrepareStreamResponse = { + video: { + port: localPort, + ssrc: videoSSRC, + + srtp_key: videoSrtpKey, + srtp_salt: videoSrtpSalt + } + // audio is omitted as we do not support audio in this example + } + + this.pendingSessions[sessionId] = sessionInfo + callback(undefined, response) + } + + // called when the iOS device asks stream to start/stop/reconfigure + handleStreamRequest( + request: StreamingRequest, + callback: StreamRequestCallback + ): void { + const sessionId = request.sessionID + + switch (request.type) { + case StreamRequestTypes.START: { + const sessionInfo = this.pendingSessions[sessionId] + + const video: VideoInfo = request.video + + const profile = FFMPEGH264ProfileNames[video.profile] + const level = FFMPEGH264LevelNames[video.level] + const width = video.width + const height = video.height + let fps = video.fps + + const payloadType = video.pt + let maxBitrate = video.max_bit_rate + // eslint-disable-next-line @typescript-eslint/no-unused-vars + // const rtcpInterval = video.rtcp_interval // usually 0.5 + const mtu = video.mtu // maximum transmission unit + + const address = sessionInfo.address + const videoPort = sessionInfo.videoPort + const localVideoPort = sessionInfo.localVideoPort + const ssrc = sessionInfo.videoSSRC + const cryptoSuite = sessionInfo.videoCryptoSuite + const videoSRTP = sessionInfo.videoSRTP.toString('base64') + + // Merge UI config for backward compatibility + const cfg = this.config + const ffmpegPath = cfg?.cameraConfigVideoProcessor || 'ffmpeg' + const source = + cfg?.cameraConfigSource || + `-f lavfi -i testsrc=s=${width}x${height}:r=${fps}` + const vcodec = cfg?.cameraConfigVideoCodec || 'libx264' + const additional = cfg?.cameraConfigAdditionalCommandLine?.trim() + const mapvideo = cfg?.cameraConfigMapVideo || '0:0' + const mapaudio = cfg?.cameraConfigMapAudio || '0:1' + // const packetsize = cfg?.cameraConfigPacketSize || 1316 + const maxConfigBitrate = cfg?.cameraConfigMaxBitrate + if ( + maxConfigBitrate && + maxConfigBitrate > 0 && + maxConfigBitrate < maxBitrate + ) { + maxBitrate = maxConfigBitrate + } + const maxConfigFps = cfg?.cameraConfigMaxFPS + if (maxConfigFps && maxConfigFps > 0 && maxConfigFps < fps) { + fps = maxConfigFps + } + + const vf: string[] = [] + if ( + cfg?.cameraConfigVideoFilter !== null && + cfg?.cameraConfigVideoFilter !== undefined && + cfg?.cameraConfigVideoFilter !== '' + ) { + vf.push(cfg.cameraConfigVideoFilter) + if (cfg.cameraConfigHorizontalFlip) vf.push('hflip') + if (cfg.cameraConfigVerticalFlip) vf.push('vflip') + } + + this.log.debug( + `Starting video stream (${width}x${height}, ${fps} fps, ${maxBitrate} kbps, ${mtu} mtu)...` + ) + + let videoffmpegCommand = + `${source} -map ${mapvideo} -vcodec ${vcodec} -pix_fmt yuv420p -r ${fps} -f rawvideo ` + + `${additional ? `${additional} ` : ''}` + + `${vf.length > 0 ? `-vf ${vf.join(',')} ` : ''}` + + `-b:v ${maxBitrate}k -bufsize ${maxBitrate}k -maxrate ${maxBitrate}k ` + + `-profile:v ${profile} -level:v ${level} ` + + `-payload_type ${payloadType} -ssrc ${ssrc} -f rtp ` + + if (cryptoSuite !== SRTPCryptoSuites.NONE) { + let suite: string + switch (cryptoSuite) { + case SRTPCryptoSuites.AES_CM_128_HMAC_SHA1_80: // actually ffmpeg just supports AES_CM_128_HMAC_SHA1_80 + suite = 'AES_CM_128_HMAC_SHA1_80' + break + case SRTPCryptoSuites.AES_CM_256_HMAC_SHA1_80: + suite = 'AES_CM_256_HMAC_SHA1_80' + break + } + + videoffmpegCommand += `-srtp_out_suite ${suite} -srtp_out_params ${videoSRTP} s` + } + + videoffmpegCommand += `rtp://${address}:${videoPort}?rtcpport=${videoPort}&localrtcpport=${localVideoPort}&pkt_size=${cfg?.cameraConfigPacketSize || mtu}` + + // Optional Audio stream (legacy compatibility) + const audioEnabled = + (this.config?.cameraConfigAudio as any) === true || + this.config?.cameraConfigAudio === 'true' + let audioffmpegCommand = '' + if (audioEnabled) { + const acodec = cfg?.cameraConfigAudioCodec || 'libfdk_aac' + const abitrate = 32 // legacy default + const asamplerate = 16 // kHz legacy default + const apayloadType = 110 + // const audioSRTP = sessionInfo.videoSRTP.toString('base64') // placeholder, audio not negotiated separately in this simplified impl + audioffmpegCommand = + ` -map ${mapaudio} -acodec ${acodec} -profile:a aac_eld -flags +global_header -f null -ar ${asamplerate}k -b:a ${abitrate}k -bufsize ${abitrate}k -ac 1 ` + + `-payload_type ${apayloadType} ` + // not appending RTP audio out url here due to missing audio session params in this example + } + + if (this.ffmpegDebugOutput || this.config?.cameraConfigDebug) { + this.log.debug( + `FFMPEG command: ${ffmpegPath} ${videoffmpegCommand}${audioffmpegCommand}` + ) + } + + const ffmpegVideo = spawn( + ffmpegPath, + (videoffmpegCommand + audioffmpegCommand).split(' '), + { + env: process.env + } + ) + + let started = false + ffmpegVideo.stderr.on('data', (data: Buffer) => { + this.log.debug(data.toString('utf8')) + if (!started) { + started = true + this.log.debug('FFMPEG: received first frame') + + callback() // remember to execute a callback once set up + } + + if (this.ffmpegDebugOutput || this.config?.cameraConfigDebug) { + this.log.debug(`VIDEO: ${String(data)}`) + } + }) + ffmpegVideo.on('error', (error) => { + this.log.error( + `[Video] Failed to start video stream: ${error.message}` + ) + callback(new Error('ffmpeg process creation failed!')) + }) + ffmpegVideo.on('exit', (code, signal) => { + const message = + '[Video] ffmpeg exited with code: ' + + code + + ' and signal: ' + + signal + + if (code == null || code === 255) { + this.log.debug(`${message} (Video stream stopped!)`) + } else { + this.log.error(`${message} (error)`) + + if (!started) { + callback(new Error(message)) + } else { + this.controller?.forceStopStreamingSession(sessionId) + } + } + }) + + this.ongoingSessions[sessionId] = { + localVideoPort: localVideoPort, + process: ffmpegVideo + } + delete this.pendingSessions[sessionId] + + break + } + case StreamRequestTypes.RECONFIGURE: + // not supported by this example + this.log.debug( + 'Received (unsupported) request to reconfigure to: ' + + JSON.stringify(request.video) + ) + callback() + break + case StreamRequestTypes.STOP: { + const ongoingSession = this.ongoingSessions[sessionId] + if (!ongoingSession) { + callback() + break + } + + ports.delete(ongoingSession.localVideoPort) + + try { + ongoingSession.process.kill('SIGKILL') + } catch (e) { + this.log.error('Error occurred terminating the video process!') + this.log.error(String(e)) + } + + delete this.ongoingSessions[sessionId] + + this.log.debug('Stopped streaming session!') + callback() + break + } + } + } + + updateRecordingActive(active: boolean): void { + // we haven't implemented a prebuffer + this.log.debug(`Recording active set to ${active}`) + } + + updateRecordingConfiguration( + configuration: CameraRecordingConfiguration | undefined + ): void { + this.configuration = configuration + this.log.debug(JSON.stringify(configuration)) + } + + /** + * This is a very minimal, very experimental example of how to implement fmp4 streaming with a + * CameraController supporting HomeKit Secure Video. + * + * An ideal implementation would diverge from this in the following ways: + * * It would implement a prebuffer and respect the recording `active` characteristic for that. + * * It would start to immediately record after a trigger event occurred and not just + * when the HomeKit Controller requests it (see the documentation of `CameraRecordingDelegate`). + */ + // eslint-disable-next-line @typescript-eslint/no-unused-vars + async *handleRecordingStreamRequest( + _streamId: number + ): AsyncGenerator { + assert(!!this.configuration) + + /** + * With this flag you can control how the generator reacts to a reset to the motion trigger. + * If set to true, the generator will send a proper endOfStream if the motion stops. + * If set to false, the generator will run till the HomeKit Controller closes the stream. + * + * Note: In a real implementation you would most likely introduce a bit of a delay. + */ + const STOP_AFTER_MOTION_STOP = false + + this.handlingStreamingRequest = true + + assert(this.configuration.videoCodec.type === VideoCodecType.H264) + + const profile = + this.configuration.videoCodec.parameters.profile === H264Profile.HIGH + ? 'high' + : this.configuration.videoCodec.parameters.profile === H264Profile.MAIN + ? 'main' + : 'baseline' + + const level = + this.configuration.videoCodec.parameters.level === H264Level.LEVEL4_0 + ? '4.0' + : this.configuration.videoCodec.parameters.level === H264Level.LEVEL3_2 + ? '3.2' + : '3.1' + + const videoArgs: Array = [ + '-an', + '-sn', + '-dn', + '-codec:v', + 'libx264', + '-pix_fmt', + 'yuv420p', + + '-profile:v', + profile, + '-level:v', + level, + '-b:v', + `${this.configuration.videoCodec.parameters.bitRate}k`, + '-force_key_frames', + `expr:eq(t,n_forced*${this.configuration.videoCodec.parameters.iFrameInterval / 1000})`, + '-r', + this.configuration.videoCodec.resolution[2].toString() + ] + + let samplerate: string + switch (this.configuration.audioCodec.samplerate) { + case AudioRecordingSamplerate.KHZ_8: + samplerate = '8' + break + case AudioRecordingSamplerate.KHZ_16: + samplerate = '16' + break + case AudioRecordingSamplerate.KHZ_24: + samplerate = '24' + break + case AudioRecordingSamplerate.KHZ_32: + samplerate = '32' + break + case AudioRecordingSamplerate.KHZ_44_1: + samplerate = '44.1' + break + case AudioRecordingSamplerate.KHZ_48: + samplerate = '48' + break + default: + throw new Error( + 'Unsupported audio samplerate: ' + + this.configuration.audioCodec.samplerate + ) + } + + const audioArgs: Array = + this.controller?.recordingManagement?.recordingManagementService.getCharacteristic( + Characteristic.RecordingAudioActive + ) + ? [ + '-acodec', + 'libfdk_aac', + ...(this.configuration.audioCodec.type === + AudioRecordingCodecType.AAC_LC + ? ['-profile:a', 'aac_low'] + : ['-profile:a', 'aac_eld']), + '-ar', + `${samplerate}k`, + '-b:a', + `${this.configuration.audioCodec.bitrate}k`, + '-ac', + `${this.configuration.audioCodec.audioChannels}` + ] + : [] + + this.server = new MP4StreamingServer( + 'ffmpeg', + `-f lavfi -i \ + testsrc=s=${this.configuration.videoCodec.resolution[0]}x${this.configuration.videoCodec.resolution[1]}:r=${this.configuration.videoCodec.resolution[2]}`.split( + / /g + ), + audioArgs, + videoArgs + ) + + await this.server.start() + if (!this.server || this.server.destroyed) { + return // early exit + } + + const pending: Array = [] + + try { + for await (const box of this.server.generator()) { + pending.push(box.header, box.data) + + const motionDetected = this.accessory + .getService(Service.MotionSensor) + ?.getCharacteristic(Characteristic.MotionDetected).value + + this.log.debug(`mp4 box type ${box.type} and length ${box.length}`) + if (box.type === 'moov' || box.type === 'mdat') { + const fragment = Buffer.concat(pending) + pending.splice(0, pending.length) + + const isLast = STOP_AFTER_MOTION_STOP && !motionDetected + + yield { + data: fragment, + isLast: isLast + } + + if (isLast) { + this.log.debug('Ending session due to motion stopped!') + break + } + } + } + } catch (error: any) { + if (!error.message.startsWith('FFMPEG')) { + // an inexpensive way of identifying our own emitted errors + this.log.error( + `Encountered unexpected error on generator ${error.stack}` + ) + } + } + } + + // eslint-disable-next-line @typescript-eslint/no-unused-vars + closeRecordingStream( + streamId: number, + reason?: HDSProtocolSpecificErrorReason + ): void { + if (reason) { + this.log.error(`Closing stream ${streamId} due to error: ${reason}`) + } + if (this.server) { + this.server.destroy() + this.server = undefined + } + this.handlingStreamingRequest = false + } + + acknowledgeStream(streamId: number): void { + this.closeRecordingStream(streamId) + } +} diff --git a/src/lib/camera/MP4StreamingServer.ts b/src/lib/camera/MP4StreamingServer.ts new file mode 100644 index 00000000..0044eff5 --- /dev/null +++ b/src/lib/camera/MP4StreamingServer.ts @@ -0,0 +1,182 @@ +// Based on https://github.com/homebridge/HAP-NodeJS/blob/latest/src/accessories/Camera_accessory.ts + +import { type ChildProcess, spawn } from 'node:child_process' +import { once } from 'node:events' +import { + type AddressInfo, + createServer, + type Server, + type Socket +} from 'node:net' +import { logger } from '@nrchkb/logger' + +const log = logger('NRCHKB', 'MP4StreamingServer') + +interface MP4Atom { + header: Buffer + length: number + type: string + data: Buffer +} + +export class MP4StreamingServer { + readonly server: Server + + /** + * This can be configured to output ffmpeg debug output! + */ + readonly debugMode: boolean = false + + readonly ffmpegPath: string + readonly args: string[] + + socket?: Socket + childProcess?: ChildProcess + destroyed = false + + connectPromise: Promise + connectResolve?: () => void + + constructor( + ffmpegPath: string, + ffmpegInput: Array, + audioOutputArgs: Array, + videoOutputArgs: Array + ) { + this.connectPromise = new Promise((resolve) => { + this.connectResolve = resolve + }) + + this.server = createServer(this.handleConnection.bind(this)) + this.ffmpegPath = ffmpegPath + this.args = [] + + this.args.push(...ffmpegInput) + + this.args.push(...audioOutputArgs) + + this.args.push('-f', 'mp4') + this.args.push(...videoOutputArgs) + this.args.push('-fflags', '+genpts', '-reset_timestamps', '1') + this.args.push('-movflags', 'frag_keyframe+empty_moov+default_base_moof') + } + + async start() { + const promise = once(this.server, 'listening') + this.server.listen() // listen on random port + await promise + + if (this.destroyed) { + return + } + + const port = (this.server.address() as AddressInfo).port + this.args.push(`tcp://127.0.0.1:${port}`) + + log.debug(`${this.ffmpegPath} ${this.args.join(' ')}`) + + this.childProcess = spawn(this.ffmpegPath, this.args, { + env: process.env, + stdio: this.debugMode ? 'pipe' : 'ignore' + }) + if (!this.childProcess) { + log.error('ChildProcess is undefined directly after the init!') + } + if (this.debugMode) { + this.childProcess.stdout?.on('data', (data) => log.debug(data.toString())) + this.childProcess.stderr?.on('data', (data) => log.debug(data.toString())) + } + } + + destroy() { + this.socket?.destroy() + this.childProcess?.kill() + + this.socket = undefined + this.childProcess = undefined + this.destroyed = true + } + + handleConnection(socket: Socket): void { + this.server.close() // don't accept any further clients + this.socket = socket + this.connectResolve?.() + } + + /** + * Generator for `MP4Atom`s. + * Throws error to signal EOF when socket is closed. + */ + async *generator(): AsyncGenerator { + await this.connectPromise + + if (!this.socket || !this.childProcess) { + log.error( + 'Socket undefined ' + + !!this.socket + + ' childProcess undefined ' + + !!this.childProcess + ) + throw new Error('Unexpected state!') + } + + while (true) { + const header = await this.read(8) + const length = header.readInt32BE(0) - 8 + const type = header.subarray(4).toString() + const data = await this.read(length) + + yield { + header: header, + length: length, + type: type, + data: data + } + } + } + + async read(length: number): Promise { + if (!this.socket) { + throw Error('FFMPEG tried reading from closed socket!') + } + + if (!length) { + return Buffer.alloc(0) + } + + const value = this.socket.read(length) + if (value) { + return value + } + + return new Promise((resolve, reject) => { + const readHandler = () => { + const value = this.socket?.read(length) + if (value) { + cleanup() + resolve(value) + } + } + + const endHandler = () => { + // eslint-disable-next-line @typescript-eslint/no-use-before-define + cleanup() + reject( + new Error(`FFMPEG socket closed during read for ${length} bytes!`) + ) + } + + const cleanup = () => { + this.socket?.removeListener('readable', readHandler) + this.socket?.removeListener('close', endHandler) + } + + if (!this.socket) { + throw new Error('FFMPEG socket is closed now!') + } + + this.socket.on('readable', readHandler) + this.socket.on('close', endHandler) + }) + } +} diff --git a/src/lib/utils/ServiceUtils.ts b/src/lib/utils/ServiceUtils.ts index 976a4a95..0898c159 100644 --- a/src/lib/utils/ServiceUtils.ts +++ b/src/lib/utils/ServiceUtils.ts @@ -17,7 +17,7 @@ import { } from '@homebridge/hap-nodejs' import type { HAPConnection } from '@homebridge/hap-nodejs/dist/lib/util/eventedhttp' import { logger } from '@nrchkb/logger' - +import { configureCamera } from '../camera/CameraControl' import NRCHKBError from '../NRCHKBError' import type HAPServiceConfigType from '../types/HAPServiceConfigType' import type HAPServiceNodeType from '../types/HAPServiceNodeType' @@ -308,7 +308,7 @@ module.exports = (node: HAPServiceNodeType) => { if (removed) { // This node has been deleted if (node.config.isParent) { - // remove accessory from bridge + // remove accessory from the bridge node.hostNode.host.removeBridgedAccessories([node.accessory]) node.accessory.destroy() } else { @@ -364,7 +364,7 @@ module.exports = (node: HAPServiceNodeType) => { service = accessory.addService(newService) } } else { - // if a service with the same UUID and subtype was found it will + // if a service with the same UUID and subtype was found, it will // be updated and used log.debug('... found it! Updating it.') service @@ -386,7 +386,7 @@ module.exports = (node: HAPServiceNodeType) => { } const configureCameraSource = ( - _accessory: Accessory, + accessory: Accessory, _service: Service, config: HAPServiceConfigType ) => { @@ -403,6 +403,7 @@ module.exports = (node: HAPServiceNodeType) => { // accessory.configureCameraSource( // new CameraSource(service, config, node) // ) + configureCamera(accessory, config) } } else { log.error('Missing configuration for CameraControl.') diff --git a/src/lib/utils/ServiceUtils2.ts b/src/lib/utils/ServiceUtils2.ts index dea49704..d53186ca 100644 --- a/src/lib/utils/ServiceUtils2.ts +++ b/src/lib/utils/ServiceUtils2.ts @@ -16,7 +16,7 @@ import type { } from '@homebridge/hap-nodejs/dist/lib/util/eventedhttp' import type { SessionIdentifier } from '@homebridge/hap-nodejs/dist/types' import { logger } from '@nrchkb/logger' - +import { configureCamera } from '../camera/CameraControl' import NRCHKBError from '../NRCHKBError' import { Storage } from '../Storage' import type HAPService2ConfigType from '../types/HAPService2ConfigType' @@ -351,7 +351,7 @@ module.exports = (node: HAPService2NodeType) => { if (removed) { // This node has been deleted if (node.config.isParent) { - // remove accessory from bridge + // remove accessory from the bridge node.hostNode.host.removeBridgedAccessories([node.accessory]) node.accessory.destroy() } else { @@ -407,7 +407,7 @@ module.exports = (node: HAPService2NodeType) => { service = accessory.addService(newService) } } else { - // if a service with the same UUID and subtype was found it will + // if a service with the same UUID and subtype was found, it will // be updated and used log.debug('... found it! Updating it.') service @@ -429,7 +429,7 @@ module.exports = (node: HAPService2NodeType) => { } const configureCameraSource = ( - _accessory: Accessory, + accessory: Accessory, _service: Service, config: HAPService2ConfigType ) => { @@ -446,6 +446,7 @@ module.exports = (node: HAPService2NodeType) => { // accessory.configureCameraSource( // new CameraSource(service, config, node) // ) + configureCamera(accessory, config) } } else { log.error('Missing configuration for CameraControl.')