diff --git a/bun.lock b/bun.lock index 62262a9..35362d5 100644 --- a/bun.lock +++ b/bun.lock @@ -250,21 +250,21 @@ "@cacheable/memory": ["@cacheable/memory@2.0.8", "", { "dependencies": { "@cacheable/utils": "^2.4.0", "@keyv/bigmap": "^1.3.1", "hookified": "^1.15.1", "keyv": "^5.6.0" } }, "sha512-FvEb29x5wVwu/Kf93IWwsOOEuhHh6dYCJF3vcKLzXc0KXIW181AOzv6ceT4ZpBHDvAfG60eqb+ekmrnLHIy+jw=="], - "@cacheable/utils": ["@cacheable/utils@2.4.0", "", { "dependencies": { "hashery": "^1.5.0", "keyv": "^5.6.0" } }, "sha512-PeMMsqjVq+bF0WBsxFBxr/WozBJiZKY0rUojuaCoIaKnEl3Ju1wfEwS+SV1DU/cSe8fqHIPiYJFif8T3MVt4cQ=="], + "@cacheable/utils": ["@cacheable/utils@2.4.1", "", { "dependencies": { "hashery": "^1.5.1", "keyv": "^5.6.0" } }, "sha512-eiFgzCbIneyMlLOmNG4g9xzF7Hv3Mga4LjxjcSC/ues6VYq2+gUbQI8JqNuw/ZM8tJIeIaBGpswAsqV2V7ApgA=="], - "@capacitor/android": ["@capacitor/android@8.2.0", "", { "peerDependencies": { "@capacitor/core": "^8.2.0" } }, "sha512-XLm5OsWLPfXQxDxzFS7SOdMEgGvW+2c7TGLXkTR2cSKdkWK5Abns4imlT5qghKYhjM9r74IrDkBWg/9ALUGNKQ=="], + "@capacitor/android": ["@capacitor/android@8.3.0", "", { "peerDependencies": { "@capacitor/core": "^8.3.0" } }, "sha512-EQy6ByUuKayQBJmMm/e0byJiHavqsQHrvW23BuT2GNVQvenAvipqwaePiJHzrv2PZr7A0T0+se4kgDCeROj0mQ=="], - "@capacitor/app": ["@capacitor/app@8.0.1", "", { "peerDependencies": { "@capacitor/core": ">=8.0.0" } }, "sha512-yeG3yyA0ETKqvgqexwHMBlmVOF13A1hRXzv/km0Ptv5TrNIZvZJK4MTI3uiqvnbHrzoJGP5DwWAjEXEfi90v3Q=="], + "@capacitor/app": ["@capacitor/app@8.1.0", "", { "peerDependencies": { "@capacitor/core": ">=8.0.0" } }, "sha512-MlmttTOWHDedr/G4SrhNRxsXMqY+R75S4MM4eIgzsgCzOYhb/MpCkA5Q3nuOCfL1oHm26xjUzqZ5aupbOwdfYg=="], "@capacitor/assets": ["@capacitor/assets@3.0.5", "", { "dependencies": { "@capacitor/cli": "^5.3.0", "@ionic/utils-array": "2.1.6", "@ionic/utils-fs": "3.1.7", "@trapezedev/project": "^7.0.10", "commander": "8.3.0", "debug": "4.3.4", "fs-extra": "10.1.0", "node-fetch": "2.7.0", "node-html-parser": "5.4.2", "sharp": "0.32.6", "tslib": "2.6.2", "yargs": "17.7.2" }, "bin": { "capacitor-assets": "bin/capacitor-assets" } }, "sha512-ohz/OUq61Y1Fc6aVSt0uDrUdeOA7oTH4pkWDbv/8I3UrPjH7oPkzYhShuDRUjekNp9RBi198VSFdt0CetpEOzw=="], - "@capacitor/cli": ["@capacitor/cli@8.2.0", "", { "dependencies": { "@ionic/cli-framework-output": "^2.2.8", "@ionic/utils-subprocess": "^3.0.1", "@ionic/utils-terminal": "^2.3.5", "commander": "^12.1.0", "debug": "^4.4.0", "env-paths": "^2.2.0", "fs-extra": "^11.2.0", "kleur": "^4.1.5", "native-run": "^2.0.3", "open": "^8.4.0", "plist": "^3.1.0", "prompts": "^2.4.2", "rimraf": "^6.0.1", "semver": "^7.6.3", "tar": "^7.5.3", "tslib": "^2.8.1", "xml2js": "^0.6.2" }, "bin": { "cap": "bin/capacitor", "capacitor": "bin/capacitor" } }, "sha512-1cMEk0d/I6tl1U+v/lnJR5Oylpx8ZBIHrvQxD5zK0MkjYOUyQAAGJgh97rkhGJqjAUvrGpa8H4BmyhNQN9a17A=="], + "@capacitor/cli": ["@capacitor/cli@8.3.0", "", { "dependencies": { "@ionic/cli-framework-output": "^2.2.8", "@ionic/utils-subprocess": "^3.0.1", "@ionic/utils-terminal": "^2.3.5", "commander": "^12.1.0", "debug": "^4.4.0", "env-paths": "^2.2.0", "fs-extra": "^11.2.0", "kleur": "^4.1.5", "native-run": "^2.0.3", "open": "^8.4.0", "plist": "^3.1.0", "prompts": "^2.4.2", "rimraf": "^6.0.1", "semver": "^7.6.3", "tar": "^7.5.3", "tslib": "^2.8.1", "xml2js": "^0.6.2" }, "bin": { "cap": "bin/capacitor", "capacitor": "bin/capacitor" } }, "sha512-n3QDUimtFNbagoo8kLdjvTz3i3Y4jX1fOjvo6ptUKLzErmuqeamL8kECASoyQvg/OzJisZToGZrgLphBsptJcw=="], - "@capacitor/core": ["@capacitor/core@8.2.0", "", { "dependencies": { "tslib": "^2.1.0" } }, "sha512-oKaoNeNtH2iIZMDFVrb1atoyRECDGHcfLMunJ5KWN8DtvpVBeeA4c41e20NTuhMxw1cSYbpq2PV2hb+/9CJxlQ=="], + "@capacitor/core": ["@capacitor/core@8.3.0", "", { "dependencies": { "tslib": "^2.1.0" } }, "sha512-S4ajn4G/fS3VJj8salxqH/3LO5PPWv1VxGKQ27OCajnDcLJjEg9VXwgMPnlypgkIOqCJ2fmQLtk8GT+BlI9/rw=="], - "@capacitor/haptics": ["@capacitor/haptics@8.0.1", "", { "peerDependencies": { "@capacitor/core": ">=8.0.0" } }, "sha512-8v8rowLBMeb3CryqoQvXndwyUsoi4pPXf0qFw7IGA4D32Uk7+K6juN2SjRowqunoovkvvbFmU9TD7JIAz2zmFw=="], + "@capacitor/haptics": ["@capacitor/haptics@8.0.2", "", { "peerDependencies": { "@capacitor/core": ">=8.0.0" } }, "sha512-c2hZzRR5Fk1tbTvhG1jhh2XBAf3EhnIerMIb2sl7Mt41Gxx1fhBJFDa0/BI1IbY4loVepyyuqNC9820/GZuoWQ=="], - "@capacitor/ios": ["@capacitor/ios@8.2.0", "", { "peerDependencies": { "@capacitor/core": "^8.2.0" } }, "sha512-X2/VtM4qP/R1SM0VQ5W/VotEc6PS/KTooD33EijsfAHWBdee+xmBapW8SeNLnu16wJ+tsfWlvtipaJEyfKbRKQ=="], + "@capacitor/ios": ["@capacitor/ios@8.3.0", "", { "peerDependencies": { "@capacitor/core": "^8.3.0" } }, "sha512-5Rtwv8SITKlYTt8lAZG+khnVIdzPtqbocH3eP+JkEmX1vpSMwx4TOKtT8OBz8gpQ+pUJDRp7DBYOv3U6l/obCw=="], "@cloudflare/workerd-darwin-64": ["@cloudflare/workerd-darwin-64@1.20260317.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-8hjh3sPMwY8M/zedq3/sXoA2Q4BedlGufn3KOOleIG+5a4ReQKLlUah140D7J6zlKmYZAFMJ4tWC7hCuI/s79g=="], @@ -280,7 +280,7 @@ "@csstools/css-parser-algorithms": ["@csstools/css-parser-algorithms@3.0.5", "", { "peerDependencies": { "@csstools/css-tokenizer": "^3.0.4" } }, "sha512-DaDeUkXZKjdGhgYaHNJTV9pV7Y9B3b644jCLs9Upc3VeNGg6LWARAT6O+Q+/COo+2gg/bM5rhpMAtf70WqfBdQ=="], - "@csstools/css-syntax-patches-for-csstree": ["@csstools/css-syntax-patches-for-csstree@1.1.1", "", { "peerDependencies": { "css-tree": "^3.2.1" }, "optionalPeers": ["css-tree"] }, "sha512-BvqN0AMWNAnLk9G8jnUT77D+mUbY/H2b3uDTvg2isJkHaOufUE2R3AOwxWo7VBQKT1lOdwdvorddo2B/lk64+w=="], + "@csstools/css-syntax-patches-for-csstree": ["@csstools/css-syntax-patches-for-csstree@1.1.2", "", { "peerDependencies": { "css-tree": "^3.2.1" }, "optionalPeers": ["css-tree"] }, "sha512-5GkLzz4prTIpoyeUiIu3iV6CSG3Plo7xRVOFPKI7FVEJ3mZ0A8SwK0XU3Gl7xAkiQ+mDyam+NNp875/C5y+jSA=="], "@csstools/css-tokenizer": ["@csstools/css-tokenizer@3.0.4", "", {}, "sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw=="], @@ -670,13 +670,13 @@ "bare-path": ["bare-path@3.0.0", "", { "dependencies": { "bare-os": "^3.0.1" } }, "sha512-tyfW2cQcB5NN8Saijrhqn0Zh7AnFNsnczRcuWODH0eYAXBsJ5gVxAUuNr7tsHSC6IZ77cA0SitzT+s47kot8Mw=="], - "bare-stream": ["bare-stream@2.10.0", "", { "dependencies": { "streamx": "^2.25.0", "teex": "^1.0.1" }, "peerDependencies": { "bare-buffer": "*", "bare-events": "*" }, "optionalPeers": ["bare-buffer", "bare-events"] }, "sha512-DOPZF/DDcDruKDA43cOw6e9Quq5daua7ygcAwJE/pKJsRWhgSSemi7qVNGE5kyDIxIeN1533G/zfbvWX7Wcb9w=="], + "bare-stream": ["bare-stream@2.11.0", "", { "dependencies": { "streamx": "^2.25.0", "teex": "^1.0.1" }, "peerDependencies": { "bare-abort-controller": "*", "bare-buffer": "*", "bare-events": "*" }, "optionalPeers": ["bare-abort-controller", "bare-buffer", "bare-events"] }, "sha512-Y/+iQ49fL3rIn6w/AVxI/2+BRrpmzJvdWt5Jv8Za6Ngqc6V227c+pYjYYgLdpR3MwQ9ObVXD0ZrqoBztakM0rw=="], "bare-url": ["bare-url@2.4.0", "", { "dependencies": { "bare-path": "^3.0.0" } }, "sha512-NSTU5WN+fy/L0DDenfE8SXQna4voXuW0FHM7wH8i3/q9khUSchfPbPezO4zSFMnDGIf9YE+mt/RWhZgNRKRIXA=="], "base64-js": ["base64-js@1.5.1", "", {}, "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="], - "baseline-browser-mapping": ["baseline-browser-mapping@2.10.10", "", { "bin": { "baseline-browser-mapping": "dist/cli.cjs" } }, "sha512-sUoJ3IMxx4AyRqO4MLeHlnGDkyXRoUG0/AI9fjK+vS72ekpV0yWVY7O0BVjmBcRtkNcsAO2QDZ4tdKKGoI6YaQ=="], + "baseline-browser-mapping": ["baseline-browser-mapping@2.10.11", "", { "bin": { "baseline-browser-mapping": "dist/cli.cjs" } }, "sha512-DAKrHphkJyiGuau/cFieRYhcTFeK/lBuD++C7cZ6KZHbMhBrisoi+EvhQ5RZrIfV5qwsW8kgQ07JIC+MDJRAhg=="], "big-integer": ["big-integer@1.6.52", "", {}, "sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg=="], @@ -690,7 +690,7 @@ "bplist-parser": ["bplist-parser@0.3.2", "", { "dependencies": { "big-integer": "1.6.x" } }, "sha512-apC2+fspHGI3mMKj+dGevkGo/tCqVB8jMb6i+OX+E29p0Iposz07fABkRIfVUPNd5A5VbuOz1bZbnmkKLYF+wQ=="], - "brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="], + "brace-expansion": ["brace-expansion@1.1.13", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w=="], "braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="], @@ -722,7 +722,7 @@ "camelcase-keys": ["camelcase-keys@6.2.2", "", { "dependencies": { "camelcase": "^5.3.1", "map-obj": "^4.0.0", "quick-lru": "^4.0.1" } }, "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg=="], - "caniuse-lite": ["caniuse-lite@1.0.30001780", "", {}, "sha512-llngX0E7nQci5BPJDqoZSbuZ5Bcs9F5db7EtgfwBerX9XGtkkiO4NwfDDIRzHTTwcYC8vC7bmeUEPGrKlR/TkQ=="], + "caniuse-lite": ["caniuse-lite@1.0.30001781", "", {}, "sha512-RdwNCyMsNBftLjW6w01z8bKEvT6e/5tpPVEgtn22TiLGlstHOVecsX2KHFkD5e/vRnIE4EGzpuIODb3mtswtkw=="], "chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], @@ -884,7 +884,7 @@ "ejs": ["ejs@3.1.10", "", { "dependencies": { "jake": "^10.8.5" }, "bin": { "ejs": "bin/cli.js" } }, "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA=="], - "electron-to-chromium": ["electron-to-chromium@1.5.321", "", {}, "sha512-L2C7Q279W2D/J4PLZLk7sebOILDSWos7bMsMNN06rK482umHUrh/3lM8G7IlHFOYip2oAg5nha1rCMxr/rs6ZQ=="], + "electron-to-chromium": ["electron-to-chromium@1.5.328", "", {}, "sha512-QNQ5l45DzYytThO21403XN3FvK0hOkWDG8viNf6jqS42msJ8I4tGDSpBCgvDRRPnkffafiwAym2X2eHeGD2V0w=="], "elementtree": ["elementtree@0.1.7", "", { "dependencies": { "sax": "1.1.4" } }, "sha512-wkgGT6kugeQk/P6VZ/f4T+4HB41BVgNBq5CDIZVbQ02nvTVqAiVTbskxxu3eA/X96lMlfYOwnLQpN2v5E1zDEg=="], @@ -1066,7 +1066,7 @@ "gradle-to-js": ["gradle-to-js@2.0.1", "", { "dependencies": { "lodash.merge": "^4.6.2" }, "bin": { "gradle-to-js": "cli.js" } }, "sha512-is3hDn9zb8XXnjbEeAEIqxTpLHUiGBqjegLmXPuyMBfKAggpadWFku4/AP8iYAGBX6qR9/5UIUIp47V0XI3aMw=="], - "handlebars": ["handlebars@4.7.8", "", { "dependencies": { "minimist": "^1.2.5", "neo-async": "^2.6.2", "source-map": "^0.6.1", "wordwrap": "^1.0.0" }, "optionalDependencies": { "uglify-js": "^3.1.4" }, "bin": { "handlebars": "bin/handlebars" } }, "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ=="], + "handlebars": ["handlebars@4.7.9", "", { "dependencies": { "minimist": "^1.2.5", "neo-async": "^2.6.2", "source-map": "^0.6.1", "wordwrap": "^1.0.0" }, "optionalDependencies": { "uglify-js": "^3.1.4" }, "bin": { "handlebars": "bin/handlebars" } }, "sha512-4E71E0rpOaQuJR2A3xDZ+GM1HyWYv1clR58tC8emQNeQe3RH7MAzSbat+V0wG78LQBo6m6bzSG/L4pBuCsgnUQ=="], "hard-rejection": ["hard-rejection@2.1.0", "", {}, "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA=="], @@ -1316,7 +1316,7 @@ "min-indent": ["min-indent@1.0.1", "", {}, "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg=="], - "miniflare": ["miniflare@4.20260317.1", "", { "dependencies": { "@cspotcode/source-map-support": "0.8.1", "sharp": "^0.34.5", "undici": "7.24.4", "workerd": "1.20260317.1", "ws": "8.18.0", "youch": "4.1.0-beta.10" }, "bin": { "miniflare": "bootstrap.js" } }, "sha512-A3csI1HXEIfqe3oscgpoRMHdYlkReQKPH/g5JE53vFSjoM6YIAOGAzyDNeYffwd9oQkPWDj9xER8+vpxei8klA=="], + "miniflare": ["miniflare@4.20260317.2", "", { "dependencies": { "@cspotcode/source-map-support": "0.8.1", "sharp": "^0.34.5", "undici": "7.24.4", "workerd": "1.20260317.1", "ws": "8.18.0", "youch": "4.1.0-beta.10" }, "bin": { "miniflare": "bootstrap.js" } }, "sha512-qNL+yWAFMX6fr0pWU6Lx1vNpPobpnDSF1V8eunIckWvoIQl8y1oBjL2RJFEGY3un+l3f9gwW9dirDPP26usYJQ=="], "minimatch": ["minimatch@3.1.5", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w=="], @@ -1366,7 +1366,7 @@ "normalize-path": ["normalize-path@3.0.0", "", {}, "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA=="], - "npm": ["npm@11.12.0", "", { "dependencies": { "@isaacs/string-locale-compare": "^1.1.0", "@npmcli/arborist": "^9.4.2", "@npmcli/config": "^10.8.0", "@npmcli/fs": "^5.0.0", "@npmcli/map-workspaces": "^5.0.3", "@npmcli/metavuln-calculator": "^9.0.3", "@npmcli/package-json": "^7.0.5", "@npmcli/promise-spawn": "^9.0.1", "@npmcli/redact": "^4.0.0", "@npmcli/run-script": "^10.0.4", "@sigstore/tuf": "^4.0.2", "abbrev": "^4.0.0", "archy": "~1.0.0", "cacache": "^20.0.4", "chalk": "^5.6.2", "ci-info": "^4.4.0", "fastest-levenshtein": "^1.0.16", "fs-minipass": "^3.0.3", "glob": "^13.0.6", "graceful-fs": "^4.2.11", "hosted-git-info": "^9.0.2", "ini": "^6.0.0", "init-package-json": "^8.2.5", "is-cidr": "^6.0.3", "json-parse-even-better-errors": "^5.0.0", "libnpmaccess": "^10.0.3", "libnpmdiff": "^8.1.5", "libnpmexec": "^10.2.5", "libnpmfund": "^7.0.19", "libnpmorg": "^8.0.1", "libnpmpack": "^9.1.5", "libnpmpublish": "^11.1.3", "libnpmsearch": "^9.0.1", "libnpmteam": "^8.0.2", "libnpmversion": "^8.0.3", "make-fetch-happen": "^15.0.5", "minimatch": "^10.2.4", "minipass": "^7.1.3", "minipass-pipeline": "^1.2.4", "ms": "^2.1.2", "node-gyp": "^12.2.0", "nopt": "^9.0.0", "npm-audit-report": "^7.0.0", "npm-install-checks": "^8.0.0", "npm-package-arg": "^13.0.2", "npm-pick-manifest": "^11.0.3", "npm-profile": "^12.0.1", "npm-registry-fetch": "^19.1.1", "npm-user-validate": "^4.0.0", "p-map": "^7.0.4", "pacote": "^21.5.0", "parse-conflict-json": "^5.0.1", "proc-log": "^6.1.0", "qrcode-terminal": "^0.12.0", "read": "^5.0.1", "semver": "^7.7.4", "spdx-expression-parse": "^4.0.0", "ssri": "^13.0.1", "supports-color": "^10.2.2", "tar": "^7.5.11", "text-table": "~0.2.0", "tiny-relative-date": "^2.0.2", "treeverse": "^3.0.0", "validate-npm-package-name": "^7.0.2", "which": "^6.0.1" }, "bin": { "npm": "bin/npm-cli.js", "npx": "bin/npx-cli.js" } }, "sha512-xPhOap4ZbJWyd7DAOukP564WFwNSGu/2FeTRFHhiiKthcauxhH/NpkJAQm24xD+cAn8av5tQ00phi98DqtfLsg=="], + "npm": ["npm@11.12.1", "", { "dependencies": { "@isaacs/string-locale-compare": "^1.1.0", "@npmcli/arborist": "^9.4.2", "@npmcli/config": "^10.8.1", "@npmcli/fs": "^5.0.0", "@npmcli/map-workspaces": "^5.0.3", "@npmcli/metavuln-calculator": "^9.0.3", "@npmcli/package-json": "^7.0.5", "@npmcli/promise-spawn": "^9.0.1", "@npmcli/redact": "^4.0.0", "@npmcli/run-script": "^10.0.4", "@sigstore/tuf": "^4.0.2", "abbrev": "^4.0.0", "archy": "~1.0.0", "cacache": "^20.0.4", "chalk": "^5.6.2", "ci-info": "^4.4.0", "fastest-levenshtein": "^1.0.16", "fs-minipass": "^3.0.3", "glob": "^13.0.6", "graceful-fs": "^4.2.11", "hosted-git-info": "^9.0.2", "ini": "^6.0.0", "init-package-json": "^8.2.5", "is-cidr": "^6.0.3", "json-parse-even-better-errors": "^5.0.0", "libnpmaccess": "^10.0.3", "libnpmdiff": "^8.1.5", "libnpmexec": "^10.2.5", "libnpmfund": "^7.0.19", "libnpmorg": "^8.0.1", "libnpmpack": "^9.1.5", "libnpmpublish": "^11.1.3", "libnpmsearch": "^9.0.1", "libnpmteam": "^8.0.2", "libnpmversion": "^8.0.3", "make-fetch-happen": "^15.0.5", "minimatch": "^10.2.4", "minipass": "^7.1.3", "minipass-pipeline": "^1.2.4", "ms": "^2.1.2", "node-gyp": "^12.2.0", "nopt": "^9.0.0", "npm-audit-report": "^7.0.0", "npm-install-checks": "^8.0.0", "npm-package-arg": "^13.0.2", "npm-pick-manifest": "^11.0.3", "npm-profile": "^12.0.1", "npm-registry-fetch": "^19.1.1", "npm-user-validate": "^4.0.0", "p-map": "^7.0.4", "pacote": "^21.5.0", "parse-conflict-json": "^5.0.1", "proc-log": "^6.1.0", "qrcode-terminal": "^0.12.0", "read": "^5.0.1", "semver": "^7.7.4", "spdx-expression-parse": "^4.0.0", "ssri": "^13.0.1", "supports-color": "^10.2.2", "tar": "^7.5.11", "text-table": "~0.2.0", "tiny-relative-date": "^2.0.2", "treeverse": "^3.0.0", "validate-npm-package-name": "^7.0.2", "which": "^6.0.1" }, "bin": { "npm": "bin/npm-cli.js", "npx": "bin/npx-cli.js" } }, "sha512-zcoUuF1kezGSAo0CqtvoLXX3mkRqzuqYdL6Y5tdo8g69NVV3CkjQ6ZBhBgB4d7vGkPcV6TcvLi3GRKPDFX+xTA=="], "nth-check": ["nth-check@2.1.1", "", { "dependencies": { "boolbase": "^1.0.0" } }, "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w=="], @@ -1418,7 +1418,7 @@ "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="], - "picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="], + "picomatch": ["picomatch@4.0.4", "", {}, "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A=="], "pify": ["pify@2.3.0", "", {}, "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog=="], @@ -1538,7 +1538,7 @@ "semver": ["semver@7.7.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="], - "serialize-javascript": ["serialize-javascript@7.0.4", "", {}, "sha512-DuGdB+Po43Q5Jxwpzt1lhyFSYKryqoNjQSA9M92tyw0lyHIOur+XCalOUe0KTJpyqzT8+fQ5A0Jf7vCx/NKmIg=="], + "serialize-javascript": ["serialize-javascript@7.0.5", "", {}, "sha512-F4LcB0UqUl1zErq+1nYEEzSHJnIwb3AF2XWB94b+afhrekOUijwooAYqFyRbjYkm2PAKBabx6oYv/xDxNi8IBw=="], "set-blocking": ["set-blocking@2.0.0", "", {}, "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw=="], @@ -1550,7 +1550,7 @@ "set-value": ["set-value@4.1.0", "", { "dependencies": { "is-plain-object": "^2.0.4", "is-primitive": "^3.0.1" } }, "sha512-zTEg4HL0RwVrqcWs3ztF+x1vkxfm0lP+MQQFPiMJTKVceBwEV0A569Ou8l9IYQG8jOZdMVI1hGsc0tmeD2o/Lw=="], - "shaka-player": ["shaka-player@5.0.7", "", {}, "sha512-dUcGDac2yRJsgLSwdYqkaOLu9X8Ih+skE5tC4odUuKtNVRCLp/FaKfXydcusRcnkHWhGZN8rG8+HTJQJs7HN1g=="], + "shaka-player": ["shaka-player@5.0.8", "", {}, "sha512-f886rKRvQ0IKhWGk+rINS++YTjTJyc4DT5YypTsHW6wiNV9fiHi2n35+lg5R+hj9RfhqkmJHMjJb3gprUTNa8w=="], "sharp": ["sharp@0.32.6", "", { "dependencies": { "color": "^4.2.3", "detect-libc": "^2.0.2", "node-addon-api": "^6.1.0", "prebuild-install": "^7.1.1", "semver": "^7.5.4", "simple-get": "^4.0.1", "tar-fs": "^3.0.4", "tunnel-agent": "^0.6.0" } }, "sha512-KyLTWwgcR9Oe4d9HwCwNM2l7+J0dUQwn/yf7S0EnTtb0eVS4RxO0eUSvxPtzT4F3SY+C4K6fqdv/DO27sJ/v/w=="], @@ -1662,7 +1662,7 @@ "table": ["table@6.9.0", "", { "dependencies": { "ajv": "^8.0.1", "lodash.truncate": "^4.4.2", "slice-ansi": "^4.0.0", "string-width": "^4.2.3", "strip-ansi": "^6.0.1" } }, "sha512-9kY+CygyYM6j02t5YFHbNz2FN5QmYGv9zAjVp4lCDjlCw7amdckXlEt/bjMhUIfj4ThGRE4gCUH5+yGnNuPo5A=="], - "tar": ["tar@7.5.12", "", { "dependencies": { "@isaacs/fs-minipass": "^4.0.0", "chownr": "^3.0.0", "minipass": "^7.1.2", "minizlib": "^3.1.0", "yallist": "^5.0.0" } }, "sha512-9TsuLcdhOn4XztcQqhNyq1KOwOOED/3k58JAvtULiYqbO8B/0IBAAIE1hj0Svmm58k27TmcigyDI0deMlgG3uw=="], + "tar": ["tar@7.5.13", "", { "dependencies": { "@isaacs/fs-minipass": "^4.0.0", "chownr": "^3.0.0", "minipass": "^7.1.2", "minizlib": "^3.1.0", "yallist": "^5.0.0" } }, "sha512-tOG/7GyXpFevhXVh8jOPJrmtRpOTsYqUIkVdVooZYJS/z8WhfQUX8RJILmeuJNinGAMSu1veBr4asSHFt5/hng=="], "tar-fs": ["tar-fs@3.1.2", "", { "dependencies": { "pump": "^3.0.0", "tar-stream": "^3.1.5" }, "optionalDependencies": { "bare-fs": "^4.0.1", "bare-path": "^3.0.0" } }, "sha512-QGxxTxxyleAdyM3kpFs14ymbYmNFrfY+pHj7Z8FgtbZ7w2//VAgLMac7sT6nRpIHjppXO2AwwEOg0bPFVRcmXw=="], @@ -1912,8 +1912,6 @@ "@capacitor/cli/tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], - "@capacitor/core/tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], - "@electron/asar/commander": ["commander@5.1.0", "", {}, "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg=="], "@electron/asar/glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="], @@ -1986,7 +1984,7 @@ "@rollup/pluginutils/@types/estree": ["@types/estree@0.0.39", "", {}, "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw=="], - "@rollup/pluginutils/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], + "@rollup/pluginutils/picomatch": ["picomatch@2.3.2", "", {}, "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA=="], "@rollup/pluginutils/rollup": ["rollup@2.80.0", "", { "optionalDependencies": { "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-cIFJOD1DESzpjOBl763Kp1AH7UE/0fcdHe6rZXUdQ9c50uvgigvW97u3IcSeBwOkgqL/PXPBktBCh0KEu5L8XQ=="], @@ -2066,7 +2064,7 @@ "mergexml/xpath": ["xpath@0.0.27", "", {}, "sha512-fg03WRxtkCV6ohClePNAECYsmpKKTv5L8y/X3Dn1hQrec3POx2jHZ/0P2qQ6HvsrU1BmeqXcof3NGGueG6LxwQ=="], - "micromatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], + "micromatch/picomatch": ["picomatch@2.3.2", "", {}, "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA=="], "miniflare/sharp": ["sharp@0.34.5", "", { "dependencies": { "@img/colour": "^1.0.0", "detect-libc": "^2.1.2", "semver": "^7.7.3" }, "optionalDependencies": { "@img/sharp-darwin-arm64": "0.34.5", "@img/sharp-darwin-x64": "0.34.5", "@img/sharp-libvips-darwin-arm64": "1.2.4", "@img/sharp-libvips-darwin-x64": "1.2.4", "@img/sharp-libvips-linux-arm": "1.2.4", "@img/sharp-libvips-linux-arm64": "1.2.4", "@img/sharp-libvips-linux-ppc64": "1.2.4", "@img/sharp-libvips-linux-riscv64": "1.2.4", "@img/sharp-libvips-linux-s390x": "1.2.4", "@img/sharp-libvips-linux-x64": "1.2.4", "@img/sharp-libvips-linuxmusl-arm64": "1.2.4", "@img/sharp-libvips-linuxmusl-x64": "1.2.4", "@img/sharp-linux-arm": "0.34.5", "@img/sharp-linux-arm64": "0.34.5", "@img/sharp-linux-ppc64": "0.34.5", "@img/sharp-linux-riscv64": "0.34.5", "@img/sharp-linux-s390x": "0.34.5", "@img/sharp-linux-x64": "0.34.5", "@img/sharp-linuxmusl-arm64": "0.34.5", "@img/sharp-linuxmusl-x64": "0.34.5", "@img/sharp-wasm32": "0.34.5", "@img/sharp-win32-arm64": "0.34.5", "@img/sharp-win32-ia32": "0.34.5", "@img/sharp-win32-x64": "0.34.5" } }, "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg=="], @@ -2090,7 +2088,7 @@ "npm/@npmcli/arborist": ["@npmcli/arborist@9.4.2", "", { "dependencies": { "@gar/promise-retry": "^1.0.0", "@isaacs/string-locale-compare": "^1.1.0", "@npmcli/fs": "^5.0.0", "@npmcli/installed-package-contents": "^4.0.0", "@npmcli/map-workspaces": "^5.0.0", "@npmcli/metavuln-calculator": "^9.0.2", "@npmcli/name-from-folder": "^4.0.0", "@npmcli/node-gyp": "^5.0.0", "@npmcli/package-json": "^7.0.0", "@npmcli/query": "^5.0.0", "@npmcli/redact": "^4.0.0", "@npmcli/run-script": "^10.0.0", "bin-links": "^6.0.0", "cacache": "^20.0.1", "common-ancestor-path": "^2.0.0", "hosted-git-info": "^9.0.0", "json-stringify-nice": "^1.1.4", "lru-cache": "^11.2.1", "minimatch": "^10.0.3", "nopt": "^9.0.0", "npm-install-checks": "^8.0.0", "npm-package-arg": "^13.0.0", "npm-pick-manifest": "^11.0.1", "npm-registry-fetch": "^19.0.0", "pacote": "^21.0.2", "parse-conflict-json": "^5.0.1", "proc-log": "^6.0.0", "proggy": "^4.0.0", "promise-all-reject-late": "^1.0.0", "promise-call-limit": "^3.0.1", "semver": "^7.3.7", "ssri": "^13.0.0", "treeverse": "^3.0.0", "walk-up-path": "^4.0.0" }, "bundled": true, "bin": { "arborist": "bin/index.js" } }, "sha512-omJgPyzt11cEGrxzgrECoOyxAunmPMgBFTcAB/FbaB+9iOYhGmRdsQqySV8o0LWQ/l2kTeASUIMR4xJufVwmtw=="], - "npm/@npmcli/config": ["@npmcli/config@10.8.0", "", { "dependencies": { "@npmcli/map-workspaces": "^5.0.0", "@npmcli/package-json": "^7.0.0", "ci-info": "^4.0.0", "ini": "^6.0.0", "nopt": "^9.0.0", "proc-log": "^6.0.0", "semver": "^7.3.5", "walk-up-path": "^4.0.0" }, "bundled": true }, "sha512-YkhoXZQU7zxyGi3V7J0zdK2pghzF9YXHiRdpRX8QNhsefk/zAJZJjRsbbw1hD67hlMp2gSygUGgW4y7FlrUThw=="], + "npm/@npmcli/config": ["@npmcli/config@10.8.1", "", { "dependencies": { "@npmcli/map-workspaces": "^5.0.0", "@npmcli/package-json": "^7.0.0", "ci-info": "^4.0.0", "ini": "^6.0.0", "nopt": "^9.0.0", "proc-log": "^6.0.0", "semver": "^7.3.5", "walk-up-path": "^4.0.0" }, "bundled": true }, "sha512-MAYk9IlIGiyC0c9fnjdBSQfIFPZT0g1MfeSiD1UXTq2zJOLX55jS9/sETJHqw/7LN18JjITrhYfgCfapbmZHiQ=="], "npm/@npmcli/fs": ["@npmcli/fs@5.0.0", "", { "dependencies": { "semver": "^7.3.5" }, "bundled": true }, "sha512-7OsC1gNORBEawOa5+j2pXN9vsicaIOH5cPXxoR6fJOmH6/EXpJB2CajXOu1fPRFun2m1lktEFX11+P89hqO/og=="], @@ -2146,7 +2144,7 @@ "npm/binary-extensions": ["binary-extensions@3.1.0", "", {}, "sha512-Jvvd9hy1w+xUad8+ckQsWA/V1AoyubOvqn0aygjMOVM4BfIaRav1NFS3LsTSDaV4n4FtcCtQXvzep1E6MboqwQ=="], - "npm/brace-expansion": ["brace-expansion@5.0.4", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg=="], + "npm/brace-expansion": ["brace-expansion@5.0.5", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ=="], "npm/cacache": ["cacache@20.0.4", "", { "dependencies": { "@npmcli/fs": "^5.0.0", "fs-minipass": "^3.0.0", "glob": "^13.0.0", "lru-cache": "^11.1.0", "minipass": "^7.0.3", "minipass-collect": "^2.0.1", "minipass-flush": "^1.0.5", "minipass-pipeline": "^1.2.4", "p-map": "^7.0.2", "ssri": "^13.0.0" }, "bundled": true }, "sha512-M3Lab8NPYlZU2exsL3bMVvMrMqgwCnMWfdZbK28bn3pK6APT/Te/I8hjRPNu1uwORY9a1eEQoifXbKPQMfMTOA=="], @@ -2166,7 +2164,7 @@ "npm/debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="], - "npm/diff": ["diff@8.0.3", "", {}, "sha512-qejHi7bcSD4hQAZE0tNAawRK1ZtafHDmMTMkrrIGgSLl7hTnQHmKCeB45xAcbfTqK2zowkM3j3bHt/4b/ARbYQ=="], + "npm/diff": ["diff@8.0.4", "", {}, "sha512-DPi0FmjiSU5EvQV0++GFDOJ9ASQUVFh5kD+OzOnYdi7n3Wpm9hWWGfB/O2blfHcMVTL5WkQXSnRiK9makhrcnw=="], "npm/env-paths": ["env-paths@2.2.1", "", {}, "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A=="], @@ -2246,7 +2244,7 @@ "npm/minipass-fetch": ["minipass-fetch@5.0.2", "", { "dependencies": { "minipass": "^7.0.3", "minipass-sized": "^2.0.0", "minizlib": "^3.0.1" }, "optionalDependencies": { "iconv-lite": "^0.7.2" } }, "sha512-2d0q2a8eCi2IRg/IGubCNRJoYbA1+YPXAzQVRFmB45gdGZafyivnZ5YSEfo3JikbjGxOdntGFvBQGqaSMXlAFQ=="], - "npm/minipass-flush": ["minipass-flush@1.0.5", "", { "dependencies": { "minipass": "^3.0.0" } }, "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw=="], + "npm/minipass-flush": ["minipass-flush@1.0.7", "", { "dependencies": { "minipass": "^3.0.0" } }, "sha512-TbqTz9cUwWyHS2Dy89P3ocAGUGxKjjLuR9z8w4WUTGAVgEj17/4nhgo2Du56i0Fm3Pm30g4iA8Lcqctc76jCzA=="], "npm/minipass-pipeline": ["minipass-pipeline@1.2.4", "", { "dependencies": { "minipass": "^3.0.0" }, "bundled": true }, "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A=="], @@ -2292,7 +2290,7 @@ "npm/path-scurry": ["path-scurry@2.0.2", "", { "dependencies": { "lru-cache": "^11.0.0", "minipass": "^7.1.2" } }, "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg=="], - "npm/picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="], + "npm/picomatch": ["picomatch@4.0.4", "", {}, "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A=="], "npm/postcss-selector-parser": ["postcss-selector-parser@7.1.1", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg=="], @@ -2336,7 +2334,7 @@ "npm/supports-color": ["supports-color@10.2.2", "", { "bundled": true }, "sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g=="], - "npm/tar": ["tar@7.5.12", "", { "dependencies": { "@isaacs/fs-minipass": "^4.0.0", "chownr": "^3.0.0", "minipass": "^7.1.2", "minizlib": "^3.1.0", "yallist": "^5.0.0" }, "bundled": true }, "sha512-9TsuLcdhOn4XztcQqhNyq1KOwOOED/3k58JAvtULiYqbO8B/0IBAAIE1hj0Svmm58k27TmcigyDI0deMlgG3uw=="], + "npm/tar": ["tar@7.5.13", "", { "dependencies": { "@isaacs/fs-minipass": "^4.0.0", "chownr": "^3.0.0", "minipass": "^7.1.2", "minizlib": "^3.1.0", "yallist": "^5.0.0" }, "bundled": true }, "sha512-tOG/7GyXpFevhXVh8jOPJrmtRpOTsYqUIkVdVooZYJS/z8WhfQUX8RJILmeuJNinGAMSu1veBr4asSHFt5/hng=="], "npm/text-table": ["text-table@0.2.0", "", { "bundled": true }, "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw=="], @@ -2516,7 +2514,7 @@ "eslint/debug/ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], - "filelist/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="], + "filelist/minimatch/brace-expansion": ["brace-expansion@2.0.3", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA=="], "fs-minipass/minipass/yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="], @@ -2538,7 +2536,7 @@ "git-semver-tags/meow/yargs-parser": ["yargs-parser@20.2.9", "", {}, "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w=="], - "glob/minimatch/brace-expansion": ["brace-expansion@5.0.4", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg=="], + "glob/minimatch/brace-expansion": ["brace-expansion@5.0.5", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ=="], "hosted-git-info/lru-cache/yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="], @@ -2580,7 +2578,7 @@ "stylelint/debug/ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], - "stylelint/file-entry-cache/flat-cache": ["flat-cache@6.1.21", "", { "dependencies": { "cacheable": "^2.3.3", "flatted": "^3.4.1", "hookified": "^1.15.0" } }, "sha512-2u7cJfSf7Th7NxEk/VzQjnPoglok2YCsevS7TSbJjcDQWJPbqUUnSYtriHSvtnq+fRZHy1s0ugk4ApnQyhPGoQ=="], + "stylelint/file-entry-cache/flat-cache": ["flat-cache@6.1.22", "", { "dependencies": { "cacheable": "^2.3.4", "flatted": "^3.4.2", "hookified": "^1.15.0" } }, "sha512-N2dnzVJIphnNsjHcrxGW7DePckJ6haPrSFqpsBUhHYgwtKGVq4JrBGielEGD2fCVnsGm1zlBVZ8wGhkyuetgug=="], "table/ajv/json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="], @@ -2666,7 +2664,7 @@ "replace/yargs/find-up/locate-path": ["locate-path@5.0.0", "", { "dependencies": { "p-locate": "^4.1.0" } }, "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g=="], - "workbox-build/glob/minimatch/brace-expansion": ["brace-expansion@5.0.4", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg=="], + "workbox-build/glob/minimatch/brace-expansion": ["brace-expansion@5.0.5", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ=="], "@capacitor/assets/@capacitor/cli/rimraf/glob/minimatch": ["minimatch@8.0.7", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-V+1uQNdzybxa14e/p00HZnQNNcTjnRJjDxg2V8wtkjFctq4M7hXFws4oekyTP0Jebeq7QYtpFyOeBAjc88zvYg=="], @@ -2710,7 +2708,7 @@ "workbox-build/glob/minimatch/brace-expansion/balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="], - "@capacitor/assets/@capacitor/cli/rimraf/glob/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="], + "@capacitor/assets/@capacitor/cli/rimraf/glob/minimatch/brace-expansion": ["brace-expansion@2.0.3", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA=="], "@capacitor/assets/@capacitor/cli/rimraf/glob/path-scurry/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="], diff --git a/index.html b/index.html index 285c072..6e0c766 100644 --- a/index.html +++ b/index.html @@ -3689,16 +3689,6 @@
-
-
- Music Provider - Default service for searching and streaming -
- -
Streaming Quality diff --git a/js/music-api.js b/js/music-api.js index a608c10..33d0ff4 100644 --- a/js/music-api.js +++ b/js/music-api.js @@ -1,8 +1,6 @@ // js/music-api.js -// Unified API wrapper that supports both Tidal and Qobuz import { LosslessAPI } from './api.js'; -import { QobuzAPI } from './qobuz-api.js'; import { PodcastsAPI } from './podcasts-api.js'; import { musicProviderSettings } from './storage.js'; @@ -18,7 +16,6 @@ export class MusicAPI { /** @private */ constructor(settings) { this.tidalAPI = new LosslessAPI(settings); - this.qobuzAPI = new QobuzAPI(); this.podcastsAPI = new PodcastsAPI(); this._settings = settings; this.videoArtworkCache = new Map(); @@ -39,14 +36,12 @@ export class MusicAPI { // Get the appropriate API based on provider getAPI(provider = null) { - const p = provider || this.getCurrentProvider(); - return p === 'qobuz' ? this.qobuzAPI : this.tidalAPI; + return this.tidalAPI; } // Search methods async search(query, options = {}) { - const provider = options.provider || this.getCurrentProvider(); - const api = this.getAPI(provider); + const api = this.getAPI(); if (typeof api.search === 'function') { return api.search(query, options); } @@ -70,31 +65,22 @@ export class MusicAPI { } async searchTracks(query, options = {}) { - const provider = options.provider || this.getCurrentProvider(); - return this.getAPI(provider).searchTracks(query, options); + return this.getAPI().searchTracks(query, options); } async searchArtists(query, options = {}) { - const provider = options.provider || this.getCurrentProvider(); - return this.getAPI(provider).searchArtists(query, options); + return this.getAPI().searchArtists(query, options); } async searchAlbums(query, options = {}) { - const provider = options.provider || this.getCurrentProvider(); - return this.getAPI(provider).searchAlbums(query, options); + return this.getAPI().searchAlbums(query, options); } async searchPlaylists(query, options = {}) { - const provider = options.provider || this.getCurrentProvider(); - if (provider === 'qobuz') { - // Qobuz doesn't support playlist search, return empty - return { items: [], limit: 0, offset: 0, totalNumberOfItems: 0 }; - } return this.tidalAPI.searchPlaylists(query, options); } async searchVideos(query, options = {}) { - const provider = options.provider || this.getCurrentProvider(); return this.tidalAPI.searchVideos(query, options); } @@ -116,38 +102,31 @@ export class MusicAPI { // Get methods async getTrack(id, quality, provider = null) { - const p = provider || this.getProviderFromId(id) || this.getCurrentProvider(); - const api = this.getAPI(p); + const api = this.getAPI(); const cleanId = this.stripProviderPrefix(id); return api.getTrack(cleanId, quality); } async getTrackMetadata(id, provider = null) { - const p = provider || this.getProviderFromId(id) || this.getCurrentProvider(); - const api = this.getAPI(p); + const api = this.getAPI(); const cleanId = this.stripProviderPrefix(id); return api.getTrackMetadata(cleanId); } async getAlbum(id, provider = null) { - const p = provider || this.getProviderFromId(id) || this.getCurrentProvider(); - const api = this.getAPI(p); + const api = this.getAPI(); const cleanId = this.stripProviderPrefix(id); return api.getAlbum(cleanId); } async getArtist(id, provider = null) { - const p = provider || this.getProviderFromId(id) || this.getCurrentProvider(); - const api = this.getAPI(p); + const api = this.getAPI(); const cleanId = this.stripProviderPrefix(id); return api.getArtist(cleanId); } async getArtistBiography(id, provider = null) { - const p = provider || this.getProviderFromId(id) || this.getCurrentProvider(); - if (p !== 'tidal') return null; // Biography only supported for Tidal - - const api = this.getAPI(p); + const api = this.getAPI(); const cleanId = this.stripProviderPrefix(id); if (typeof api.getArtistBiography === 'function') { return api.getArtistBiography(cleanId); @@ -156,15 +135,13 @@ export class MusicAPI { } async getVideo(id, provider = null) { - const p = provider || this.getProviderFromId(id) || this.getCurrentProvider(); - const api = this.getAPI(p); + const api = this.getAPI(); const cleanId = this.stripProviderPrefix(id); return api.getVideo(cleanId); } async getVideoStreamUrl(id, provider = null) { - const p = provider || this.getProviderFromId(id) || this.getCurrentProvider(); - const api = this.getAPI(p); + const api = this.getAPI(); const cleanId = this.stripProviderPrefix(id); if (typeof api.getVideoStreamUrl === 'function') { return api.getVideoStreamUrl(cleanId); @@ -186,8 +163,7 @@ export class MusicAPI { } async getTrackRecommendations(id) { - const p = this.getProviderFromId(id) || this.getCurrentProvider(); - const api = this.getAPI(p); + const api = this.getAPI(); const cleanId = this.stripProviderPrefix(id); if (typeof api.getTrackRecommendations === 'function') { return api.getTrackRecommendations(cleanId); @@ -197,8 +173,7 @@ export class MusicAPI { // Stream methods async getStreamUrl(id, quality, provider = null) { - const p = provider || this.getProviderFromId(id) || this.getCurrentProvider(); - const api = this.getAPI(p); + const api = this.getAPI(); const cleanId = this.stripProviderPrefix(id); return api.getStreamUrl(cleanId, quality); } @@ -208,10 +183,7 @@ export class MusicAPI { if (typeof id === 'string' && id.startsWith('blob:')) { return id; } - if (typeof id === 'string' && id.startsWith('q:')) { - return this.qobuzAPI.getCoverUrl(id.slice(2), size); - } - return this.tidalAPI.getCoverUrl(id, size); + return this.tidalAPI.getCoverUrl(this.stripProviderPrefix(id), size); } getVideoCoverUrl(imageId, size = '1280') { @@ -221,10 +193,7 @@ export class MusicAPI { if (typeof imageId === 'string' && imageId.startsWith('blob:')) { return imageId; } - if (typeof imageId === 'string' && imageId.startsWith('q:')) { - return null; - } - return this.tidalAPI.getVideoCoverUrl(imageId, size); + return this.tidalAPI.getVideoCoverUrl(this.stripProviderPrefix(imageId), size); } async getVideoArtwork(title, artist) { @@ -251,10 +220,7 @@ export class MusicAPI { } getArtistPictureUrl(id, size = '320') { - if (typeof id === 'string' && id.startsWith('q:')) { - return this.qobuzAPI.getArtistPictureUrl(id.slice(2), size); - } - return this.tidalAPI.getArtistPictureUrl(id, size); + return this.tidalAPI.getArtistPictureUrl(this.stripProviderPrefix(id), size); } extractStreamUrlFromManifest(manifest) { @@ -264,7 +230,6 @@ export class MusicAPI { // Helper methods getProviderFromId(id) { if (typeof id === 'string') { - if (id.startsWith('q:')) return 'qobuz'; if (id.startsWith('t:')) return 'tidal'; } return null; @@ -281,16 +246,14 @@ export class MusicAPI { // Download methods async downloadTrack(id, quality, filename, options = {}) { - const provider = this.getProviderFromId(id) || this.getCurrentProvider(); - const api = this.getAPI(provider); + const api = this.getAPI(); const cleanId = this.stripProviderPrefix(id); return api.downloadTrack(cleanId, quality, filename, options); } // Similar/recommendation methods async getSimilarArtists(artistId) { - const provider = this.getProviderFromId(artistId) || this.getCurrentProvider(); - const api = this.getAPI(provider); + const api = this.getAPI(); const cleanId = this.stripProviderPrefix(artistId); return api.getSimilarArtists(cleanId); } @@ -300,8 +263,7 @@ export class MusicAPI { } async getSimilarAlbums(albumId) { - const provider = this.getProviderFromId(albumId) || this.getCurrentProvider(); - const api = this.getAPI(provider); + const api = this.getAPI(); const cleanId = this.stripProviderPrefix(albumId); return api.getSimilarAlbums(cleanId); } @@ -314,7 +276,6 @@ export class MusicAPI { // Cache methods async clearCache() { await this.tidalAPI.clearCache(); - // Qobuz doesn't have cache yet } getCacheStats() { @@ -326,3 +287,5 @@ export class MusicAPI { return this._settings; } } + +export const musicAPI = new MusicAPI(); diff --git a/js/player.js b/js/player.js index ac438c0..4f53f1a 100644 --- a/js/player.js +++ b/js/player.js @@ -943,51 +943,36 @@ export class Player { await this.safePlay(activeElement); } else { - const isQobuz = String(track.id).startsWith('q:'); + // Tidal: Try to get ReplayGain from manifest first, supplement with track info if needed + const streamInfoPromise = this.preloadCache.has(track.id) + ? Promise.resolve(this.preloadCache.get(track.id)) + : this.api.getStreamUrl(track.id, this.quality); - if (isQobuz) { - // Qobuz: skip getTrack call, directly fetch stream URL - this.currentRgValues = null; + // We only need the legacy track info if we missed getting ReplayGain from the manifest endpoint + const resolvedStreamInfo = await streamInfoPromise; + if (this.playbackSequence !== currentSequence) return; + + streamUrl = resolvedStreamInfo.url; + + if (resolvedStreamInfo.rgInfo) { + this.currentRgValues = resolvedStreamInfo.rgInfo; this.applyReplayGain(); - - if (this.preloadCache.has(track.id)) { - streamUrl = this.preloadCache.get(track.id).url; - } else { - const streamInfo = await this.api.getStreamUrl(track.id, this.quality); - streamUrl = streamInfo.url; - } } else { - // Tidal: Try to get ReplayGain from manifest first, supplement with track info if needed - const streamInfoPromise = this.preloadCache.has(track.id) - ? Promise.resolve(this.preloadCache.get(track.id)) - : this.api.getStreamUrl(track.id, this.quality); - - // We only need the legacy track info if we missed getting ReplayGain from the manifest endpoint - const resolvedStreamInfo = await streamInfoPromise; + // Fallback to legacy metadata if manifest lacked normalization data + const trackData = await this.api.getTrack(track.id, this.quality).catch(() => null); if (this.playbackSequence !== currentSequence) return; - streamUrl = resolvedStreamInfo.url; - - if (resolvedStreamInfo.rgInfo) { - this.currentRgValues = resolvedStreamInfo.rgInfo; - this.applyReplayGain(); + if (trackData && trackData.info) { + this.currentRgValues = { + trackReplayGain: trackData.info.trackReplayGain, + trackPeakAmplitude: trackData.info.trackPeakAmplitude, + albumReplayGain: trackData.info.albumReplayGain, + albumPeakAmplitude: trackData.info.albumPeakAmplitude, + }; } else { - // Fallback to legacy metadata if manifest lacked normalization data - const trackData = await this.api.getTrack(track.id, this.quality).catch(() => null); - if (this.playbackSequence !== currentSequence) return; - - if (trackData && trackData.info) { - this.currentRgValues = { - trackReplayGain: trackData.info.trackReplayGain, - trackPeakAmplitude: trackData.info.trackPeakAmplitude, - albumReplayGain: trackData.info.albumReplayGain, - albumPeakAmplitude: trackData.info.albumPeakAmplitude, - }; - } else { - this.currentRgValues = null; - } - this.applyReplayGain(); + this.currentRgValues = null; } + this.applyReplayGain(); } if (this.playbackSequence !== currentSequence) return; diff --git a/js/qobuz-api.js b/js/qobuz-api.js deleted file mode 100644 index 23e0830..0000000 --- a/js/qobuz-api.js +++ /dev/null @@ -1,412 +0,0 @@ -// js/qobuz-api.js -// Qobuz API integration for Monochrome Music - -// LMFAOOOO this shit is useless now qobuz killing accounts every time a dude takes their breath - -const QOBUZ_API_BASE = 'https://qobuz.squid.wtf/api'; - -export class QobuzAPI { - constructor() { - this.baseUrl = QOBUZ_API_BASE; - } - - async fetchWithRetry(endpoint, options = {}) { - const url = `${this.baseUrl}${endpoint}`; - - try { - const response = await fetch(url, { signal: options.signal }); - - if (!response.ok) { - throw new Error(`Request failed with status ${response.status}`); - } - - const data = await response.json(); - return data; - } catch (error) { - if (error.name === 'AbortError') throw error; - console.error('Qobuz API request failed:', error); - throw error; - } - } - - // Search tracks - async searchTracks(query, options = {}) { - try { - const offset = options.offset || 0; - const limit = options.limit || 10; - const data = await this.fetchWithRetry( - `/get-music?q=${encodeURIComponent(query)}&offset=${offset}&limit=${limit}` - ); - - if (!data.success || !data.data) { - return { items: [], limit: 0, offset: 0, totalNumberOfItems: 0 }; - } - - // Transform Qobuz tracks to match Tidal format - const tracks = (data.data.tracks?.items || []).map((track) => this.transformTrack(track)); - - return { - items: tracks, - limit: data.data.tracks?.limit || tracks.length, - offset: data.data.tracks?.offset || 0, - totalNumberOfItems: data.data.tracks?.total || tracks.length, - }; - } catch (error) { - if (error.name === 'AbortError') throw error; - console.error('Qobuz track search failed:', error); - return { items: [], limit: 0, offset: 0, totalNumberOfItems: 0 }; - } - } - - // Search albums - async searchAlbums(query, options = {}) { - try { - const offset = options.offset || 0; - const limit = options.limit || 10; - const data = await this.fetchWithRetry( - `/get-music?q=${encodeURIComponent(query)}&offset=${offset}&limit=${limit}` - ); - - if (!data.success || !data.data) { - return { items: [], limit: 0, offset: 0, totalNumberOfItems: 0 }; - } - - // Transform Qobuz albums to match Tidal format - const albums = (data.data.albums?.items || []).map((album) => this.transformAlbum(album)); - - return { - items: albums, - limit: data.data.albums?.limit || albums.length, - offset: data.data.albums?.offset || 0, - totalNumberOfItems: data.data.albums?.total || albums.length, - }; - } catch (error) { - if (error.name === 'AbortError') throw error; - console.error('Qobuz album search failed:', error); - return { items: [], limit: 0, offset: 0, totalNumberOfItems: 0 }; - } - } - - // Search artists - async searchArtists(query, options = {}) { - try { - const offset = options.offset || 0; - const limit = options.limit || 10; - const data = await this.fetchWithRetry( - `/get-music?q=${encodeURIComponent(query)}&offset=${offset}&limit=${limit}` - ); - - if (!data.success || !data.data) { - return { items: [], limit: 0, offset: 0, totalNumberOfItems: 0 }; - } - - // Transform Qobuz artists to match Tidal format - const artists = (data.data.artists?.items || []).map((artist) => this.transformArtist(artist)); - - return { - items: artists, - limit: data.data.artists?.limit || artists.length, - offset: data.data.artists?.offset || 0, - totalNumberOfItems: data.data.artists?.total || artists.length, - }; - } catch (error) { - if (error.name === 'AbortError') throw error; - console.error('Qobuz artist search failed:', error); - return { items: [], limit: 0, offset: 0, totalNumberOfItems: 0 }; - } - } - - // Get track details - async getTrack(_id) { - // Qobuz doesn't have a direct track endpoint - // Track metadata comes from search/album endpoints - // For playback, use getStreamUrl directly - throw new Error('Qobuz getTrack not implemented - use getStreamUrl for playback'); - } - - // Get album details - async getAlbum(id) { - try { - const data = await this.fetchWithRetry(`/get-album?album_id=${encodeURIComponent(id)}`); - - if (!data.success || !data.data) { - throw new Error('Album not found'); - } - - const album = this.transformAlbum(data.data); - const tracks = (data.data.tracks?.items || []).map((track) => this.transformTrack(track, data.data)); - - return { album, tracks }; - } catch (error) { - console.error('Qobuz getAlbum failed:', error); - throw error; - } - } - - // Get artist details - async getArtist(id) { - try { - const artistData = await this.fetchWithRetry(`/get-artist?artist_id=${encodeURIComponent(id)}`); - - if (!artistData.success || !artistData.data) { - throw new Error('Artist not found'); - } - - // Qobuz get-artist returns { artist: {...} } nested structure - const artistInfo = artistData.data.artist || artistData.data; - if (!artistInfo) { - throw new Error('Artist info not found in response'); - } - const artist = this.transformArtist(artistInfo); - - // Get albums from the releases section - let albums = []; - let eps = []; - if (Array.isArray(artistData.data.releases)) { - // Find album releases - const albumReleases = artistData.data.releases.find((r) => r.type === 'album'); - if (albumReleases?.items) { - albums = albumReleases.items.map((album) => this.transformAlbum(album)); - } - // Find EP/single releases - const epReleases = artistData.data.releases.find((r) => r.type === 'epSingle'); - if (epReleases?.items) { - eps = epReleases.items.map((album) => this.transformAlbum(album)); - } - } - - // Get top tracks - let tracks = []; - if (Array.isArray(artistData.data.top_tracks)) { - tracks = artistData.data.top_tracks.map((track) => this.transformTrack(track)); - } - - return { ...artist, albums, eps, tracks }; - } catch (error) { - console.error('Qobuz getArtist failed:', error); - throw error; - } - } - - // Transform Qobuz track to Tidal-like format - transformTrack(track, albumData = null) { - // Qobuz uses 'performer' for the main artist, not 'artist' - const mainArtist = track.performer || track.artist; - const artistsList = track.artists || (mainArtist ? [mainArtist] : []); - - return { - id: `q:${track.id}`, - title: track.title, - duration: track.duration, - artist: mainArtist ? this.transformArtist(mainArtist) : null, - artists: artistsList.map((a) => this.transformArtist(a)), - album: albumData ? this.transformAlbum(albumData) : track.album ? this.transformAlbum(track.album) : null, - audioQuality: this.mapQuality(track.streaming_quality), - explicit: track.parental_warning || false, - trackNumber: track.track_number, - volumeNumber: track.media_number || 1, - isrc: track.isrc, - provider: 'qobuz', - originalId: track.id, - }; - } - - // Transform Qobuz album to Tidal-like format - transformAlbum(album) { - // Qobuz albums have artist (single) or artists (array) - const mainArtist = album.artist || album.artists?.[0]; - return { - id: `q:${album.id}`, - title: album.title, - artist: mainArtist ? this.transformArtist(mainArtist) : null, - artists: album.artists - ? album.artists.map((a) => this.transformArtist(a)) - : mainArtist - ? [this.transformArtist(mainArtist)] - : [], - numberOfTracks: album.tracks_count || 0, - releaseDate: album.release_date_original || album.release_date, - cover: album.image?.large || album.image?.medium || album.image?.small, - explicit: album.parental_warning || false, - type: album.album_type === 'ep' ? 'EP' : album.album_type === 'single' ? 'SINGLE' : 'ALBUM', - provider: 'qobuz', - originalId: album.id, - }; - } - - // Transform Qobuz artist to Tidal-like format - transformArtist(artist) { - if (!artist) { - return { - id: 'q:unknown', - name: 'Unknown Artist', - picture: null, - provider: 'qobuz', - originalId: null, - }; - } - // Handle different name structures: string or { display: string } - const name = typeof artist.name === 'string' ? artist.name : artist.name?.display || 'Unknown Artist'; - // Handle different image structures: image object or picture string or images.portrait - const picture = - artist.image?.large || - artist.image?.medium || - artist.image?.small || - artist.picture || - (artist.images?.portrait - ? `https://static.qobuz.com/images/artists/covers/large/${artist.images.portrait.hash}.${artist.images.portrait.format}` - : null); - return { - id: `q:${artist.id}`, - name: name, - picture: picture, - provider: 'qobuz', - originalId: artist.id, - }; - } - - // Map Qobuz quality to Tidal quality format - mapQuality(qobuzQuality) { - const qualityMap = { - MP3: 'HIGH', - FLAC: 'LOSSLESS', - HiRes: 'HI_RES_LOSSLESS', - }; - return qualityMap[qobuzQuality] || 'LOSSLESS'; - } - - // Get cover URL - getCoverUrl(coverId, size = '320') { - if (!coverId) { - return `https://picsum.photos/seed/${Math.random()}/${size}`; - } - - // Qobuz cover URLs are usually full URLs - if (typeof coverId === 'string' && coverId.startsWith('http')) { - return coverId; - } - - return coverId; - } - - // Get artist picture URL - getArtistPictureUrl(pictureUrl, size = '320') { - if (!pictureUrl) { - return `https://picsum.photos/seed/${Math.random()}/${size}`; - } - - // Qobuz picture URLs are usually full URLs - if (typeof pictureUrl === 'string' && pictureUrl.startsWith('http')) { - return pictureUrl; - } - - return pictureUrl; - } - - // Get stream URL for a track - async getStreamUrl(trackId, quality = '27') { - try { - const cleanId = trackId.replace(/^q:/, ''); - // Map Tidal quality format to Qobuz quality values - // Qobuz: 27=MP3 320kbps, 7=FLAC lossless, 6=HiRes 96/24, 5=HiRes 192/24 - const qualityMap = { - LOW: '27', - HIGH: '27', - LOSSLESS: '7', - HI_RES: '6', - HI_RES_LOSSLESS: '5', - }; - const qobuzQuality = qualityMap[quality] || quality || '27'; - const data = await this.fetchWithRetry( - `/download-music?track_id=${encodeURIComponent(cleanId)}&quality=${qobuzQuality}` - ); - - if (!data.success || !data.data?.url) { - throw new Error('Stream URL not available'); - } - - return data.data.url; - } catch (error) { - console.error('Qobuz getStreamUrl failed:', error); - throw error; - } - } - - // Similar/recommendation methods - async getSimilarArtists(_artistId) { - // Qobuz doesn't have a direct similar artists endpoint in this simplified API - return []; - } - - async getSimilarAlbums(_albumId) { - // Qobuz doesn't have a direct similar albums endpoint in this simplified API - return []; - } - - // Unified search - search all types at once - async search(query, options = {}) { - const offset = options.offset || 0; - const limit = options.limit || 10; - - try { - const data = await this.fetchWithRetry( - `/get-music?q=${encodeURIComponent(query)}&offset=${offset}&limit=${limit}` - ); - - if (!data.success || !data.data) { - return { - tracks: { items: [], limit: 0, offset: 0, totalNumberOfItems: 0 }, - albums: { items: [], limit: 0, offset: 0, totalNumberOfItems: 0 }, - artists: { items: [], limit: 0, offset: 0, totalNumberOfItems: 0 }, - }; - } - - const tracks = (data.data.tracks?.items || []).map((track) => this.transformTrack(track)); - const albums = (data.data.albums?.items || []).map((album) => this.transformAlbum(album)); - const artists = (data.data.artists?.items || []).map((artist) => this.transformArtist(artist)); - - return { - tracks: { - items: tracks, - limit: data.data.tracks?.limit || tracks.length, - offset: data.data.tracks?.offset || 0, - totalNumberOfItems: data.data.tracks?.total || tracks.length, - }, - albums: { - items: albums, - limit: data.data.albums?.limit || albums.length, - offset: data.data.albums?.offset || 0, - totalNumberOfItems: data.data.albums?.total || albums.length, - }, - artists: { - items: artists, - limit: data.data.artists?.limit || artists.length, - offset: data.data.artists?.offset || 0, - totalNumberOfItems: data.data.artists?.total || artists.length, - }, - }; - } catch (error) { - if (error.name === 'AbortError') throw error; - console.error('Qobuz search failed:', error); - return { - tracks: { items: [], limit: 0, offset: 0, totalNumberOfItems: 0 }, - albums: { items: [], limit: 0, offset: 0, totalNumberOfItems: 0 }, - artists: { items: [], limit: 0, offset: 0, totalNumberOfItems: 0 }, - }; - } - } - - // Get next page helper - getNextPage(currentOffset, limit, total) { - const nextOffset = currentOffset + limit; - return nextOffset < total ? nextOffset : null; - } - - // Get previous page helper - getPreviousPage(currentOffset, limit) { - const prevOffset = currentOffset - limit; - return prevOffset >= 0 ? prevOffset : null; - } -} - -export const qobuzAPI = new QobuzAPI(); diff --git a/js/router.js b/js/router.js index 5432fb7..e273e9a 100644 --- a/js/router.js +++ b/js/router.js @@ -31,14 +31,11 @@ export function createRouter(ui) { const param = parts.slice(1).join('/'); // Helper to extract provider prefix and ID from params - // Supports formats like: /track/t/123 (Tidal), /track/q/123 (Qobuz), /track/123 (default) + // Supports formats like: /track/t/123 (Tidal), /track/123 (default) const extractProviderAndId = (p) => { if (p.startsWith('t/')) { return { provider: 'tidal', id: p.slice(2) }; } - if (p.startsWith('q/')) { - return { provider: 'qobuz', id: p.slice(2) }; - } return { provider: null, id: p }; }; diff --git a/js/ui.js b/js/ui.js index d0b058c..591fd48 100644 --- a/js/ui.js +++ b/js/ui.js @@ -4631,7 +4631,6 @@ export class UIRenderer { const url = link.url; if (url.includes('tidal.com')) return ''; - if (url.includes('qobuz.com')) return ''; let icon = SVG_GLOBE(24); let title = 'Website';