From e8459a7a7b68c00f9df855f619926a80247a714e Mon Sep 17 00:00:00 2001 From: Darius Date: Fri, 21 Nov 2025 16:49:12 +0100 Subject: [PATCH] rewrite typeysation --- package-lock.json | 399 +---------------------------------- src/homeassistant/client.ts | 14 +- src/homeassistant/service.ts | 68 +++--- src/index.ts | 78 +++---- src/tidal/client.ts | 14 +- src/tidal/service.ts | 72 ++++--- 6 files changed, 131 insertions(+), 514 deletions(-) diff --git a/package-lock.json b/package-lock.json index 217e38f..41df0b0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,8 +20,8 @@ } }, "node_modules/@dpu/shared": { - "version": "1.0.14", - "resolved": "git+https://git.dariusbag.dev/DarDarBinks/dpu-shared.git#9269eaaa881762c7045ba96b07a0beaf0384ed91", + "version": "1.1.4", + "resolved": "git+https://git.dariusbag.dev/DarDarBinks/dpu-shared.git#a35a3e7ecbc23444bcfbfc2e89770f490fd4123f", "dependencies": { "axios": "^1.7.9", "chalk": "^5.6.2", @@ -605,23 +605,6 @@ "node": "20 || >=22" } }, - "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==", - "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/@pinojs/redact": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/@pinojs/redact/-/redact-0.4.0.tgz", @@ -677,30 +660,6 @@ } } }, - "node_modules/ansi-regex": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", - "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/ansi-styles": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", - "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -762,24 +721,6 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "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==", - "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==", - "license": "MIT" - }, "node_modules/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -801,20 +742,6 @@ "node": ">=18" } }, - "node_modules/cross-spawn": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", - "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", - "license": "MIT", - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -859,18 +786,6 @@ "node": ">= 0.4" } }, - "node_modules/eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "license": "MIT" - }, - "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==", - "license": "MIT" - }, "node_modules/es-define-property": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", @@ -1111,22 +1026,6 @@ } } }, - "node_modules/foreground-child": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", - "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", - "license": "ISC", - "dependencies": { - "cross-spawn": "^7.0.6", - "signal-exit": "^4.0.1" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/form-data": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", @@ -1218,21 +1117,15 @@ } }, "node_modules/glob": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-11.1.0.tgz", - "integrity": "sha512-vuNwKSaKiqm7g0THUBu2x7ckSs3XJLXE+2ssL7/MfTGPLLcrJQ/4Uq1CjPTtO5cCIiRxqvN6Twy1qOwhL0Xjcw==", + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-13.0.0.tgz", + "integrity": "sha512-tvZgpqk6fz4BaNZ66ZsRaZnbHvP/jG3uKJvAZOwEVUL4RTA5nJeeLYfyN9/VA8NX/V3IBG+hkeuGpKjvELkVhA==", "license": "BlueOak-1.0.0", "dependencies": { - "foreground-child": "^3.3.1", - "jackspeak": "^4.1.1", "minimatch": "^10.1.1", "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", "path-scurry": "^2.0.0" }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, "engines": { "node": "20 || >=22" }, @@ -1300,36 +1193,6 @@ "node": ">= 10" } }, - "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==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "license": "ISC" - }, - "node_modules/jackspeak": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.1.1.tgz", - "integrity": "sha512-zptv57P3GpL+O0I7VdMJNBZCu+BPHVQUk55Ft8/QCJjTVxrnJHuVuX/0Bl2A6/+2oyR/ZMEuFKwmzqqZ/U5nPQ==", - "license": "BlueOak-1.0.0", - "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, - "engines": { - "node": "20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/json-schema-ref-resolver": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/json-schema-ref-resolver/-/json-schema-ref-resolver-3.0.0.tgz", @@ -1470,15 +1333,6 @@ "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", "license": "BlueOak-1.0.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==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/path-scurry": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.1.tgz", @@ -1614,12 +1468,12 @@ "license": "MIT" }, "node_modules/rimraf": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.1.0.tgz", - "integrity": "sha512-DxdlA1bdNzkZK7JiNWH+BAx1x4tEJWoTofIopFo6qWUU94jYrFZ0ubY05TqH3nWPJ1nKa1JWVFDINZ3fnrle/A==", + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.1.2.tgz", + "integrity": "sha512-cFCkPslJv7BAXJsYlK1dZsbP8/ZNLkCAQ0bi1hf5EKX2QHegmDFEFA6QhuYJlk7UDdc+02JjO80YSOrWPpw06g==", "license": "BlueOak-1.0.0", "dependencies": { - "glob": "^11.0.3", + "glob": "^13.0.0", "package-json-from-dist": "^1.0.1" }, "bin": { @@ -1694,39 +1548,6 @@ "integrity": "sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==", "license": "MIT" }, - "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==", - "license": "MIT", - "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==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "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==", - "license": "ISC", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/sonic-boom": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-4.2.0.tgz", @@ -1745,102 +1566,6 @@ "node": ">= 10.x" } }, - "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==", - "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/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==", - "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/string-width-cjs/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==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/string-width-cjs/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==", - "license": "MIT" - }, - "node_modules/string-width-cjs/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==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", - "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi-cjs/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==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/thread-stream": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-3.1.0.tgz", @@ -1899,112 +1624,6 @@ "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", "dev": true, "license": "MIT" - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "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==", - "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/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==", - "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-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "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==", - "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/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==", - "license": "MIT" - }, - "node_modules/wrap-ansi-cjs/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==", - "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/wrap-ansi-cjs/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==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } } } } diff --git a/src/homeassistant/client.ts b/src/homeassistant/client.ts index c77307c..0835862 100644 --- a/src/homeassistant/client.ts +++ b/src/homeassistant/client.ts @@ -1,14 +1,8 @@ import type { HomeAssistantEntity } from "@dpu/shared"; +import { BaseClient } from "@dpu/shared/dist/fastify"; import { printNetworkError } from "@dpu/shared/dist/logger.js"; -import type { AxiosInstance } from "axios"; - -export class HomeAssistantClient { - private axiosInstance: AxiosInstance; - - constructor(axiosInstance: AxiosInstance) { - this.axiosInstance = axiosInstance; - } +export class HomeAssistantClient extends BaseClient { async getEntityStates(entityIds: string[]): Promise { try { const promises = entityIds.map((id) => this.getEntityState(id)); @@ -21,7 +15,7 @@ export class HomeAssistantClient { async getEntityState(entityId: string): Promise { try { - const response = await this.axiosInstance.get( + const response = await this.getAxios().get( `states/${entityId}`, ); return response.data; @@ -33,7 +27,7 @@ export class HomeAssistantClient { async triggerWebhook(webhookId: string): Promise { try { - const response = await this.axiosInstance.post( + const response = await this.getAxios().post( `webhook/${webhookId}`, ); return response.data; diff --git a/src/homeassistant/service.ts b/src/homeassistant/service.ts index 9276fe9..94edb2f 100644 --- a/src/homeassistant/service.ts +++ b/src/homeassistant/service.ts @@ -2,26 +2,23 @@ import type { HomeAssistantDeskPositionResult, HomeAssistantEntity, } from "@dpu/shared"; +import { BaseService, type ServiceResult } from "@dpu/shared/dist/fastify.js"; import { logWarning } from "@dpu/shared/dist/logger.js"; import { calculateSecondsBetween } from "@dpu/shared/dist/timehelper.js"; import { Config } from "../config.js"; import type { HomeAssistantClient } from "./client.js"; -export class HomeAssistantService { - private client: HomeAssistantClient; - - constructor(client: HomeAssistantClient) { - this.client = client; - } - - async startStandingAutomation(): Promise { +export class HomeAssistantService extends BaseService { + async startStandingAutomation(): Promise> { try { - const position = await this.getDeskPosition(); + const positionResult = await this.getDeskPosition(); - if (position === null) { - throw Error("error accessing desk api"); + if (!positionResult.successful) { + throw Error(positionResult.result as string); } + const position = positionResult.result as HomeAssistantDeskPositionResult; + if (position.as_boolean) { throw Error("desk is already in standing position"); } @@ -30,24 +27,29 @@ export class HomeAssistantService { throw Error("desk has moved too recently"); } - return await this.client.triggerWebhook( + const result = await this.getClient().triggerWebhook( Config.homeassistant.id_webhook_stand, ); + + return this.getSuccessfulResult(result); } catch (error) { - logWarning("Error starting stand automation:", error); - return null; + const error_message = "error starting stand automation"; + logWarning(error_message, error); + return this.getErrorResult(error_message); } } - async getDeskPosition(): Promise { + async getDeskPosition(): Promise< + ServiceResult + > { try { - const raw = await this.client.getEntityState( + const raw = await this.getClient().getEntityState( Config.homeassistant.id_desk_sensor_binary, ); const position = Number(raw.state); - return { + const result = { raw, as_boolean: position === 1, as_text: () => { @@ -60,13 +62,16 @@ export class HomeAssistantService { Date.now(), ), }; + + return this.getSuccessfulResult(result); } catch (error) { - logWarning("Error getting desk position:", error); - return null; + const error_message = "error getting desk position"; + logWarning(error_message, error); + return this.getErrorResult(error_message); } } - async getTemperatureText(): Promise { + async getTemperatureText(): Promise> { try { const entities = await this.getTemperatures(); const values = entities @@ -76,30 +81,23 @@ export class HomeAssistantService { values.length > 0 ? values.reduce((sum, value) => sum + value, 0) / values.length : 0; - return average.toFixed(2); + const result = average.toFixed(2); + return this.getSuccessfulResult(result); } catch (error) { - logWarning(`Error getting temperature as text`, error); - return null; + const error_message = "error getting temperature as text"; + logWarning(error_message, error); + return this.getErrorResult(error_message); } } - async getTemperatures(): Promise { + private async getTemperatures(): Promise { try { - return await this.client.getEntityStates( + return await this.getClient().getEntityStates( Config.homeassistant.id_room_sensors, ); } catch (error) { - logWarning("Error getting temperatures:", error); + logWarning("error getting temperatures:", error); return []; } } - - async getTemperature(entityId: string): Promise { - try { - return await this.client.getEntityState(entityId); - } catch (error) { - logWarning(`Error getting temperature for ${entityId}:`, error); - return null; - } - } } diff --git a/src/index.ts b/src/index.ts index 51d5e4e..8370dca 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,3 +1,4 @@ +import type { HomeAssistantDeskPositionResult } from "@dpu/shared"; import { logInfo } from "@dpu/shared/dist/logger.js"; import type { FastifyReply, FastifyRequest } from "fastify"; import fastify from "fastify"; @@ -44,17 +45,20 @@ const tidalService = new TidalService(tidalClient); // HOME ASSISTANT server.get("/homeassistant/desk/position", async (_request, reply) => { - const result = await haService.getDeskPosition(); + const service_result = await haService.getDeskPosition(); - if (!result) { - reply.code(500); - return { error: "Failed to get desk position" }; + if (!service_result.successful) { + reply.code(418); + return { error: service_result.result }; } + const position_result = + service_result.result as HomeAssistantDeskPositionResult; + return { - position: result.as_text(), - is_standing: result.as_boolean, - last_changed: result.last_changed.toReadable(true), + position: position_result.as_text(), + is_standing: position_result.as_boolean, + last_changed: position_result.last_changed.toReadable(true), }; }); @@ -62,60 +66,60 @@ server.post( "/homeassistant/desk/stand", { preHandler: verifyAPIKey }, async (_request, reply) => { - const result = await haService.startStandingAutomation(); + const service_result = await haService.startStandingAutomation(); - if (!result) { - reply.code(500); - return { error: "Failed to start stand automation" }; + if (!service_result.successful) { + reply.code(418); + return { error: service_result.result }; } - return result; + return service_result.result; }, ); server.get("/homeassistant/temperature", async (_request, reply) => { - const result = await haService.getTemperatureText(); + const service_result = await haService.getTemperatureText(); - if (!result) { - reply.code(500); - return { error: "Failed to get temperature" }; + if (!service_result.successful) { + reply.code(418); + return { error: service_result.result }; } - return result; + return service_result.result; }); // TIDAL server.get("/tidal/song", async (_request, reply) => { - const result = await tidalService.getSong(); + const service_result = await tidalService.getSong(); - if (!result) { - reply.code(500); - return { error: "Failed to get song" }; + if (!service_result.successful) { + reply.code(418); + return { error: service_result.result }; } - return result; + return service_result.result; }); server.get("/tidal/songFormatted", async (_request, reply) => { - const result = await tidalService.getSongFormatted(); + const service_result = await tidalService.getSongFormatted(); - if (!result) { - reply.code(500); - return { error: "Failed to get song" }; + if (!service_result.successful) { + reply.code(418); + return { error: service_result.result }; } - return result; + return service_result.result; }); server.get("/tidal/volume", async (_request, reply) => { - const result = await tidalService.getVolume(); + const service_result = await tidalService.getVolume(); - if (!result) { - reply.code(500); - return { error: "Failed to get volume" }; + if (!service_result.successful) { + reply.code(418); + return { error: service_result.result }; } - return result; + return service_result.result; }); server.post( @@ -123,14 +127,14 @@ server.post( { preHandler: verifyAPIKey }, async (request, reply) => { const volume = request.body as string; - const result = await tidalService.setVolume(volume); + const service_result = await tidalService.setVolume(volume); - if (!result) { - reply.code(500); - return { error: "Failed to set volume" }; + if (!service_result.successful) { + reply.code(418); + return { error: service_result.result }; } - return result; + return service_result.result; }, ); diff --git a/src/tidal/client.ts b/src/tidal/client.ts index 8abbc18..dcc6471 100644 --- a/src/tidal/client.ts +++ b/src/tidal/client.ts @@ -1,16 +1,10 @@ +import { BaseClient } from "@dpu/shared/dist/fastify"; import { printNetworkError } from "@dpu/shared/dist/logger.js"; -import type { AxiosInstance } from "axios"; - -export class TidalClient { - private axiosInstance: AxiosInstance; - - constructor(axiosInstance: AxiosInstance) { - this.axiosInstance = axiosInstance; - } +export class TidalClient extends BaseClient { async get(endpoint: string): Promise { try { - const response = await this.axiosInstance.get(`/${endpoint}`); + const response = await this.getAxios().get(`/${endpoint}`); return response.data; } catch (error) { @@ -21,7 +15,7 @@ export class TidalClient { async post(endpoint: string, data: unknown): Promise { try { - const response = await this.axiosInstance.post(`/${endpoint}`, data); + const response = await this.getAxios().post(`/${endpoint}`, data); return response.data; } catch (error) { printNetworkError(error); diff --git a/src/tidal/service.ts b/src/tidal/service.ts index cbef323..cbbb834 100644 --- a/src/tidal/service.ts +++ b/src/tidal/service.ts @@ -1,43 +1,43 @@ import type { TidalSong, TidalVolume } from "@dpu/shared"; +import { BaseService, type ServiceResult } from "@dpu/shared/dist/fastify.js"; import { logWarning } from "@dpu/shared/dist/logger.js"; -import type { TidalClient } from "./client.js"; +import type { TidalClient } from "./client"; -export class TidalService { - private client: TidalClient; - - constructor(client: TidalClient) { - this.client = client; - } - - async getSongFormatted(): Promise { - const song = await this.getSong(); - if (song) { +export class TidalService extends BaseService { + async getSongFormatted(): Promise> { + const req = await this.getSong(); + if (req.successful) { + const song = req.result as TidalSong; const status = song.status === "playing" ? "▶️" : "⏸️"; - return `listening to ${song.title} by ${song.artists}. ${status} ${song.current}/${song.duration}. link: ${song.url}`; + return this.getSuccessfulResult( + `listening to ${song.title} by ${song.artists}. ${status} ${song.current}/${song.duration}. link: ${song.url}`, + ); } else { - return `no song found`; + return this.getErrorResult(req.result as string); } } - async getSong(): Promise { + async getSong(): Promise> { try { - const response = this.client.get("current"); + const response = await this.getClient().get("current"); - return response; + return this.getSuccessfulResult(response); } catch { - logWarning("error getting song from tidal"); - return null; + const error_message = "error getting song from tidal"; + logWarning(error_message); + return this.getErrorResult(error_message); } } - async getVolume(): Promise { + async getVolume(): Promise> { try { - const response = await this.client.get("volume"); + const response = await this.getClient().get("volume"); - return response; + return this.getSuccessfulResult(response); } catch { - logWarning("error getting volume from tidal"); - return null; + const error_message = "error getting volume from tidal"; + logWarning(error_message); + return this.getErrorResult(error_message); } } @@ -45,13 +45,16 @@ export class TidalService { return Math.min(Math.max(value, 0), 100); } - async setVolume(argument: string): Promise { + async setVolume( + argument: string, + ): Promise> { const value = parseInt(argument, 10); // relative const adjustMatch = argument.match(/^([+-])(\d+)$/); if (adjustMatch) { - const volume = await this.getVolume(); - if (volume) { + const req = await this.getVolume(); + if (req.successful) { + const volume = req.result as TidalVolume; const wantedVolume = volume.volume + value; const clampWantedVolume = this.clamp(wantedVolume); return await this.setVolumeToTidal(clampWantedVolume); @@ -65,19 +68,24 @@ export class TidalService { return await this.setVolumeToTidal(clampValue); } - return null; + const error_message = "error parsing volume to set"; + logWarning(error_message); + return this.getErrorResult(error_message); } - async setVolumeToTidal(volume: number): Promise { + async setVolumeToTidal( + volume: number, + ): Promise> { try { - const response = await this.client.post("volume", { + const response = await this.getClient().post("volume", { volume, }); - return response; + return this.getSuccessfulResult(response); } catch { - logWarning("error setting volume from tidal"); - return null; + const error_message = "error setting volume from tidal"; + logWarning(error_message); + return this.getErrorResult(error_message); } } }