diff --git a/docsite/docusaurus.config.ts b/docsite/docusaurus.config.ts index c7d9856c..02f0f3b6 100644 --- a/docsite/docusaurus.config.ts +++ b/docsite/docusaurus.config.ts @@ -71,7 +71,7 @@ const config: Config = { ], ], themes: [ - "docusaurus-json-schema-plugin", + //"docusaurus-json-schema-plugin", [ "@easyops-cn/docusaurus-search-local", /** @type {import("@easyops-cn/docusaurus-search-local").PluginOptions} */ @@ -90,6 +90,7 @@ const config: Config = { 'docusaurus-theme-github-codeblock' ], plugins: [ + 'docusaurus-plugin-sass', [ '@docusaurus/plugin-client-redirects', { @@ -160,7 +161,7 @@ const config: Config = { ], }, footer: { - style: 'dark', + links: [ { title: 'Docs', diff --git a/docsite/package-lock.json b/docsite/package-lock.json index 74b5c909..929389a7 100644 --- a/docsite/package-lock.json +++ b/docsite/package-lock.json @@ -7,6 +7,7 @@ "": { "name": "my-website", "version": "0.0.0", + "hasInstallScript": true, "dependencies": { "@docusaurus/core": "3.8.1", "@docusaurus/faster": "3.8.1", @@ -14,15 +15,22 @@ "@docusaurus/preset-classic": "3.8.1", "@easyops-cn/docusaurus-search-local": "0.51.1", "@mdx-js/react": "^3.0.0", + "ajv": "^8.18.0", + "ajv-formats": "^3.0.1", + "cf-json-schema-viz": "^0.3.0", "clsx": "^2.0.0", - "docusaurus-json-schema-plugin": "^1.14.0", + "docusaurus-plugin-sass": "^0.2.6", "docusaurus-theme-github-codeblock": "^2.0.2", "json5": "^2.2.3", "micromark-extension-directive": "^3.0.1", + "modern-react-json-editor": "^1.0.2", + "patch-package": "^8.0.1", "prism-react-renderer": "^2.3.0", "raw-loader": "^4.0.2", "react": "^19.0.0", - "react-dom": "^19.0.0" + "react-dom": "^19.0.0", + "react-markdown": "^10.1.0", + "sass": "^1.97.0" }, "devDependencies": { "@docusaurus/module-type-aliases": "^3.6.3", @@ -1914,12 +1922,10 @@ } }, "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==", - "dependencies": { - "regenerator-runtime": "^0.14.0" - }, + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.6.tgz", + "integrity": "sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==", + "license": "MIT", "engines": { "node": ">=6.9.0" } @@ -1981,6 +1987,150 @@ "node": ">=6.9.0" } }, + "node_modules/@base-ui/react": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@base-ui/react/-/react-1.3.0.tgz", + "integrity": "sha512-FwpKqZbPz14AITp1CVgf4AjhKPe1OeeVKSBMdgD10zbFlj3QSWelmtCMLi2+/PFZZcIm3l87G7rwtCZJwHyXWA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.28.6", + "@base-ui/utils": "0.2.6", + "@floating-ui/react-dom": "^2.1.8", + "@floating-ui/utils": "^0.2.11", + "tabbable": "^6.4.0", + "use-sync-external-store": "^1.6.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@types/react": "^17 || ^18 || ^19", + "react": "^17 || ^18 || ^19", + "react-dom": "^17 || ^18 || ^19" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@base-ui/utils": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/@base-ui/utils/-/utils-0.2.6.tgz", + "integrity": "sha512-yQ+qeuqohwhsNpoYDqqXaLllYAkPCP4vYdDrVo8FQXaAPfHWm1pG/Vm+jmGTA5JFS0BAIjookyapuJFY8F9PIw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.28.6", + "@floating-ui/utils": "^0.2.11", + "reselect": "^5.1.1", + "use-sync-external-store": "^1.6.0" + }, + "peerDependencies": { + "@types/react": "^17 || ^18 || ^19", + "react": "^17 || ^18 || ^19", + "react-dom": "^17 || ^18 || ^19" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@codemirror/autocomplete": { + "version": "6.20.1", + "resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.20.1.tgz", + "integrity": "sha512-1cvg3Vz1dSSToCNlJfRA2WSI4ht3K+WplO0UMOgmUYPivCyy2oueZY6Lx7M9wThm7SDUBViRmuT+OG/i8+ON9A==", + "license": "MIT", + "dependencies": { + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.17.0", + "@lezer/common": "^1.0.0" + } + }, + "node_modules/@codemirror/commands": { + "version": "6.10.3", + "resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.10.3.tgz", + "integrity": "sha512-JFRiqhKu+bvSkDLI+rUhJwSxQxYb759W5GBezE8Uc8mHLqC9aV/9aTC7yJSqCtB3F00pylrLCwnyS91Ap5ej4Q==", + "license": "MIT", + "dependencies": { + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.6.0", + "@codemirror/view": "^6.27.0", + "@lezer/common": "^1.1.0" + } + }, + "node_modules/@codemirror/lang-json": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@codemirror/lang-json/-/lang-json-6.0.2.tgz", + "integrity": "sha512-x2OtO+AvwEHrEwR0FyyPtfDUiloG3rnVTSZV1W8UteaLL8/MajQd8DpvUb2YVzC+/T18aSDv0H9mu+xw0EStoQ==", + "license": "MIT", + "dependencies": { + "@codemirror/language": "^6.0.0", + "@lezer/json": "^1.0.0" + } + }, + "node_modules/@codemirror/language": { + "version": "6.12.2", + "resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.12.2.tgz", + "integrity": "sha512-jEPmz2nGGDxhRTg3lTpzmIyGKxz3Gp3SJES4b0nAuE5SWQoKdT5GoQ69cwMmFd+wvFUhYirtDTr0/DRHpQAyWg==", + "license": "MIT", + "dependencies": { + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.23.0", + "@lezer/common": "^1.5.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0", + "style-mod": "^4.0.0" + } + }, + "node_modules/@codemirror/lint": { + "version": "6.9.5", + "resolved": "https://registry.npmjs.org/@codemirror/lint/-/lint-6.9.5.tgz", + "integrity": "sha512-GElsbU9G7QT9xXhpUg1zWGmftA/7jamh+7+ydKRuT0ORpWS3wOSP0yT1FOlIZa7mIJjpVPipErsyvVqB9cfTFA==", + "license": "MIT", + "dependencies": { + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.35.0", + "crelt": "^1.0.5" + } + }, + "node_modules/@codemirror/search": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/@codemirror/search/-/search-6.6.0.tgz", + "integrity": "sha512-koFuNXcDvyyotWcgOnZGmY7LZqEOXZaaxD/j6n18TCLx2/9HieZJ5H6hs1g8FiRxBD0DNfs0nXn17g872RmYdw==", + "license": "MIT", + "dependencies": { + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.37.0", + "crelt": "^1.0.5" + } + }, + "node_modules/@codemirror/state": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.6.0.tgz", + "integrity": "sha512-4nbvra5R5EtiCzr9BTHiTLc+MLXK2QGiAVYMyi8PkQd3SR+6ixar/Q/01Fa21TBIDOZXgeWV4WppsQolSreAPQ==", + "license": "MIT", + "dependencies": { + "@marijn/find-cluster-break": "^1.0.0" + } + }, + "node_modules/@codemirror/view": { + "version": "6.40.0", + "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.40.0.tgz", + "integrity": "sha512-WA0zdU7xfF10+5I3HhUUq3kqOx3KjqmtQ9lqZjfK7jtYk4G72YW9rezcSywpaUMCWOMlq+6E0pO1IWg1TNIhtg==", + "license": "MIT", + "dependencies": { + "@codemirror/state": "^6.6.0", + "crelt": "^1.0.6", + "style-mod": "^4.1.0", + "w3c-keyname": "^2.2.4" + } + }, "node_modules/@colors/colors": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", @@ -4039,6 +4189,77 @@ "tslib": "^2.4.0" } }, + "node_modules/@floating-ui/core": { + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.5.tgz", + "integrity": "sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ==", + "license": "MIT", + "dependencies": { + "@floating-ui/utils": "^0.2.11" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.7.6", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.6.tgz", + "integrity": "sha512-9gZSAI5XM36880PPMm//9dfiEngYoC6Am2izES1FF406YFsjvyBMmeJ2g4SAju3xWwtuynNRFL2s9hgxpLI5SQ==", + "license": "MIT", + "dependencies": { + "@floating-ui/core": "^1.7.5", + "@floating-ui/utils": "^0.2.11" + } + }, + "node_modules/@floating-ui/react-dom": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.8.tgz", + "integrity": "sha512-cC52bHwM/n/CxS87FH0yWdngEZrjdtLW/qVruo68qg+prK7ZQ4YGdut2GyDVpoGeAYe/h899rVeOVm6Oi40k2A==", + "license": "MIT", + "dependencies": { + "@floating-ui/dom": "^1.7.6" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@floating-ui/utils": { + "version": "0.2.11", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.11.tgz", + "integrity": "sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg==", + "license": "MIT" + }, + "node_modules/@fortawesome/fontawesome-common-types": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-7.2.0.tgz", + "integrity": "sha512-IpR0bER9FY25p+e7BmFH25MZKEwFHTfRAfhOyJubgiDnoJNsSvJ7nigLraHtp4VOG/cy8D7uiV0dLkHOne5Fhw==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/@fortawesome/free-regular-svg-icons": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-7.2.0.tgz", + "integrity": "sha512-iycmlN51EULlQ4D/UU9WZnHiN0CvjJ2TuuCrAh+1MVdzD+4ViKYH2deNAll4XAAYlZa8WAefHR5taSK8hYmSMw==", + "license": "(CC-BY-4.0 AND MIT)", + "dependencies": { + "@fortawesome/fontawesome-common-types": "7.2.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@fortawesome/free-solid-svg-icons": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-7.2.0.tgz", + "integrity": "sha512-YTVITFGN0/24PxzXrwqCgnyd7njDuzp5ZvaCx5nq/jg55kUYd94Nj8UTchBdBofi/L0nwRfjGOg0E41d2u9T1w==", + "license": "(CC-BY-4.0 AND MIT)", + "dependencies": { + "@fortawesome/fontawesome-common-types": "7.2.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/@hapi/hoek": { "version": "9.3.0", "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", @@ -4091,6 +4312,16 @@ "@jridgewell/trace-mapping": "^0.3.24" } }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, "node_modules/@jridgewell/resolve-uri": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", @@ -4109,9 +4340,10 @@ } }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==" + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.29", @@ -4123,12 +4355,86 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@jsep-plugin/assignment": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@jsep-plugin/assignment/-/assignment-1.3.0.tgz", + "integrity": "sha512-VVgV+CXrhbMI3aSusQyclHkenWSAm95WaiKrMxRFam3JSUiIaQjoMIw2sEs/OX4XifnqeQUN4DYbJjlA8EfktQ==", + "license": "MIT", + "engines": { + "node": ">= 10.16.0" + }, + "peerDependencies": { + "jsep": "^0.4.0||^1.0.0" + } + }, + "node_modules/@jsep-plugin/regex": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@jsep-plugin/regex/-/regex-1.0.4.tgz", + "integrity": "sha512-q7qL4Mgjs1vByCaTnDFcBnV9HS7GVPJX5vyVoCgZHNSC9rjwIlmbXG5sUuorR5ndfHAIlJ8pVStxvjXHbNvtUg==", + "license": "MIT", + "engines": { + "node": ">= 10.16.0" + }, + "peerDependencies": { + "jsep": "^0.4.0||^1.0.0" + } + }, + "node_modules/@jsonquerylang/jsonquery": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@jsonquerylang/jsonquery/-/jsonquery-5.1.1.tgz", + "integrity": "sha512-Fj4SoA6Ku09EF+t7OEI8QLipA2A+fJCdEOwnDWG84o5jXMRjkcN5NCMH7kFZb5fP62xz914XV5LBOiDdiUXObg==", + "license": "ISC", + "bin": { + "jsonquery": "bin/cli.js" + } + }, "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/@lezer/common": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.5.1.tgz", + "integrity": "sha512-6YRVG9vBkaY7p1IVxL4s44n5nUnaNnGM2/AckNgYOnxTG2kWh1vR8BMxPseWPjRNpb5VtXnMpeYAEAADoRV1Iw==", + "license": "MIT" + }, + "node_modules/@lezer/highlight": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@lezer/highlight/-/highlight-1.2.3.tgz", + "integrity": "sha512-qXdH7UqTvGfdVBINrgKhDsVTJTxactNNxLk7+UMwZhU13lMHaOBlJe9Vqp907ya56Y3+ed2tlqzys7jDkTmW0g==", + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.3.0" + } + }, + "node_modules/@lezer/json": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@lezer/json/-/json-1.0.3.tgz", + "integrity": "sha512-BP9KzdF9Y35PDpv04r0VeSTKDeox5vVr3efE7eBbx3r4s3oNLfunchejZhjArmeieBH+nVOpgIiBJpEAv8ilqQ==", + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0" + } + }, + "node_modules/@lezer/lr": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.4.8.tgz", + "integrity": "sha512-bPWa0Pgx69ylNlMlPvBPryqeLYQjyJjqPx+Aupm5zydLIF3NE+6MMLT8Yi23Bd9cif9VS00aUebn+6fDIGBcDA==", + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.0.0" + } + }, + "node_modules/@marijn/find-cluster-break": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@marijn/find-cluster-break/-/find-cluster-break-1.0.2.tgz", + "integrity": "sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g==", + "license": "MIT" + }, "node_modules/@mdx-js/mdx": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-3.1.0.tgz", @@ -4515,6 +4821,328 @@ "node": ">= 8" } }, + "node_modules/@parcel/watcher": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.1.tgz", + "integrity": "sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "dependencies": { + "detect-libc": "^1.0.3", + "is-glob": "^4.0.3", + "micromatch": "^4.0.5", + "node-addon-api": "^7.0.0" + }, + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "@parcel/watcher-android-arm64": "2.5.1", + "@parcel/watcher-darwin-arm64": "2.5.1", + "@parcel/watcher-darwin-x64": "2.5.1", + "@parcel/watcher-freebsd-x64": "2.5.1", + "@parcel/watcher-linux-arm-glibc": "2.5.1", + "@parcel/watcher-linux-arm-musl": "2.5.1", + "@parcel/watcher-linux-arm64-glibc": "2.5.1", + "@parcel/watcher-linux-arm64-musl": "2.5.1", + "@parcel/watcher-linux-x64-glibc": "2.5.1", + "@parcel/watcher-linux-x64-musl": "2.5.1", + "@parcel/watcher-win32-arm64": "2.5.1", + "@parcel/watcher-win32-ia32": "2.5.1", + "@parcel/watcher-win32-x64": "2.5.1" + } + }, + "node_modules/@parcel/watcher-android-arm64": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.1.tgz", + "integrity": "sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-darwin-arm64": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.1.tgz", + "integrity": "sha512-eAzPv5osDmZyBhou8PoF4i6RQXAfeKL9tjb3QzYuccXFMQU0ruIc/POh30ePnaOyD1UXdlKguHBmsTs53tVoPw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-darwin-x64": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.1.tgz", + "integrity": "sha512-1ZXDthrnNmwv10A0/3AJNZ9JGlzrF82i3gNQcWOzd7nJ8aj+ILyW1MTxVk35Db0u91oD5Nlk9MBiujMlwmeXZg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-freebsd-x64": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.1.tgz", + "integrity": "sha512-SI4eljM7Flp9yPuKi8W0ird8TI/JK6CSxju3NojVI6BjHsTyK7zxA9urjVjEKJ5MBYC+bLmMcbAWlZ+rFkLpJQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm-glibc": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.1.tgz", + "integrity": "sha512-RCdZlEyTs8geyBkkcnPWvtXLY44BCeZKmGYRtSgtwwnHR4dxfHRG3gR99XdMEdQ7KeiDdasJwwvNSF5jKtDwdA==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm-musl": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.1.tgz", + "integrity": "sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm64-glibc": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.1.tgz", + "integrity": "sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm64-musl": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.1.tgz", + "integrity": "sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-x64-glibc": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.1.tgz", + "integrity": "sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-x64-musl": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.1.tgz", + "integrity": "sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-arm64": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.1.tgz", + "integrity": "sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-ia32": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.1.tgz", + "integrity": "sha512-c2KkcVN+NJmuA7CGlaGD1qJh1cLfDnQsHjE89E60vUEMlqduHGCdCLJCID5geFVM0dOtA3ZiIO8BoEQmzQVfpQ==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-x64": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.1.tgz", + "integrity": "sha512-9lHBdJITeNR++EvSQVUcaZoWupyHfXe1jZvGZ06O/5MflPcuPLtEphScIBL+AiCWBO46tDSHzWyD0uDmmZqsgA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher/node_modules/detect-libc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==", + "license": "Apache-2.0", + "optional": true, + "bin": { + "detect-libc": "bin/detect-libc.js" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/@phosphor-icons/react": { + "version": "2.1.10", + "resolved": "https://registry.npmjs.org/@phosphor-icons/react/-/react-2.1.10.tgz", + "integrity": "sha512-vt8Tvq8GLjheAZZYa+YG/pW7HDbov8El/MANW8pOAz4eGxrwhnbfrQZq0Cp4q8zBEu8NIhHdnr+r8thnfRSNYA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "react": ">= 16.8", + "react-dom": ">= 16.8" + } + }, "node_modules/@pnpm/config.env-replace": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@pnpm/config.env-replace/-/config.env-replace-1.1.0.tgz", @@ -4562,6 +5190,17 @@ "integrity": "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==", "license": "MIT" }, + "node_modules/@replit/codemirror-indentation-markers": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/@replit/codemirror-indentation-markers/-/codemirror-indentation-markers-6.5.3.tgz", + "integrity": "sha512-hL5Sfvw3C1vgg7GolLe/uxX5T3tmgOA3ZzqlMv47zjU1ON51pzNWiVbS22oh6crYhtVhv8b3gdXwoYp++2ilHw==", + "license": "MIT", + "peerDependencies": { + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0" + } + }, "node_modules/@rspack/binding": { "version": "1.4.6", "resolved": "https://registry.npmjs.org/@rspack/binding/-/binding-1.4.6.tgz", @@ -4787,6 +5426,12 @@ "micromark-util-symbol": "^1.0.1" } }, + "node_modules/@sphinxxxx/color-conversion": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/@sphinxxxx/color-conversion/-/color-conversion-2.2.2.tgz", + "integrity": "sha512-XExJS3cLqgrmNBIP3bBw6+1oQ1ksGjFh0+oClDKFYpCCqx/hlqwWO5KO/S63fzUo67SxI9dMrF0y5T/Ey7h8Zw==", + "license": "ISC" + }, "node_modules/@stoplight/json": { "version": "3.21.7", "resolved": "https://registry.npmjs.org/@stoplight/json/-/json-3.21.7.tgz", @@ -4803,21 +5448,41 @@ "node": ">=8.3.0" } }, - "node_modules/@stoplight/json-ref-resolver": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/@stoplight/json-ref-resolver/-/json-ref-resolver-3.1.6.tgz", - "integrity": "sha512-YNcWv3R3n3U6iQYBsFOiWSuRGE5su1tJSiX6pAPRVk7dP0L7lqCteXGzuVRQ0gMZqUl8v1P0+fAKxF6PLo9B5A==", + "node_modules/@stoplight/json-schema-merge-allof": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@stoplight/json-schema-merge-allof/-/json-schema-merge-allof-0.8.0.tgz", + "integrity": "sha512-g8e0s43v96Xbzvd8d6KKUuJTO16CS2oJglJrviUi8ASIUxzFvAJqTHWLtGmpTryisQopqg1evXGJfi0+164+Qw==", + "license": "MIT", "dependencies": { - "@stoplight/json": "^3.21.0", - "@stoplight/path": "^1.3.2", - "@stoplight/types": "^12.3.0 || ^13.0.0", - "@types/urijs": "^1.19.19", - "dependency-graph": "~0.11.0", - "fast-memoize": "^2.5.2", - "immer": "^9.0.6", - "lodash": "^4.17.21", - "tslib": "^2.6.0", - "urijs": "^1.19.11" + "compute-lcm": "^1.1.0", + "json-schema-compare": "^0.2.2", + "lodash": "^4.17.4" + } + }, + "node_modules/@stoplight/json-schema-tree": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@stoplight/json-schema-tree/-/json-schema-tree-4.0.0.tgz", + "integrity": "sha512-SAGtof+ihIdPqETR+7XXOaqZJcrbSih/xEahaw5t1nXk5sVW6ss2l5A1WCIuvtvnQiUKnBfanmZU4eoM1ZvItg==", + "license": "Apache-2.0", + "dependencies": { + "@stoplight/json": "^3.12.0", + "@stoplight/json-schema-merge-allof": "^0.8.0", + "@stoplight/lifecycle": "^2.3.2", + "@types/json-schema": "^7.0.7", + "magic-error": "0.0.1" + }, + "engines": { + "node": ">=10.18" + } + }, + "node_modules/@stoplight/lifecycle": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/@stoplight/lifecycle/-/lifecycle-2.3.3.tgz", + "integrity": "sha512-JbPRTIzPZabeYPAk5+gdsnfwAxqW35G9e0ZjOG3toUmNViLOsEzuK4vpWd+Prv2Mw8HRmu+haiYizteZp6mk0w==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.3.1", + "wolfy87-eventemitter": "~5.2.8" }, "engines": { "node": ">=8.3.0" @@ -4851,6 +5516,15 @@ "node": "^12.20 || >=14.13" } }, + "node_modules/@sveltejs/acorn-typescript": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@sveltejs/acorn-typescript/-/acorn-typescript-1.0.9.tgz", + "integrity": "sha512-lVJX6qEgs/4DOcRTpo56tmKzVPtoWAaVbL4hfO7t7NVwl9AAXzQR6cihesW1BmNMPl+bK6dreu2sOKBP2Q9CIA==", + "license": "MIT", + "peerDependencies": { + "acorn": "^8.9.0" + } + }, "node_modules/@svgr/babel-plugin-add-jsx-attribute": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-8.0.0.tgz", @@ -5888,16 +6562,17 @@ "@types/node": "*" } }, + "node_modules/@types/trusted-types": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", + "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", + "license": "MIT" + }, "node_modules/@types/unist": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==" }, - "node_modules/@types/urijs": { - "version": "1.19.25", - "resolved": "https://registry.npmjs.org/@types/urijs/-/urijs-1.19.25.tgz", - "integrity": "sha512-XOfUup9r3Y06nFAZh3WvO0rBU4OtlfPB/vgxpjg+NRdGU6CN6djdc6OEiH+PcqHCY6eFLo9Ista73uarf4gnBg==" - }, "node_modules/@types/ws": { "version": "8.18.1", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz", @@ -6068,6 +6743,12 @@ "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==" }, + "node_modules/@yarnpkg/lockfile": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", + "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==", + "license": "BSD-2-Clause" + }, "node_modules/accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", @@ -6165,9 +6846,10 @@ } }, "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==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", + "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", + "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", @@ -6180,9 +6862,10 @@ } }, "node_modules/ajv-formats": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", - "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz", + "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==", + "license": "MIT", "dependencies": { "ajv": "^8.0.0" }, @@ -6357,6 +7040,15 @@ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" }, + "node_modules/aria-query": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.1.tgz", + "integrity": "sha512-Z/ZeOgVl7bcSYZ/u/rh0fOpvEpq//LZmdbkXyc7syVzjPAhfOa9ebsdTSjEBDU4vs5nC98Kfduj1uFo0qyET3g==", + "license": "Apache-2.0", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", @@ -6416,6 +7108,15 @@ "postcss": "^8.1.0" } }, + "node_modules/axobject-query": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz", + "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==", + "license": "Apache-2.0", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/babel-loader": { "version": "9.2.1", "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-9.2.1.tgz", @@ -6827,6 +7528,54 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/cf-json-schema-viz": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/cf-json-schema-viz/-/cf-json-schema-viz-0.3.0.tgz", + "integrity": "sha512-abWFhQ/5m08sSqO5XFwF9vh49An2cxrfr1/MnF88Qdo7AXFOWEB3dFJ7MN74ASIKegwK7AemxNPGVkQjzNCujQ==", + "license": "Apache-2.0", + "dependencies": { + "@base-ui/react": "^1.2.0", + "@phosphor-icons/react": "^2.1.7", + "@stoplight/json": "^3.21.7", + "@stoplight/json-schema-tree": "^4.0.0", + "@types/json-schema": "^7.0.15", + "clsx": "^2.1.1", + "jotai": "^2.10.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + } + }, + "node_modules/cf-json-schema-viz/node_modules/jotai": { + "version": "2.18.1", + "resolved": "https://registry.npmjs.org/jotai/-/jotai-2.18.1.tgz", + "integrity": "sha512-e0NOzK+yRFwHo7DOp0DS0Ycq74KMEAObDWFGmfEL28PD9nLqBTt3/Ug7jf9ca72x0gC9LQZG9zH+0ISICmy3iA==", + "license": "MIT", + "engines": { + "node": ">=12.20.0" + }, + "peerDependencies": { + "@babel/core": ">=7.0.0", + "@babel/template": ">=7.0.0", + "@types/react": ">=17.0.0", + "react": ">=17.0.0" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "@babel/template": { + "optional": true + }, + "@types/react": { + "optional": true + }, + "react": { + "optional": true + } + } + }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -7069,6 +7818,17 @@ "node": ">=6" } }, + "node_modules/codemirror-wrapped-line-indent": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/codemirror-wrapped-line-indent/-/codemirror-wrapped-line-indent-1.0.9.tgz", + "integrity": "sha512-oc976hHLt35u6Ojbhub+IWOxEpapZSqYieLEdGhsgFZ4rtYQtdb5KjxzgjCCyVe3t0yk+a6hmaIOEsjU/tZRxQ==", + "license": "MIT", + "peerDependencies": { + "@codemirror/language": "^6.9.0", + "@codemirror/state": "^6.2.1", + "@codemirror/view": "^6.17.1" + } + }, "node_modules/collapse-white-space": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-2.1.0.tgz", @@ -7205,6 +7965,27 @@ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "license": "MIT" }, + "node_modules/compute-gcd": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/compute-gcd/-/compute-gcd-1.2.1.tgz", + "integrity": "sha512-TwMbxBNz0l71+8Sc4czv13h4kEqnchV9igQZBi6QUaz09dnz13juGnnaWWJTRsP3brxOoxeB4SA2WELLw1hCtg==", + "dependencies": { + "validate.io-array": "^1.0.3", + "validate.io-function": "^1.0.2", + "validate.io-integer-array": "^1.0.0" + } + }, + "node_modules/compute-lcm": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/compute-lcm/-/compute-lcm-1.1.2.tgz", + "integrity": "sha512-OFNPdQAXnQhDSKioX8/XYT6sdUlXwpeMjfd6ApxMJfyZ4GxmLR1xvMERctlYhlHwIiz6CSpBc2+qYKjHGZw4TQ==", + "dependencies": { + "compute-gcd": "^1.2.1", + "validate.io-array": "^1.0.3", + "validate.io-function": "^1.0.2", + "validate.io-integer-array": "^1.0.0" + } + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -7447,6 +8228,12 @@ } } }, + "node_modules/crelt": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz", + "integrity": "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==", + "license": "MIT" + }, "node_modules/cross-spawn": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", @@ -7898,9 +8685,10 @@ "license": "CC0-1.0" }, "node_modules/csstype": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", - "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "license": "MIT" }, "node_modules/debounce": { "version": "1.2.1", @@ -8055,14 +8843,6 @@ "node": ">= 0.8" } }, - "node_modules/dependency-graph": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/dependency-graph/-/dependency-graph-0.11.0.tgz", - "integrity": "sha512-JeMq7fEshyepOWDfcfHK06N3MhyPhz++vtqWhMT5O9A3K42rdsEDpfdVqjaqaAhsw6a+ZqeDvQVtD0hFHQWrzg==", - "engines": { - "node": ">= 0.6.0" - } - }, "node_modules/dequal": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", @@ -8113,6 +8893,12 @@ "node": ">= 4.0.0" } }, + "node_modules/devalue": { + "version": "5.6.4", + "resolved": "https://registry.npmjs.org/devalue/-/devalue-5.6.4.tgz", + "integrity": "sha512-Gp6rDldRsFh/7XuouDbxMH3Mx8GMCcgzIb1pDTvNyn8pZGQ22u+Wa+lGV9dQCltFQ7uVw0MhRyb8XDskNFOReA==", + "license": "MIT" + }, "node_modules/devlop": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", @@ -8125,6 +8911,15 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, "node_modules/dir-glob": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", @@ -8148,21 +8943,17 @@ "node": ">=6" } }, - "node_modules/docusaurus-json-schema-plugin": { - "version": "1.14.0", - "resolved": "https://registry.npmjs.org/docusaurus-json-schema-plugin/-/docusaurus-json-schema-plugin-1.14.0.tgz", - "integrity": "sha512-TyXIVqAr+rKXhRQqq/IElUogl5ABSDV+PoiHcB6+Jroy2RMsimHkvz3OyfYpxTPDVGetSlX9TvuYJgLVBLIe/w==", - "license": "AGPL-3.0-or-later", + "node_modules/docusaurus-plugin-sass": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/docusaurus-plugin-sass/-/docusaurus-plugin-sass-0.2.6.tgz", + "integrity": "sha512-2hKQQDkrufMong9upKoG/kSHJhuwd+FA3iAe/qzS/BmWpbIpe7XKmq5wlz4J5CJaOPu4x+iDJbgAxZqcoQf0kg==", + "license": "MIT", "dependencies": { - "@stoplight/json-ref-resolver": "^3.1.5", - "monaco-editor": "^0.52.2", - "monaco-editor-webpack-plugin": "^7.1.0", - "react-monaco-editor": "^0.58.0" + "sass-loader": "^16.0.2" }, "peerDependencies": { - "@docusaurus/core": "^3.7.0", - "@docusaurus/theme-classic": "^3.7.0", - "react": ">=18 < 20" + "@docusaurus/core": "^2.0.0-beta || ^3.0.0-alpha", + "sass": "^1.30.0" } }, "node_modules/docusaurus-theme-github-codeblock": { @@ -8512,6 +9303,12 @@ "node": ">=8.0.0" } }, + "node_modules/esm-env": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/esm-env/-/esm-env-1.2.2.tgz", + "integrity": "sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA==", + "license": "MIT" + }, "node_modules/esprima": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", @@ -8524,6 +9321,15 @@ "node": ">=4" } }, + "node_modules/esrap": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/esrap/-/esrap-2.2.3.tgz", + "integrity": "sha512-8fOS+GIGCQZl/ZIlhl59htOlms6U8NvX6ZYgYHpRU/b6tVSh3uHkOHZikl3D4cMbYM0JlpBe+p/BkZEi8J9XIQ==", + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.4.15" + } + }, "node_modules/esrecurse": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", @@ -8855,11 +9661,6 @@ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" }, - "node_modules/fast-memoize": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/fast-memoize/-/fast-memoize-2.5.2.tgz", - "integrity": "sha512-Ue0LwpDYErFbmNnZSF0UH6eImUwDmogUO1jyE+JbN2gsQz/jICm1Ve7t9QT0rNSsfJt+Hs4/S3GnsDVjL4HVrw==" - }, "node_modules/fast-uri": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.5.tgz", @@ -9084,6 +9885,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/find-yarn-workspace-root": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz", + "integrity": "sha512-1IMnbjt4KzsQfnhnzNd8wUEgXZ44IzZaZmnLYx7D5FZlaHt2gW20Cri8Q+E/t5tIj4+epTBub+2Zxu/vNILzqQ==", + "license": "Apache-2.0", + "dependencies": { + "micromatch": "^4.0.2" + } + }, "node_modules/flat": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", @@ -9834,6 +10644,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/html-url-attributes": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/html-url-attributes/-/html-url-attributes-3.0.1.tgz", + "integrity": "sha512-ol6UPyBWqsrO6EJySPz2O7ZSr856WDrEzM5zMqp+FJJLGMW35cLYmmZnl0vztAZxRUoNZJFTCohfjuIJ8I4QBQ==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/html-void-elements": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-3.0.0.tgz", @@ -10080,14 +10900,17 @@ "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.3.0.tgz", "integrity": "sha512-HR7EVodfFUdQCTIeySw+WDRFJlPcLOJbXfwwZ7Oom6tjsvZ3bOkCDJHehQC3nxJrv7+f9XecwazynjU8e4Vw3Q==" }, - "node_modules/immer": { - "version": "9.0.21", - "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.21.tgz", - "integrity": "sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/immer" - } + "node_modules/immutable": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.4.tgz", + "integrity": "sha512-p6u1bG3YSnINT5RQmx/yRZBpenIl30kVxkTLDyHLIMk0gict704Q9n+thfDI7lTRm9vXdDYutVzXhzcThxTnXA==", + "license": "MIT" + }, + "node_modules/immutable-json-patch": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/immutable-json-patch/-/immutable-json-patch-6.0.2.tgz", + "integrity": "sha512-KwCA5DXJiyldda8SPha1zB+6+vbEi5/jRRcYii/6yFXlyu9ZjiSH/wPq8Ri2Hk8iGjjTMcHW3Z21S4MOpl7sOw==", + "license": "ISC" }, "node_modules/import-fresh": { "version": "3.3.1", @@ -10401,6 +11224,15 @@ "node": ">=0.10.0" } }, + "node_modules/is-reference": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-3.0.3.tgz", + "integrity": "sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.6" + } + }, "node_modules/is-regexp": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", @@ -10523,6 +11355,15 @@ "jiti": "bin/jiti.js" } }, + "node_modules/jmespath": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.16.0.tgz", + "integrity": "sha512-9FzQjJ7MATs1tSpnco1K6ayiYE3figslrXA72G2HQ/n76RzvYlofyi5QM+iX4YRs/pu3yzxlVQSST23+dMDknw==", + "license": "Apache-2.0", + "engines": { + "node": ">= 0.6.0" + } + }, "node_modules/joi": { "version": "17.13.3", "resolved": "https://registry.npmjs.org/joi/-/joi-17.13.3.tgz", @@ -10551,6 +11392,15 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/jsep": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/jsep/-/jsep-1.4.0.tgz", + "integrity": "sha512-B7qPcEVE3NVkmSJbaYxvv4cHkVW7DQsZz13pUMrfS8z8Q/BuShN+gcTXrUlPiGqM2/t/EEaI030bpxMqY8gMlw==", + "license": "MIT", + "engines": { + "node": ">= 10.16.0" + } + }, "node_modules/jsesc": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", @@ -10574,11 +11424,51 @@ "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==" }, + "node_modules/json-schema-compare": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/json-schema-compare/-/json-schema-compare-0.2.2.tgz", + "integrity": "sha512-c4WYmDKyJXhs7WWvAWm3uIYnfyWFoIp+JEoX34rctVvEkMYCPGhXtvmFFXiffBbxfZsvQ0RNnV5H7GvDF5HCqQ==", + "license": "MIT", + "dependencies": { + "lodash": "^4.17.4" + } + }, "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/json-source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/json-source-map/-/json-source-map-0.6.1.tgz", + "integrity": "sha512-1QoztHPsMQqhDq0hlXY5ZqcEdUzxQEIxgFkKl4WUp2pgShObl+9ovi4kRh2TfvAfxAoHOJ9vIMEqk3k4iex7tg==", + "license": "MIT" + }, + "node_modules/json-stable-stringify": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.3.0.tgz", + "integrity": "sha512-qtYiSSFlwot9XHtF9bD9c7rwKjr+RecWT//ZnPvSmEjpV5mmPOCN4j8UjY5hbjNkOwZ/jQv3J6R1/pL7RwgMsg==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "isarray": "^2.0.5", + "jsonify": "^0.0.1", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/json-stable-stringify/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/json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", @@ -10606,6 +11496,42 @@ "graceful-fs": "^4.1.6" } }, + "node_modules/jsonify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.1.tgz", + "integrity": "sha512-2/Ki0GcmuqSrgFyelQq9M05y7PS0mEwuIzrf3f1fPqkVDVRvZrPZtVSMHxdgo8Aq0sxAOb/cr2aqqA3LeWHVPg==", + "license": "Public Domain", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/jsonpath-plus": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/jsonpath-plus/-/jsonpath-plus-10.4.0.tgz", + "integrity": "sha512-T92WWatJXmhBbKsgH/0hl+jxjdXrifi5IKeMY02DWggRxX0UElcbVzPlmgLTbvsPeW1PasQ6xE2Q75stkhGbsA==", + "license": "MIT", + "dependencies": { + "@jsep-plugin/assignment": "^1.3.0", + "@jsep-plugin/regex": "^1.0.4", + "jsep": "^1.4.0" + }, + "bin": { + "jsonpath": "bin/jsonpath-cli.js", + "jsonpath-plus": "bin/jsonpath-cli.js" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/jsonrepair": { + "version": "3.13.3", + "resolved": "https://registry.npmjs.org/jsonrepair/-/jsonrepair-3.13.3.tgz", + "integrity": "sha512-BTznj0owIt2CBAH/LTo7+1I5pMvl1e1033LRl/HUowlZmJOIhzC0zbX5bxMngLkfT4WnzPP26QnW5wMr2g9tsQ==", + "license": "ISC", + "bin": { + "jsonrepair": "bin/cli.js" + } + }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -10940,6 +11866,12 @@ "node": ">=8.9.0" } }, + "node_modules/locate-character": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-character/-/locate-character-3.0.0.tgz", + "integrity": "sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==", + "license": "MIT" + }, "node_modules/locate-path": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz", @@ -10960,6 +11892,12 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, + "node_modules/lodash-es": { + "version": "4.17.23", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.23.tgz", + "integrity": "sha512-kVI48u3PZr38HdYz98UmfPnXl2DXrpdctLrFLCd3kOx1xUkOmpFPx7gCWWM5MPkL/fD8zb+Ph0QzjGFs4+hHWg==", + "license": "MIT" + }, "node_modules/lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", @@ -11038,6 +11976,24 @@ "resolved": "https://registry.npmjs.org/lunr-languages/-/lunr-languages-1.14.0.tgz", "integrity": "sha512-hWUAb2KqM3L7J5bcrngszzISY4BxrXn/Xhbb9TTCJYEGqlR1nG67/M14sp09+PTIRklobrn57IAxcdcO/ZFyNA==" }, + "node_modules/magic-error": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/magic-error/-/magic-error-0.0.1.tgz", + "integrity": "sha512-1+N1ET8cbC5bfLQZcRojClzgK2gbUt9keTMr9OJeuXnQKWsfwRRRICuMA3HKaCIXFEgKzxivuMGCNKD7cdU5pg==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "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==", + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, "node_modules/mark.js": { "version": "8.11.1", "resolved": "https://registry.npmjs.org/mark.js/-/mark.js-8.11.1.tgz", @@ -11492,6 +12448,12 @@ "node": ">= 4.0.0" } }, + "node_modules/memoize-one": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-6.0.0.tgz", + "integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==", + "license": "MIT" + }, "node_modules/merge-descriptors": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", @@ -13354,22 +14316,16 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/monaco-editor": { - "version": "0.52.2", - "resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.52.2.tgz", - "integrity": "sha512-GEQWEZmfkOGLdd3XK8ryrfWz3AIP8YymVXiPHEdewrUq7mh0qrKrfHLNCXcbB6sTnMLnOZ3ztSiKcciFUkIJwQ==", - "license": "MIT" - }, - "node_modules/monaco-editor-webpack-plugin": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/monaco-editor-webpack-plugin/-/monaco-editor-webpack-plugin-7.1.0.tgz", - "integrity": "sha512-ZjnGINHN963JQkFqjjcBtn1XBtUATDZBMgNQhDQwd78w2ukRhFXAPNgWuacaQiDZsUr4h1rWv5Mv6eriKuOSzA==", + "node_modules/modern-react-json-editor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/modern-react-json-editor/-/modern-react-json-editor-1.0.2.tgz", + "integrity": "sha512-DCml2ag8MYqovlF+ZjtO6o96sF5hDz9pD/cKfIorrO811mh5anEmCVK0ZuKYTC5P96RivWhvP3p383ZJSbLXTw==", "dependencies": { - "loader-utils": "^2.0.2" + "vanilla-jsoneditor": "^3.11.0" }, "peerDependencies": { - "monaco-editor": ">= 0.31.0", - "webpack": "^4.5.0 || 5.x" + "react": ">=16.8.0", + "react-dom": ">=16.8.0" } }, "node_modules/mrmime": { @@ -13417,6 +14373,12 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, + "node_modules/natural-compare-lite": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", + "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", + "license": "MIT" + }, "node_modules/negotiator": { "version": "0.6.4", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", @@ -13441,6 +14403,13 @@ "tslib": "^2.0.3" } }, + "node_modules/node-addon-api": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", + "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", + "license": "MIT", + "optional": true + }, "node_modules/node-emoji": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-2.2.0.tgz", @@ -13967,6 +14936,74 @@ "tslib": "^2.0.3" } }, + "node_modules/patch-package": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/patch-package/-/patch-package-8.0.1.tgz", + "integrity": "sha512-VsKRIA8f5uqHQ7NGhwIna6Bx6D9s/1iXlA1hthBVBEbkq+t4kXD0HHt+rJhf/Z+Ci0F/HCB2hvn0qLdLG+Qxlw==", + "license": "MIT", + "dependencies": { + "@yarnpkg/lockfile": "^1.1.0", + "chalk": "^4.1.2", + "ci-info": "^3.7.0", + "cross-spawn": "^7.0.3", + "find-yarn-workspace-root": "^2.0.0", + "fs-extra": "^10.0.0", + "json-stable-stringify": "^1.0.2", + "klaw-sync": "^6.0.0", + "minimist": "^1.2.6", + "open": "^7.4.2", + "semver": "^7.5.3", + "slash": "^2.0.0", + "tmp": "^0.2.4", + "yaml": "^2.2.2" + }, + "bin": { + "patch-package": "index.js" + }, + "engines": { + "node": ">=14", + "npm": ">5" + } + }, + "node_modules/patch-package/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/patch-package/node_modules/open": { + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz", + "integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==", + "license": "MIT", + "dependencies": { + "is-docker": "^2.0.0", + "is-wsl": "^2.1.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/patch-package/node_modules/slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/path-exists": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", @@ -15907,15 +16944,31 @@ "webpack": ">=4.41.1 || 5.x" } }, - "node_modules/react-monaco-editor": { - "version": "0.58.0", - "resolved": "https://registry.npmjs.org/react-monaco-editor/-/react-monaco-editor-0.58.0.tgz", - "integrity": "sha512-e8JH0TQEzO96Wd/EXgzc9M9tQK1pxBECD+8GNob9slMURcCM36TiVrgc4topWCDGYxRuMj8IEkaX+s3eQcUUqw==", + "node_modules/react-markdown": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/react-markdown/-/react-markdown-10.1.0.tgz", + "integrity": "sha512-qKxVopLT/TyA6BX3Ue5NwabOsAzm0Q7kAPwq6L+wWDwisYs7R8vZ0nRXqq6rkueboxpkjvLGU9fWifiX/ZZFxQ==", "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "hast-util-to-jsx-runtime": "^2.0.0", + "html-url-attributes": "^3.0.0", + "mdast-util-to-hast": "^13.0.0", + "remark-parse": "^11.0.0", + "remark-rehype": "^11.0.0", + "unified": "^11.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + }, "peerDependencies": { - "monaco-editor": "^0.52.0", - "react": ">=16.8.0 <20.0.0", - "react-dom": ">=16.8.0 <20.0.0" + "@types/react": ">=18", + "react": ">=18" } }, "node_modules/react-router": { @@ -16071,11 +17124,6 @@ "node": ">=4" } }, - "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==" - }, "node_modules/regexpu-core": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-6.2.0.tgz", @@ -16444,6 +17492,12 @@ "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", "license": "MIT" }, + "node_modules/reselect": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/reselect/-/reselect-5.1.1.tgz", + "integrity": "sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w==", + "license": "MIT" + }, "node_modules/resolve": { "version": "1.22.10", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", @@ -16601,6 +17655,94 @@ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, + "node_modules/sass": { + "version": "1.97.0", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.97.0.tgz", + "integrity": "sha512-KR0igP1z4avUJetEuIeOdDlwaUDvkH8wSx7FdSjyYBS3dpyX3TzHfAMO0G1Q4/3cdjcmi3r7idh+KCmKqS+KeQ==", + "license": "MIT", + "dependencies": { + "chokidar": "^4.0.0", + "immutable": "^5.0.2", + "source-map-js": ">=0.6.2 <2.0.0" + }, + "bin": { + "sass": "sass.js" + }, + "engines": { + "node": ">=14.0.0" + }, + "optionalDependencies": { + "@parcel/watcher": "^2.4.1" + } + }, + "node_modules/sass-loader": { + "version": "16.0.6", + "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-16.0.6.tgz", + "integrity": "sha512-sglGzId5gmlfxNs4gK2U3h7HlVRfx278YK6Ono5lwzuvi1jxig80YiuHkaDBVsYIKFhx8wN7XSCI0M2IDS/3qA==", + "license": "MIT", + "dependencies": { + "neo-async": "^2.6.2" + }, + "engines": { + "node": ">= 18.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "@rspack/core": "0.x || 1.x", + "node-sass": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0", + "sass": "^1.3.0", + "sass-embedded": "*", + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "node-sass": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/sass/node_modules/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "license": "MIT", + "dependencies": { + "readdirp": "^4.0.1" + }, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/sass/node_modules/readdirp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", + "license": "MIT", + "engines": { + "node": ">= 14.18.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/sax": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz", @@ -16637,6 +17779,23 @@ "url": "https://opencollective.com/webpack" } }, + "node_modules/schema-utils/node_modules/ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "license": "MIT", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, "node_modules/search-insights": { "version": "2.17.3", "resolved": "https://registry.npmjs.org/search-insights/-/search-insights-2.17.3.tgz", @@ -17350,6 +18509,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/style-mod": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.1.3.tgz", + "integrity": "sha512-i/n8VsZydrugj3Iuzll8+x/00GH2vnYsk1eomD8QiRrSAeW6ItbCQDtfXCeJHd0iwiNagqjQkvpvREEPtW3IoQ==", + "license": "MIT" + }, "node_modules/style-to-object": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-1.0.8.tgz", @@ -17397,6 +18562,33 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/svelte": { + "version": "5.53.11", + "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.53.11.tgz", + "integrity": "sha512-GYmqRjRhJYLQBonfdfGAt28gkfWEShrtXKGXcFGneXi502aBE+I1dJcs/YQriByvP6xqXRz/OdBGC6tfvUQHyQ==", + "license": "MIT", + "dependencies": { + "@jridgewell/remapping": "^2.3.4", + "@jridgewell/sourcemap-codec": "^1.5.0", + "@sveltejs/acorn-typescript": "^1.0.5", + "@types/estree": "^1.0.5", + "@types/trusted-types": "^2.0.7", + "acorn": "^8.12.1", + "aria-query": "5.3.1", + "axobject-query": "^4.1.0", + "clsx": "^2.1.1", + "devalue": "^5.6.3", + "esm-env": "^1.2.1", + "esrap": "^2.2.2", + "is-reference": "^3.0.3", + "locate-character": "^3.0.0", + "magic-string": "^0.30.11", + "zimmerframe": "^1.1.2" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/svg-parser": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.4.tgz", @@ -17450,6 +18642,12 @@ "webpack": ">=2" } }, + "node_modules/tabbable": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.4.0.tgz", + "integrity": "sha512-05PUHKSNE8ou2dwIxTngl4EzcnsCDZGJ/iCLtDflR/SHB/ny14rXc+qU5P4mG9JkusiV7EivzY9Mhm55AzAvCg==", + "license": "MIT" + }, "node_modules/tapable": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", @@ -17565,6 +18763,15 @@ "node": "^18.0.0 || >=20.0.0" } }, + "node_modules/tmp": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.5.tgz", + "integrity": "sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow==", + "license": "MIT", + "engines": { + "node": ">=14.14" + } + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -17984,11 +19191,6 @@ "punycode": "^2.1.0" } }, - "node_modules/urijs": { - "version": "1.19.11", - "resolved": "https://registry.npmjs.org/urijs/-/urijs-1.19.11.tgz", - "integrity": "sha512-HXgFDgDommxn5/bIv0cnQZsPhHDA90NPHD6+c/v21U5+Sx5hoP8+dP9IZXBU1gIfvdRfhG8cel9QNPeionfcCQ==" - }, "node_modules/url-loader": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/url-loader/-/url-loader-4.1.1.tgz", @@ -18079,6 +19281,15 @@ "url": "https://opencollective.com/webpack" } }, + "node_modules/use-sync-external-store": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz", + "integrity": "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==", + "license": "MIT", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -18117,11 +19328,87 @@ "uuid": "dist/bin/uuid" } }, + "node_modules/validate.io-array": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/validate.io-array/-/validate.io-array-1.0.6.tgz", + "integrity": "sha512-DeOy7CnPEziggrOO5CZhVKJw6S3Yi7e9e65R1Nl/RTN1vTQKnzjfvks0/8kQ40FP/dsjRAOd4hxmJ7uLa6vxkg==", + "license": "MIT" + }, + "node_modules/validate.io-function": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/validate.io-function/-/validate.io-function-1.0.2.tgz", + "integrity": "sha512-LlFybRJEriSuBnUhQyG5bwglhh50EpTL2ul23MPIuR1odjO7XaMLFV8vHGwp7AZciFxtYOeiSCT5st+XSPONiQ==" + }, + "node_modules/validate.io-integer": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/validate.io-integer/-/validate.io-integer-1.0.5.tgz", + "integrity": "sha512-22izsYSLojN/P6bppBqhgUDjCkr5RY2jd+N2a3DCAUey8ydvrZ/OkGvFPR7qfOpwR2LC5p4Ngzxz36g5Vgr/hQ==", + "dependencies": { + "validate.io-number": "^1.0.3" + } + }, + "node_modules/validate.io-integer-array": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/validate.io-integer-array/-/validate.io-integer-array-1.0.0.tgz", + "integrity": "sha512-mTrMk/1ytQHtCY0oNO3dztafHYyGU88KL+jRxWuzfOmQb+4qqnWmI+gykvGp8usKZOM0H7keJHEbRaFiYA0VrA==", + "dependencies": { + "validate.io-array": "^1.0.3", + "validate.io-integer": "^1.0.4" + } + }, + "node_modules/validate.io-number": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/validate.io-number/-/validate.io-number-1.0.3.tgz", + "integrity": "sha512-kRAyotcbNaSYoDnXvb4MHg/0a1egJdLwS6oJ38TJY7aw9n93Fl/3blIXdyYvPOp55CNxywooG/3BcrwNrBpcSg==" + }, "node_modules/value-equal": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/value-equal/-/value-equal-1.0.1.tgz", "integrity": "sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw==" }, + "node_modules/vanilla-jsoneditor": { + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/vanilla-jsoneditor/-/vanilla-jsoneditor-3.11.0.tgz", + "integrity": "sha512-/Zw09Yv8Q2i1yC2q5cDsNtFpyFOQu1Aci4u8dsHwyzhueWnibCMteZz6n1aE9+RGgU92Ni5K4cXTMDUowJPE0A==", + "license": "ISC", + "dependencies": { + "@codemirror/autocomplete": "^6.18.1", + "@codemirror/commands": "^6.7.1", + "@codemirror/lang-json": "^6.0.1", + "@codemirror/language": "^6.10.3", + "@codemirror/lint": "^6.8.2", + "@codemirror/search": "^6.5.6", + "@codemirror/state": "^6.4.1", + "@codemirror/view": "^6.34.1", + "@fortawesome/free-regular-svg-icons": "^6.6.0 || ^7.0.1", + "@fortawesome/free-solid-svg-icons": "^6.6.0 || ^7.0.1", + "@jsonquerylang/jsonquery": "^3.1.1 || ^4.0.0 || ^5.0.0", + "@lezer/highlight": "^1.2.1", + "@replit/codemirror-indentation-markers": "^6.5.3", + "ajv": "^8.17.1", + "codemirror-wrapped-line-indent": "^1.0.8", + "diff-sequences": "^29.6.3", + "immutable-json-patch": "^6.0.1", + "jmespath": "^0.16.0", + "json-source-map": "^0.6.1", + "jsonpath-plus": "^10.3.0", + "jsonrepair": "^3.0.0", + "lodash-es": "^4.17.21", + "memoize-one": "^6.0.0", + "natural-compare-lite": "^1.4.0", + "svelte": "^5.0.0", + "vanilla-picker": "^2.12.3" + } + }, + "node_modules/vanilla-picker": { + "version": "2.12.3", + "resolved": "https://registry.npmjs.org/vanilla-picker/-/vanilla-picker-2.12.3.tgz", + "integrity": "sha512-qVkT1E7yMbUsB2mmJNFmaXMWE2hF8ffqzMMwe9zdAikd8u2VfnsVY2HQcOUi2F38bgbxzlJBEdS1UUhOXdF9GQ==", + "license": "ISC", + "dependencies": { + "@sphinxxxx/color-conversion": "^2.2.2" + } + }, "node_modules/vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", @@ -18171,6 +19458,12 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/w3c-keyname": { + "version": "2.2.8", + "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz", + "integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==", + "license": "MIT" + }, "node_modules/watchpack": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.2.tgz", @@ -18661,6 +19954,12 @@ "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz", "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==" }, + "node_modules/wolfy87-eventemitter": { + "version": "5.2.9", + "resolved": "https://registry.npmjs.org/wolfy87-eventemitter/-/wolfy87-eventemitter-5.2.9.tgz", + "integrity": "sha512-P+6vtWyuDw+MB01X7UeF8TaHBvbCovf4HPEMF/SV7BdDc1SMTiBy13SRD71lQh4ExFTG1d/WNzDGDCyOKSMblw==", + "license": "Unlicense" + }, "node_modules/wrap-ansi": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", @@ -18786,6 +20085,21 @@ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", "license": "ISC" }, + "node_modules/yaml": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.2.tgz", + "integrity": "sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==", + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14.6" + }, + "funding": { + "url": "https://github.com/sponsors/eemeli" + } + }, "node_modules/yocto-queue": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.2.1.tgz", @@ -18798,6 +20112,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/zimmerframe": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/zimmerframe/-/zimmerframe-1.1.4.tgz", + "integrity": "sha512-B58NGBEoc8Y9MWWCQGl/gq9xBCe4IiKM0a2x7GZdQKOW5Exr8S1W24J6OgM1njK8xCRGvAJIL/MxXHf6SkmQKQ==", + "license": "MIT" + }, "node_modules/zwitch": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", diff --git a/docsite/package.json b/docsite/package.json index 8b49f0db..e9a8b0bf 100644 --- a/docsite/package.json +++ b/docsite/package.json @@ -11,7 +11,8 @@ "serve": "docusaurus serve", "write-translations": "docusaurus write-translations", "write-heading-ids": "docusaurus write-heading-ids", - "typecheck": "tsc" + "typecheck": "tsc", + "postinstall": "patch-package" }, "dependencies": { "@docusaurus/core": "3.8.1", @@ -20,15 +21,22 @@ "@docusaurus/preset-classic": "3.8.1", "@easyops-cn/docusaurus-search-local": "0.51.1", "@mdx-js/react": "^3.0.0", + "ajv": "^8.18.0", + "ajv-formats": "^3.0.1", + "cf-json-schema-viz": "^0.3.0", "clsx": "^2.0.0", - "docusaurus-json-schema-plugin": "^1.14.0", + "docusaurus-plugin-sass": "^0.2.6", "docusaurus-theme-github-codeblock": "^2.0.2", "json5": "^2.2.3", "micromark-extension-directive": "^3.0.1", + "modern-react-json-editor": "^1.0.2", + "patch-package": "^8.0.1", "prism-react-renderer": "^2.3.0", "raw-loader": "^4.0.2", "react": "^19.0.0", - "react-dom": "^19.0.0" + "react-dom": "^19.0.0", + "react-markdown": "^10.1.0", + "sass": "^1.97.0" }, "devDependencies": { "@docusaurus/module-type-aliases": "^3.6.3", diff --git a/docsite/patches/cf-json-schema-viz+0.3.0.patch b/docsite/patches/cf-json-schema-viz+0.3.0.patch new file mode 100644 index 00000000..d37d9504 --- /dev/null +++ b/docsite/patches/cf-json-schema-viz+0.3.0.patch @@ -0,0 +1,3547 @@ +diff --git a/node_modules/cf-json-schema-viz/dist/index.d.ts b/node_modules/cf-json-schema-viz/dist/index.d.ts +index 0536c69..be6274b 100644 +--- a/node_modules/cf-json-schema-viz/dist/index.d.ts ++++ b/node_modules/cf-json-schema-viz/dist/index.d.ts +@@ -35,6 +35,7 @@ type JSVOptions = { + renderRootTreeLines?: boolean; + disableCrumbs?: boolean; + nodeHasChanged?: NodeHasChangedFn; ++ markup?: boolean; + }; + + type JsonSchemaProps = Partial & { +diff --git a/node_modules/cf-json-schema-viz/dist/index.js b/node_modules/cf-json-schema-viz/dist/index.js +index b23316c..ef8be1e 100644 +--- a/node_modules/cf-json-schema-viz/dist/index.js ++++ b/node_modules/cf-json-schema-viz/dist/index.js +@@ -41,19 +41,19 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge + )); + var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +-// node_modules/lodash-es/_freeGlobal.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_freeGlobal.js + var freeGlobal, freeGlobal_default; + var init_freeGlobal = __esm({ +- "node_modules/lodash-es/_freeGlobal.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_freeGlobal.js"() { + freeGlobal = typeof global == "object" && global && global.Object === Object && global; + freeGlobal_default = freeGlobal; + } + }); + +-// node_modules/lodash-es/_root.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_root.js + var freeSelf, root, root_default; + var init_root = __esm({ +- "node_modules/lodash-es/_root.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_root.js"() { + init_freeGlobal(); + freeSelf = typeof self == "object" && self && self.Object === Object && self; + root = freeGlobal_default || freeSelf || Function("return this")(); +@@ -61,17 +61,17 @@ var init_root = __esm({ + } + }); + +-// node_modules/lodash-es/_Symbol.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_Symbol.js + var Symbol2, Symbol_default; + var init_Symbol = __esm({ +- "node_modules/lodash-es/_Symbol.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_Symbol.js"() { + init_root(); + Symbol2 = root_default.Symbol; + Symbol_default = Symbol2; + } + }); + +-// node_modules/lodash-es/_getRawTag.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_getRawTag.js + function getRawTag(value) { + var isOwn = hasOwnProperty.call(value, symToStringTag), tag = value[symToStringTag]; + try { +@@ -91,7 +91,7 @@ function getRawTag(value) { + } + var objectProto, hasOwnProperty, nativeObjectToString, symToStringTag, getRawTag_default; + var init_getRawTag = __esm({ +- "node_modules/lodash-es/_getRawTag.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_getRawTag.js"() { + init_Symbol(); + objectProto = Object.prototype; + hasOwnProperty = objectProto.hasOwnProperty; +@@ -101,20 +101,20 @@ var init_getRawTag = __esm({ + } + }); + +-// node_modules/lodash-es/_objectToString.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_objectToString.js + function objectToString(value) { + return nativeObjectToString2.call(value); + } + var objectProto2, nativeObjectToString2, objectToString_default; + var init_objectToString = __esm({ +- "node_modules/lodash-es/_objectToString.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_objectToString.js"() { + objectProto2 = Object.prototype; + nativeObjectToString2 = objectProto2.toString; + objectToString_default = objectToString; + } + }); + +-// node_modules/lodash-es/_baseGetTag.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseGetTag.js + function baseGetTag(value) { + if (value == null) { + return value === void 0 ? undefinedTag : nullTag; +@@ -123,7 +123,7 @@ function baseGetTag(value) { + } + var nullTag, undefinedTag, symToStringTag2, baseGetTag_default; + var init_baseGetTag = __esm({ +- "node_modules/lodash-es/_baseGetTag.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseGetTag.js"() { + init_Symbol(); + init_getRawTag(); + init_objectToString(); +@@ -134,24 +134,24 @@ var init_baseGetTag = __esm({ + } + }); + +-// node_modules/lodash-es/isObjectLike.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/isObjectLike.js + function isObjectLike(value) { + return value != null && typeof value == "object"; + } + var isObjectLike_default; + var init_isObjectLike = __esm({ +- "node_modules/lodash-es/isObjectLike.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/isObjectLike.js"() { + isObjectLike_default = isObjectLike; + } + }); + +-// node_modules/lodash-es/isSymbol.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/isSymbol.js + function isSymbol(value) { + return typeof value == "symbol" || isObjectLike_default(value) && baseGetTag_default(value) == symbolTag; + } + var symbolTag, isSymbol_default; + var init_isSymbol = __esm({ +- "node_modules/lodash-es/isSymbol.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/isSymbol.js"() { + init_baseGetTag(); + init_isObjectLike(); + symbolTag = "[object Symbol]"; +@@ -159,7 +159,7 @@ var init_isSymbol = __esm({ + } + }); + +-// node_modules/lodash-es/_arrayMap.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_arrayMap.js + function arrayMap(array, iteratee) { + var index = -1, length = array == null ? 0 : array.length, result = Array(length); + while (++index < length) { +@@ -169,21 +169,21 @@ function arrayMap(array, iteratee) { + } + var arrayMap_default; + var init_arrayMap = __esm({ +- "node_modules/lodash-es/_arrayMap.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_arrayMap.js"() { + arrayMap_default = arrayMap; + } + }); + +-// node_modules/lodash-es/isArray.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/isArray.js + var isArray, isArray_default; + var init_isArray = __esm({ +- "node_modules/lodash-es/isArray.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/isArray.js"() { + isArray = Array.isArray; + isArray_default = isArray; + } + }); + +-// node_modules/lodash-es/_baseToString.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseToString.js + function baseToString(value) { + if (typeof value == "string") { + return value; +@@ -199,7 +199,7 @@ function baseToString(value) { + } + var INFINITY, symbolProto, symbolToString, baseToString_default; + var init_baseToString = __esm({ +- "node_modules/lodash-es/_baseToString.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseToString.js"() { + init_Symbol(); + init_arrayMap(); + init_isArray(); +@@ -211,30 +211,30 @@ var init_baseToString = __esm({ + } + }); + +-// node_modules/lodash-es/isObject.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/isObject.js + function isObject(value) { + var type = typeof value; + return value != null && (type == "object" || type == "function"); + } + var isObject_default; + var init_isObject = __esm({ +- "node_modules/lodash-es/isObject.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/isObject.js"() { + isObject_default = isObject; + } + }); + +-// node_modules/lodash-es/identity.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/identity.js + function identity(value) { + return value; + } + var identity_default; + var init_identity = __esm({ +- "node_modules/lodash-es/identity.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/identity.js"() { + identity_default = identity; + } + }); + +-// node_modules/lodash-es/isFunction.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/isFunction.js + function isFunction(value) { + if (!isObject_default(value)) { + return false; +@@ -244,7 +244,7 @@ function isFunction(value) { + } + var asyncTag, funcTag, genTag, proxyTag, isFunction_default; + var init_isFunction = __esm({ +- "node_modules/lodash-es/isFunction.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/isFunction.js"() { + init_baseGetTag(); + init_isObject(); + asyncTag = "[object AsyncFunction]"; +@@ -255,23 +255,23 @@ var init_isFunction = __esm({ + } + }); + +-// node_modules/lodash-es/_coreJsData.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_coreJsData.js + var coreJsData, coreJsData_default; + var init_coreJsData = __esm({ +- "node_modules/lodash-es/_coreJsData.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_coreJsData.js"() { + init_root(); + coreJsData = root_default["__core-js_shared__"]; + coreJsData_default = coreJsData; + } + }); + +-// node_modules/lodash-es/_isMasked.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_isMasked.js + function isMasked(func) { + return !!maskSrcKey && maskSrcKey in func; + } + var maskSrcKey, isMasked_default; + var init_isMasked = __esm({ +- "node_modules/lodash-es/_isMasked.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_isMasked.js"() { + init_coreJsData(); + maskSrcKey = (function() { + var uid = /[^.]+$/.exec(coreJsData_default && coreJsData_default.keys && coreJsData_default.keys.IE_PROTO || ""); +@@ -281,7 +281,7 @@ var init_isMasked = __esm({ + } + }); + +-// node_modules/lodash-es/_toSource.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_toSource.js + function toSource(func) { + if (func != null) { + try { +@@ -297,14 +297,14 @@ function toSource(func) { + } + var funcProto, funcToString, toSource_default; + var init_toSource = __esm({ +- "node_modules/lodash-es/_toSource.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_toSource.js"() { + funcProto = Function.prototype; + funcToString = funcProto.toString; + toSource_default = toSource; + } + }); + +-// node_modules/lodash-es/_baseIsNative.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseIsNative.js + function baseIsNative(value) { + if (!isObject_default(value) || isMasked_default(value)) { + return false; +@@ -314,7 +314,7 @@ function baseIsNative(value) { + } + var reRegExpChar, reIsHostCtor, funcProto2, objectProto3, funcToString2, hasOwnProperty2, reIsNative, baseIsNative_default; + var init_baseIsNative = __esm({ +- "node_modules/lodash-es/_baseIsNative.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseIsNative.js"() { + init_isFunction(); + init_isMasked(); + init_isObject(); +@@ -332,35 +332,35 @@ var init_baseIsNative = __esm({ + } + }); + +-// node_modules/lodash-es/_getValue.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_getValue.js + function getValue(object, key) { + return object == null ? void 0 : object[key]; + } + var getValue_default; + var init_getValue = __esm({ +- "node_modules/lodash-es/_getValue.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_getValue.js"() { + getValue_default = getValue; + } + }); + +-// node_modules/lodash-es/_getNative.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_getNative.js + function getNative(object, key) { + var value = getValue_default(object, key); + return baseIsNative_default(value) ? value : void 0; + } + var getNative_default; + var init_getNative = __esm({ +- "node_modules/lodash-es/_getNative.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_getNative.js"() { + init_baseIsNative(); + init_getValue(); + getNative_default = getNative; + } + }); + +-// node_modules/lodash-es/_WeakMap.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_WeakMap.js + var WeakMap2, WeakMap_default; + var init_WeakMap = __esm({ +- "node_modules/lodash-es/_WeakMap.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_WeakMap.js"() { + init_getNative(); + init_root(); + WeakMap2 = getNative_default(root_default, "WeakMap"); +@@ -368,10 +368,10 @@ var init_WeakMap = __esm({ + } + }); + +-// node_modules/lodash-es/_baseCreate.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseCreate.js + var objectCreate, baseCreate, baseCreate_default; + var init_baseCreate = __esm({ +- "node_modules/lodash-es/_baseCreate.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseCreate.js"() { + init_isObject(); + objectCreate = Object.create; + baseCreate = /* @__PURE__ */ (function() { +@@ -394,7 +394,7 @@ var init_baseCreate = __esm({ + } + }); + +-// node_modules/lodash-es/_apply.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_apply.js + function apply(func, thisArg, args) { + switch (args.length) { + case 0: +@@ -410,22 +410,22 @@ function apply(func, thisArg, args) { + } + var apply_default; + var init_apply = __esm({ +- "node_modules/lodash-es/_apply.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_apply.js"() { + apply_default = apply; + } + }); + +-// node_modules/lodash-es/noop.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/noop.js + function noop() { + } + var noop_default; + var init_noop = __esm({ +- "node_modules/lodash-es/noop.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/noop.js"() { + noop_default = noop; + } + }); + +-// node_modules/lodash-es/_copyArray.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_copyArray.js + function copyArray(source, array) { + var index = -1, length = source.length; + array || (array = Array(length)); +@@ -436,12 +436,12 @@ function copyArray(source, array) { + } + var copyArray_default; + var init_copyArray = __esm({ +- "node_modules/lodash-es/_copyArray.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_copyArray.js"() { + copyArray_default = copyArray; + } + }); + +-// node_modules/lodash-es/_shortOut.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_shortOut.js + function shortOut(func) { + var count = 0, lastCalled = 0; + return function() { +@@ -459,7 +459,7 @@ function shortOut(func) { + } + var HOT_COUNT, HOT_SPAN, nativeNow, shortOut_default; + var init_shortOut = __esm({ +- "node_modules/lodash-es/_shortOut.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_shortOut.js"() { + HOT_COUNT = 800; + HOT_SPAN = 16; + nativeNow = Date.now; +@@ -467,7 +467,7 @@ var init_shortOut = __esm({ + } + }); + +-// node_modules/lodash-es/constant.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/constant.js + function constant(value) { + return function() { + return value; +@@ -475,15 +475,15 @@ function constant(value) { + } + var constant_default; + var init_constant = __esm({ +- "node_modules/lodash-es/constant.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/constant.js"() { + constant_default = constant; + } + }); + +-// node_modules/lodash-es/_defineProperty.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_defineProperty.js + var defineProperty, defineProperty_default; + var init_defineProperty = __esm({ +- "node_modules/lodash-es/_defineProperty.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_defineProperty.js"() { + init_getNative(); + defineProperty = (function() { + try { +@@ -497,10 +497,10 @@ var init_defineProperty = __esm({ + } + }); + +-// node_modules/lodash-es/_baseSetToString.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseSetToString.js + var baseSetToString, baseSetToString_default; + var init_baseSetToString = __esm({ +- "node_modules/lodash-es/_baseSetToString.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseSetToString.js"() { + init_constant(); + init_defineProperty(); + init_identity(); +@@ -516,10 +516,10 @@ var init_baseSetToString = __esm({ + } + }); + +-// node_modules/lodash-es/_setToString.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_setToString.js + var setToString, setToString_default; + var init_setToString = __esm({ +- "node_modules/lodash-es/_setToString.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_setToString.js"() { + init_baseSetToString(); + init_shortOut(); + setToString = shortOut_default(baseSetToString_default); +@@ -527,7 +527,7 @@ var init_setToString = __esm({ + } + }); + +-// node_modules/lodash-es/_arrayEach.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_arrayEach.js + function arrayEach(array, iteratee) { + var index = -1, length = array == null ? 0 : array.length; + while (++index < length) { +@@ -539,12 +539,12 @@ function arrayEach(array, iteratee) { + } + var arrayEach_default; + var init_arrayEach = __esm({ +- "node_modules/lodash-es/_arrayEach.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_arrayEach.js"() { + arrayEach_default = arrayEach; + } + }); + +-// node_modules/lodash-es/_baseFindIndex.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseFindIndex.js + function baseFindIndex(array, predicate, fromIndex, fromRight) { + var length = array.length, index = fromIndex + (fromRight ? 1 : -1); + while (fromRight ? index-- : ++index < length) { +@@ -556,23 +556,23 @@ function baseFindIndex(array, predicate, fromIndex, fromRight) { + } + var baseFindIndex_default; + var init_baseFindIndex = __esm({ +- "node_modules/lodash-es/_baseFindIndex.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseFindIndex.js"() { + baseFindIndex_default = baseFindIndex; + } + }); + +-// node_modules/lodash-es/_baseIsNaN.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseIsNaN.js + function baseIsNaN(value) { + return value !== value; + } + var baseIsNaN_default; + var init_baseIsNaN = __esm({ +- "node_modules/lodash-es/_baseIsNaN.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseIsNaN.js"() { + baseIsNaN_default = baseIsNaN; + } + }); + +-// node_modules/lodash-es/_strictIndexOf.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_strictIndexOf.js + function strictIndexOf(array, value, fromIndex) { + var index = fromIndex - 1, length = array.length; + while (++index < length) { +@@ -584,18 +584,18 @@ function strictIndexOf(array, value, fromIndex) { + } + var strictIndexOf_default; + var init_strictIndexOf = __esm({ +- "node_modules/lodash-es/_strictIndexOf.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_strictIndexOf.js"() { + strictIndexOf_default = strictIndexOf; + } + }); + +-// node_modules/lodash-es/_baseIndexOf.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseIndexOf.js + function baseIndexOf(array, value, fromIndex) { + return value === value ? strictIndexOf_default(array, value, fromIndex) : baseFindIndex_default(array, baseIsNaN_default, fromIndex); + } + var baseIndexOf_default; + var init_baseIndexOf = __esm({ +- "node_modules/lodash-es/_baseIndexOf.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseIndexOf.js"() { + init_baseFindIndex(); + init_baseIsNaN(); + init_strictIndexOf(); +@@ -603,20 +603,20 @@ var init_baseIndexOf = __esm({ + } + }); + +-// node_modules/lodash-es/_arrayIncludes.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_arrayIncludes.js + function arrayIncludes(array, value) { + var length = array == null ? 0 : array.length; + return !!length && baseIndexOf_default(array, value, 0) > -1; + } + var arrayIncludes_default; + var init_arrayIncludes = __esm({ +- "node_modules/lodash-es/_arrayIncludes.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_arrayIncludes.js"() { + init_baseIndexOf(); + arrayIncludes_default = arrayIncludes; + } + }); + +-// node_modules/lodash-es/_isIndex.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_isIndex.js + function isIndex(value, length) { + var type = typeof value; + length = length == null ? MAX_SAFE_INTEGER : length; +@@ -624,14 +624,14 @@ function isIndex(value, length) { + } + var MAX_SAFE_INTEGER, reIsUint, isIndex_default; + var init_isIndex = __esm({ +- "node_modules/lodash-es/_isIndex.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_isIndex.js"() { + MAX_SAFE_INTEGER = 9007199254740991; + reIsUint = /^(?:0|[1-9]\d*)$/; + isIndex_default = isIndex; + } + }); + +-// node_modules/lodash-es/_baseAssignValue.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseAssignValue.js + function baseAssignValue(object, key, value) { + if (key == "__proto__" && defineProperty_default) { + defineProperty_default(object, key, { +@@ -646,24 +646,24 @@ function baseAssignValue(object, key, value) { + } + var baseAssignValue_default; + var init_baseAssignValue = __esm({ +- "node_modules/lodash-es/_baseAssignValue.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseAssignValue.js"() { + init_defineProperty(); + baseAssignValue_default = baseAssignValue; + } + }); + +-// node_modules/lodash-es/eq.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/eq.js + function eq(value, other) { + return value === other || value !== value && other !== other; + } + var eq_default; + var init_eq = __esm({ +- "node_modules/lodash-es/eq.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/eq.js"() { + eq_default = eq; + } + }); + +-// node_modules/lodash-es/_assignValue.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_assignValue.js + function assignValue(object, key, value) { + var objValue = object[key]; + if (!(hasOwnProperty3.call(object, key) && eq_default(objValue, value)) || value === void 0 && !(key in object)) { +@@ -672,7 +672,7 @@ function assignValue(object, key, value) { + } + var objectProto4, hasOwnProperty3, assignValue_default; + var init_assignValue = __esm({ +- "node_modules/lodash-es/_assignValue.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_assignValue.js"() { + init_baseAssignValue(); + init_eq(); + objectProto4 = Object.prototype; +@@ -681,7 +681,7 @@ var init_assignValue = __esm({ + } + }); + +-// node_modules/lodash-es/_copyObject.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_copyObject.js + function copyObject(source, props, object, customizer) { + var isNew = !object; + object || (object = {}); +@@ -702,14 +702,14 @@ function copyObject(source, props, object, customizer) { + } + var copyObject_default; + var init_copyObject = __esm({ +- "node_modules/lodash-es/_copyObject.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_copyObject.js"() { + init_assignValue(); + init_baseAssignValue(); + copyObject_default = copyObject; + } + }); + +-// node_modules/lodash-es/_overRest.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_overRest.js + function overRest(func, start, transform) { + start = nativeMax(start === void 0 ? func.length - 1 : start, 0); + return function() { +@@ -728,20 +728,20 @@ function overRest(func, start, transform) { + } + var nativeMax, overRest_default; + var init_overRest = __esm({ +- "node_modules/lodash-es/_overRest.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_overRest.js"() { + init_apply(); + nativeMax = Math.max; + overRest_default = overRest; + } + }); + +-// node_modules/lodash-es/_baseRest.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseRest.js + function baseRest(func, start) { + return setToString_default(overRest_default(func, start, identity_default), func + ""); + } + var baseRest_default; + var init_baseRest = __esm({ +- "node_modules/lodash-es/_baseRest.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseRest.js"() { + init_identity(); + init_overRest(); + init_setToString(); +@@ -749,32 +749,32 @@ var init_baseRest = __esm({ + } + }); + +-// node_modules/lodash-es/isLength.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/isLength.js + function isLength(value) { + return typeof value == "number" && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER2; + } + var MAX_SAFE_INTEGER2, isLength_default; + var init_isLength = __esm({ +- "node_modules/lodash-es/isLength.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/isLength.js"() { + MAX_SAFE_INTEGER2 = 9007199254740991; + isLength_default = isLength; + } + }); + +-// node_modules/lodash-es/isArrayLike.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/isArrayLike.js + function isArrayLike(value) { + return value != null && isLength_default(value.length) && !isFunction_default(value); + } + var isArrayLike_default; + var init_isArrayLike = __esm({ +- "node_modules/lodash-es/isArrayLike.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/isArrayLike.js"() { + init_isFunction(); + init_isLength(); + isArrayLike_default = isArrayLike; + } + }); + +-// node_modules/lodash-es/_isIterateeCall.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_isIterateeCall.js + function isIterateeCall(value, index, object) { + if (!isObject_default(object)) { + return false; +@@ -787,7 +787,7 @@ function isIterateeCall(value, index, object) { + } + var isIterateeCall_default; + var init_isIterateeCall = __esm({ +- "node_modules/lodash-es/_isIterateeCall.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_isIterateeCall.js"() { + init_eq(); + init_isArrayLike(); + init_isIndex(); +@@ -796,7 +796,7 @@ var init_isIterateeCall = __esm({ + } + }); + +-// node_modules/lodash-es/_createAssigner.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_createAssigner.js + function createAssigner(assigner) { + return baseRest_default(function(object, sources) { + var index = -1, length = sources.length, customizer = length > 1 ? sources[length - 1] : void 0, guard = length > 2 ? sources[2] : void 0; +@@ -817,27 +817,27 @@ function createAssigner(assigner) { + } + var createAssigner_default; + var init_createAssigner = __esm({ +- "node_modules/lodash-es/_createAssigner.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_createAssigner.js"() { + init_baseRest(); + init_isIterateeCall(); + createAssigner_default = createAssigner; + } + }); + +-// node_modules/lodash-es/_isPrototype.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_isPrototype.js + function isPrototype(value) { + var Ctor = value && value.constructor, proto = typeof Ctor == "function" && Ctor.prototype || objectProto5; + return value === proto; + } + var objectProto5, isPrototype_default; + var init_isPrototype = __esm({ +- "node_modules/lodash-es/_isPrototype.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_isPrototype.js"() { + objectProto5 = Object.prototype; + isPrototype_default = isPrototype; + } + }); + +-// node_modules/lodash-es/_baseTimes.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseTimes.js + function baseTimes(n, iteratee) { + var index = -1, result = Array(n); + while (++index < n) { +@@ -847,18 +847,18 @@ function baseTimes(n, iteratee) { + } + var baseTimes_default; + var init_baseTimes = __esm({ +- "node_modules/lodash-es/_baseTimes.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseTimes.js"() { + baseTimes_default = baseTimes; + } + }); + +-// node_modules/lodash-es/_baseIsArguments.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseIsArguments.js + function baseIsArguments(value) { + return isObjectLike_default(value) && baseGetTag_default(value) == argsTag; + } + var argsTag, baseIsArguments_default; + var init_baseIsArguments = __esm({ +- "node_modules/lodash-es/_baseIsArguments.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseIsArguments.js"() { + init_baseGetTag(); + init_isObjectLike(); + argsTag = "[object Arguments]"; +@@ -866,10 +866,10 @@ var init_baseIsArguments = __esm({ + } + }); + +-// node_modules/lodash-es/isArguments.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/isArguments.js + var objectProto6, hasOwnProperty4, propertyIsEnumerable, isArguments, isArguments_default; + var init_isArguments = __esm({ +- "node_modules/lodash-es/isArguments.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/isArguments.js"() { + init_baseIsArguments(); + init_isObjectLike(); + objectProto6 = Object.prototype; +@@ -884,21 +884,21 @@ var init_isArguments = __esm({ + } + }); + +-// node_modules/lodash-es/stubFalse.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/stubFalse.js + function stubFalse() { + return false; + } + var stubFalse_default; + var init_stubFalse = __esm({ +- "node_modules/lodash-es/stubFalse.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/stubFalse.js"() { + stubFalse_default = stubFalse; + } + }); + +-// node_modules/lodash-es/isBuffer.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/isBuffer.js + var freeExports, freeModule, moduleExports, Buffer2, nativeIsBuffer, isBuffer, isBuffer_default; + var init_isBuffer = __esm({ +- "node_modules/lodash-es/isBuffer.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/isBuffer.js"() { + init_root(); + init_stubFalse(); + freeExports = typeof exports == "object" && exports && !exports.nodeType && exports; +@@ -911,13 +911,13 @@ var init_isBuffer = __esm({ + } + }); + +-// node_modules/lodash-es/_baseIsTypedArray.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseIsTypedArray.js + function baseIsTypedArray(value) { + return isObjectLike_default(value) && isLength_default(value.length) && !!typedArrayTags[baseGetTag_default(value)]; + } + var argsTag2, arrayTag, boolTag, dateTag, errorTag, funcTag2, mapTag, numberTag, objectTag, regexpTag, setTag, stringTag, weakMapTag, arrayBufferTag, dataViewTag, float32Tag, float64Tag, int8Tag, int16Tag, int32Tag, uint8Tag, uint8ClampedTag, uint16Tag, uint32Tag, typedArrayTags, baseIsTypedArray_default; + var init_baseIsTypedArray = __esm({ +- "node_modules/lodash-es/_baseIsTypedArray.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseIsTypedArray.js"() { + init_baseGetTag(); + init_isLength(); + init_isObjectLike(); +@@ -952,7 +952,7 @@ var init_baseIsTypedArray = __esm({ + } + }); + +-// node_modules/lodash-es/_baseUnary.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseUnary.js + function baseUnary(func) { + return function(value) { + return func(value); +@@ -960,15 +960,15 @@ function baseUnary(func) { + } + var baseUnary_default; + var init_baseUnary = __esm({ +- "node_modules/lodash-es/_baseUnary.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseUnary.js"() { + baseUnary_default = baseUnary; + } + }); + +-// node_modules/lodash-es/_nodeUtil.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_nodeUtil.js + var freeExports2, freeModule2, moduleExports2, freeProcess, nodeUtil, nodeUtil_default; + var init_nodeUtil = __esm({ +- "node_modules/lodash-es/_nodeUtil.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_nodeUtil.js"() { + init_freeGlobal(); + freeExports2 = typeof exports == "object" && exports && !exports.nodeType && exports; + freeModule2 = freeExports2 && typeof module == "object" && module && !module.nodeType && module; +@@ -988,10 +988,10 @@ var init_nodeUtil = __esm({ + } + }); + +-// node_modules/lodash-es/isTypedArray.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/isTypedArray.js + var nodeIsTypedArray, isTypedArray, isTypedArray_default; + var init_isTypedArray = __esm({ +- "node_modules/lodash-es/isTypedArray.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/isTypedArray.js"() { + init_baseIsTypedArray(); + init_baseUnary(); + init_nodeUtil(); +@@ -1001,7 +1001,7 @@ var init_isTypedArray = __esm({ + } + }); + +-// node_modules/lodash-es/_arrayLikeKeys.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_arrayLikeKeys.js + function arrayLikeKeys(value, inherited) { + var isArr = isArray_default(value), isArg = !isArr && isArguments_default(value), isBuff = !isArr && !isArg && isBuffer_default(value), isType = !isArr && !isArg && !isBuff && isTypedArray_default(value), skipIndexes = isArr || isArg || isBuff || isType, result = skipIndexes ? baseTimes_default(value.length, String) : [], length = result.length; + for (var key in value) { +@@ -1017,7 +1017,7 @@ function arrayLikeKeys(value, inherited) { + } + var objectProto7, hasOwnProperty5, arrayLikeKeys_default; + var init_arrayLikeKeys = __esm({ +- "node_modules/lodash-es/_arrayLikeKeys.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_arrayLikeKeys.js"() { + init_baseTimes(); + init_isArguments(); + init_isArray(); +@@ -1030,7 +1030,7 @@ var init_arrayLikeKeys = __esm({ + } + }); + +-// node_modules/lodash-es/_overArg.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_overArg.js + function overArg(func, transform) { + return function(arg) { + return func(transform(arg)); +@@ -1038,22 +1038,22 @@ function overArg(func, transform) { + } + var overArg_default; + var init_overArg = __esm({ +- "node_modules/lodash-es/_overArg.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_overArg.js"() { + overArg_default = overArg; + } + }); + +-// node_modules/lodash-es/_nativeKeys.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_nativeKeys.js + var nativeKeys, nativeKeys_default; + var init_nativeKeys = __esm({ +- "node_modules/lodash-es/_nativeKeys.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_nativeKeys.js"() { + init_overArg(); + nativeKeys = overArg_default(Object.keys, Object); + nativeKeys_default = nativeKeys; + } + }); + +-// node_modules/lodash-es/_baseKeys.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseKeys.js + function baseKeys(object) { + if (!isPrototype_default(object)) { + return nativeKeys_default(object); +@@ -1068,7 +1068,7 @@ function baseKeys(object) { + } + var objectProto8, hasOwnProperty6, baseKeys_default; + var init_baseKeys = __esm({ +- "node_modules/lodash-es/_baseKeys.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseKeys.js"() { + init_isPrototype(); + init_nativeKeys(); + objectProto8 = Object.prototype; +@@ -1077,13 +1077,13 @@ var init_baseKeys = __esm({ + } + }); + +-// node_modules/lodash-es/keys.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/keys.js + function keys(object) { + return isArrayLike_default(object) ? arrayLikeKeys_default(object) : baseKeys_default(object); + } + var keys_default; + var init_keys = __esm({ +- "node_modules/lodash-es/keys.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/keys.js"() { + init_arrayLikeKeys(); + init_baseKeys(); + init_isArrayLike(); +@@ -1091,7 +1091,7 @@ var init_keys = __esm({ + } + }); + +-// node_modules/lodash-es/_nativeKeysIn.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_nativeKeysIn.js + function nativeKeysIn(object) { + var result = []; + if (object != null) { +@@ -1103,12 +1103,12 @@ function nativeKeysIn(object) { + } + var nativeKeysIn_default; + var init_nativeKeysIn = __esm({ +- "node_modules/lodash-es/_nativeKeysIn.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_nativeKeysIn.js"() { + nativeKeysIn_default = nativeKeysIn; + } + }); + +-// node_modules/lodash-es/_baseKeysIn.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseKeysIn.js + function baseKeysIn(object) { + if (!isObject_default(object)) { + return nativeKeysIn_default(object); +@@ -1123,7 +1123,7 @@ function baseKeysIn(object) { + } + var objectProto9, hasOwnProperty7, baseKeysIn_default; + var init_baseKeysIn = __esm({ +- "node_modules/lodash-es/_baseKeysIn.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseKeysIn.js"() { + init_isObject(); + init_isPrototype(); + init_nativeKeysIn(); +@@ -1133,13 +1133,13 @@ var init_baseKeysIn = __esm({ + } + }); + +-// node_modules/lodash-es/keysIn.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/keysIn.js + function keysIn(object) { + return isArrayLike_default(object) ? arrayLikeKeys_default(object, true) : baseKeysIn_default(object); + } + var keysIn_default; + var init_keysIn = __esm({ +- "node_modules/lodash-es/keysIn.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/keysIn.js"() { + init_arrayLikeKeys(); + init_baseKeysIn(); + init_isArrayLike(); +@@ -1147,7 +1147,7 @@ var init_keysIn = __esm({ + } + }); + +-// node_modules/lodash-es/_isKey.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_isKey.js + function isKey(value, object) { + if (isArray_default(value)) { + return false; +@@ -1160,7 +1160,7 @@ function isKey(value, object) { + } + var reIsDeepProp, reIsPlainProp, isKey_default; + var init_isKey = __esm({ +- "node_modules/lodash-es/_isKey.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_isKey.js"() { + init_isArray(); + init_isSymbol(); + reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/; +@@ -1169,30 +1169,30 @@ var init_isKey = __esm({ + } + }); + +-// node_modules/lodash-es/_nativeCreate.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_nativeCreate.js + var nativeCreate, nativeCreate_default; + var init_nativeCreate = __esm({ +- "node_modules/lodash-es/_nativeCreate.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_nativeCreate.js"() { + init_getNative(); + nativeCreate = getNative_default(Object, "create"); + nativeCreate_default = nativeCreate; + } + }); + +-// node_modules/lodash-es/_hashClear.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_hashClear.js + function hashClear() { + this.__data__ = nativeCreate_default ? nativeCreate_default(null) : {}; + this.size = 0; + } + var hashClear_default; + var init_hashClear = __esm({ +- "node_modules/lodash-es/_hashClear.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_hashClear.js"() { + init_nativeCreate(); + hashClear_default = hashClear; + } + }); + +-// node_modules/lodash-es/_hashDelete.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_hashDelete.js + function hashDelete(key) { + var result = this.has(key) && delete this.__data__[key]; + this.size -= result ? 1 : 0; +@@ -1200,12 +1200,12 @@ function hashDelete(key) { + } + var hashDelete_default; + var init_hashDelete = __esm({ +- "node_modules/lodash-es/_hashDelete.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_hashDelete.js"() { + hashDelete_default = hashDelete; + } + }); + +-// node_modules/lodash-es/_hashGet.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_hashGet.js + function hashGet(key) { + var data = this.__data__; + if (nativeCreate_default) { +@@ -1216,7 +1216,7 @@ function hashGet(key) { + } + var HASH_UNDEFINED, objectProto10, hasOwnProperty8, hashGet_default; + var init_hashGet = __esm({ +- "node_modules/lodash-es/_hashGet.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_hashGet.js"() { + init_nativeCreate(); + HASH_UNDEFINED = "__lodash_hash_undefined__"; + objectProto10 = Object.prototype; +@@ -1225,14 +1225,14 @@ var init_hashGet = __esm({ + } + }); + +-// node_modules/lodash-es/_hashHas.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_hashHas.js + function hashHas(key) { + var data = this.__data__; + return nativeCreate_default ? data[key] !== void 0 : hasOwnProperty9.call(data, key); + } + var objectProto11, hasOwnProperty9, hashHas_default; + var init_hashHas = __esm({ +- "node_modules/lodash-es/_hashHas.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_hashHas.js"() { + init_nativeCreate(); + objectProto11 = Object.prototype; + hasOwnProperty9 = objectProto11.hasOwnProperty; +@@ -1240,7 +1240,7 @@ var init_hashHas = __esm({ + } + }); + +-// node_modules/lodash-es/_hashSet.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_hashSet.js + function hashSet(key, value) { + var data = this.__data__; + this.size += this.has(key) ? 0 : 1; +@@ -1249,14 +1249,14 @@ function hashSet(key, value) { + } + var HASH_UNDEFINED2, hashSet_default; + var init_hashSet = __esm({ +- "node_modules/lodash-es/_hashSet.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_hashSet.js"() { + init_nativeCreate(); + HASH_UNDEFINED2 = "__lodash_hash_undefined__"; + hashSet_default = hashSet; + } + }); + +-// node_modules/lodash-es/_Hash.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_Hash.js + function Hash(entries) { + var index = -1, length = entries == null ? 0 : entries.length; + this.clear(); +@@ -1267,7 +1267,7 @@ function Hash(entries) { + } + var Hash_default; + var init_Hash = __esm({ +- "node_modules/lodash-es/_Hash.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_Hash.js"() { + init_hashClear(); + init_hashDelete(); + init_hashGet(); +@@ -1282,19 +1282,19 @@ var init_Hash = __esm({ + } + }); + +-// node_modules/lodash-es/_listCacheClear.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_listCacheClear.js + function listCacheClear() { + this.__data__ = []; + this.size = 0; + } + var listCacheClear_default; + var init_listCacheClear = __esm({ +- "node_modules/lodash-es/_listCacheClear.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_listCacheClear.js"() { + listCacheClear_default = listCacheClear; + } + }); + +-// node_modules/lodash-es/_assocIndexOf.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_assocIndexOf.js + function assocIndexOf(array, key) { + var length = array.length; + while (length--) { +@@ -1306,13 +1306,13 @@ function assocIndexOf(array, key) { + } + var assocIndexOf_default; + var init_assocIndexOf = __esm({ +- "node_modules/lodash-es/_assocIndexOf.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_assocIndexOf.js"() { + init_eq(); + assocIndexOf_default = assocIndexOf; + } + }); + +-// node_modules/lodash-es/_listCacheDelete.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_listCacheDelete.js + function listCacheDelete(key) { + var data = this.__data__, index = assocIndexOf_default(data, key); + if (index < 0) { +@@ -1329,7 +1329,7 @@ function listCacheDelete(key) { + } + var arrayProto, splice, listCacheDelete_default; + var init_listCacheDelete = __esm({ +- "node_modules/lodash-es/_listCacheDelete.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_listCacheDelete.js"() { + init_assocIndexOf(); + arrayProto = Array.prototype; + splice = arrayProto.splice; +@@ -1337,32 +1337,32 @@ var init_listCacheDelete = __esm({ + } + }); + +-// node_modules/lodash-es/_listCacheGet.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_listCacheGet.js + function listCacheGet(key) { + var data = this.__data__, index = assocIndexOf_default(data, key); + return index < 0 ? void 0 : data[index][1]; + } + var listCacheGet_default; + var init_listCacheGet = __esm({ +- "node_modules/lodash-es/_listCacheGet.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_listCacheGet.js"() { + init_assocIndexOf(); + listCacheGet_default = listCacheGet; + } + }); + +-// node_modules/lodash-es/_listCacheHas.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_listCacheHas.js + function listCacheHas(key) { + return assocIndexOf_default(this.__data__, key) > -1; + } + var listCacheHas_default; + var init_listCacheHas = __esm({ +- "node_modules/lodash-es/_listCacheHas.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_listCacheHas.js"() { + init_assocIndexOf(); + listCacheHas_default = listCacheHas; + } + }); + +-// node_modules/lodash-es/_listCacheSet.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_listCacheSet.js + function listCacheSet(key, value) { + var data = this.__data__, index = assocIndexOf_default(data, key); + if (index < 0) { +@@ -1375,13 +1375,13 @@ function listCacheSet(key, value) { + } + var listCacheSet_default; + var init_listCacheSet = __esm({ +- "node_modules/lodash-es/_listCacheSet.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_listCacheSet.js"() { + init_assocIndexOf(); + listCacheSet_default = listCacheSet; + } + }); + +-// node_modules/lodash-es/_ListCache.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_ListCache.js + function ListCache(entries) { + var index = -1, length = entries == null ? 0 : entries.length; + this.clear(); +@@ -1392,7 +1392,7 @@ function ListCache(entries) { + } + var ListCache_default; + var init_ListCache = __esm({ +- "node_modules/lodash-es/_ListCache.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_ListCache.js"() { + init_listCacheClear(); + init_listCacheDelete(); + init_listCacheGet(); +@@ -1407,10 +1407,10 @@ var init_ListCache = __esm({ + } + }); + +-// node_modules/lodash-es/_Map.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_Map.js + var Map2, Map_default; + var init_Map = __esm({ +- "node_modules/lodash-es/_Map.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_Map.js"() { + init_getNative(); + init_root(); + Map2 = getNative_default(root_default, "Map"); +@@ -1418,7 +1418,7 @@ var init_Map = __esm({ + } + }); + +-// node_modules/lodash-es/_mapCacheClear.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_mapCacheClear.js + function mapCacheClear() { + this.size = 0; + this.__data__ = { +@@ -1429,7 +1429,7 @@ function mapCacheClear() { + } + var mapCacheClear_default; + var init_mapCacheClear = __esm({ +- "node_modules/lodash-es/_mapCacheClear.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_mapCacheClear.js"() { + init_Hash(); + init_ListCache(); + init_Map(); +@@ -1437,32 +1437,32 @@ var init_mapCacheClear = __esm({ + } + }); + +-// node_modules/lodash-es/_isKeyable.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_isKeyable.js + function isKeyable(value) { + var type = typeof value; + return type == "string" || type == "number" || type == "symbol" || type == "boolean" ? value !== "__proto__" : value === null; + } + var isKeyable_default; + var init_isKeyable = __esm({ +- "node_modules/lodash-es/_isKeyable.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_isKeyable.js"() { + isKeyable_default = isKeyable; + } + }); + +-// node_modules/lodash-es/_getMapData.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_getMapData.js + function getMapData(map, key) { + var data = map.__data__; + return isKeyable_default(key) ? data[typeof key == "string" ? "string" : "hash"] : data.map; + } + var getMapData_default; + var init_getMapData = __esm({ +- "node_modules/lodash-es/_getMapData.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_getMapData.js"() { + init_isKeyable(); + getMapData_default = getMapData; + } + }); + +-// node_modules/lodash-es/_mapCacheDelete.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_mapCacheDelete.js + function mapCacheDelete(key) { + var result = getMapData_default(this, key)["delete"](key); + this.size -= result ? 1 : 0; +@@ -1470,37 +1470,37 @@ function mapCacheDelete(key) { + } + var mapCacheDelete_default; + var init_mapCacheDelete = __esm({ +- "node_modules/lodash-es/_mapCacheDelete.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_mapCacheDelete.js"() { + init_getMapData(); + mapCacheDelete_default = mapCacheDelete; + } + }); + +-// node_modules/lodash-es/_mapCacheGet.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_mapCacheGet.js + function mapCacheGet(key) { + return getMapData_default(this, key).get(key); + } + var mapCacheGet_default; + var init_mapCacheGet = __esm({ +- "node_modules/lodash-es/_mapCacheGet.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_mapCacheGet.js"() { + init_getMapData(); + mapCacheGet_default = mapCacheGet; + } + }); + +-// node_modules/lodash-es/_mapCacheHas.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_mapCacheHas.js + function mapCacheHas(key) { + return getMapData_default(this, key).has(key); + } + var mapCacheHas_default; + var init_mapCacheHas = __esm({ +- "node_modules/lodash-es/_mapCacheHas.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_mapCacheHas.js"() { + init_getMapData(); + mapCacheHas_default = mapCacheHas; + } + }); + +-// node_modules/lodash-es/_mapCacheSet.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_mapCacheSet.js + function mapCacheSet(key, value) { + var data = getMapData_default(this, key), size = data.size; + data.set(key, value); +@@ -1509,13 +1509,13 @@ function mapCacheSet(key, value) { + } + var mapCacheSet_default; + var init_mapCacheSet = __esm({ +- "node_modules/lodash-es/_mapCacheSet.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_mapCacheSet.js"() { + init_getMapData(); + mapCacheSet_default = mapCacheSet; + } + }); + +-// node_modules/lodash-es/_MapCache.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_MapCache.js + function MapCache(entries) { + var index = -1, length = entries == null ? 0 : entries.length; + this.clear(); +@@ -1526,7 +1526,7 @@ function MapCache(entries) { + } + var MapCache_default; + var init_MapCache = __esm({ +- "node_modules/lodash-es/_MapCache.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_MapCache.js"() { + init_mapCacheClear(); + init_mapCacheDelete(); + init_mapCacheGet(); +@@ -1541,7 +1541,7 @@ var init_MapCache = __esm({ + } + }); + +-// node_modules/lodash-es/memoize.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/memoize.js + function memoize(func, resolver) { + if (typeof func != "function" || resolver != null && typeof resolver != "function") { + throw new TypeError(FUNC_ERROR_TEXT); +@@ -1560,7 +1560,7 @@ function memoize(func, resolver) { + } + var FUNC_ERROR_TEXT, memoize_default; + var init_memoize = __esm({ +- "node_modules/lodash-es/memoize.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/memoize.js"() { + init_MapCache(); + FUNC_ERROR_TEXT = "Expected a function"; + memoize.Cache = MapCache_default; +@@ -1568,7 +1568,7 @@ var init_memoize = __esm({ + } + }); + +-// node_modules/lodash-es/_memoizeCapped.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_memoizeCapped.js + function memoizeCapped(func) { + var result = memoize_default(func, function(key) { + if (cache.size === MAX_MEMOIZE_SIZE) { +@@ -1581,17 +1581,17 @@ function memoizeCapped(func) { + } + var MAX_MEMOIZE_SIZE, memoizeCapped_default; + var init_memoizeCapped = __esm({ +- "node_modules/lodash-es/_memoizeCapped.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_memoizeCapped.js"() { + init_memoize(); + MAX_MEMOIZE_SIZE = 500; + memoizeCapped_default = memoizeCapped; + } + }); + +-// node_modules/lodash-es/_stringToPath.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_stringToPath.js + var rePropName, reEscapeChar, stringToPath, stringToPath_default; + var init_stringToPath = __esm({ +- "node_modules/lodash-es/_stringToPath.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_stringToPath.js"() { + init_memoizeCapped(); + rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g; + reEscapeChar = /\\(\\)?/g; +@@ -1609,19 +1609,19 @@ var init_stringToPath = __esm({ + } + }); + +-// node_modules/lodash-es/toString.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/toString.js + function toString(value) { + return value == null ? "" : baseToString_default(value); + } + var toString_default; + var init_toString = __esm({ +- "node_modules/lodash-es/toString.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/toString.js"() { + init_baseToString(); + toString_default = toString; + } + }); + +-// node_modules/lodash-es/_castPath.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_castPath.js + function castPath(value, object) { + if (isArray_default(value)) { + return value; +@@ -1630,7 +1630,7 @@ function castPath(value, object) { + } + var castPath_default; + var init_castPath = __esm({ +- "node_modules/lodash-es/_castPath.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_castPath.js"() { + init_isArray(); + init_isKey(); + init_stringToPath(); +@@ -1639,7 +1639,7 @@ var init_castPath = __esm({ + } + }); + +-// node_modules/lodash-es/_toKey.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_toKey.js + function toKey(value) { + if (typeof value == "string" || isSymbol_default(value)) { + return value; +@@ -1649,14 +1649,14 @@ function toKey(value) { + } + var INFINITY2, toKey_default; + var init_toKey = __esm({ +- "node_modules/lodash-es/_toKey.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_toKey.js"() { + init_isSymbol(); + INFINITY2 = 1 / 0; + toKey_default = toKey; + } + }); + +-// node_modules/lodash-es/_baseGet.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseGet.js + function baseGet(object, path) { + path = castPath_default(path, object); + var index = 0, length = path.length; +@@ -1667,27 +1667,27 @@ function baseGet(object, path) { + } + var baseGet_default; + var init_baseGet = __esm({ +- "node_modules/lodash-es/_baseGet.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseGet.js"() { + init_castPath(); + init_toKey(); + baseGet_default = baseGet; + } + }); + +-// node_modules/lodash-es/get.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/get.js + function get(object, path, defaultValue) { + var result = object == null ? void 0 : baseGet_default(object, path); + return result === void 0 ? defaultValue : result; + } + var get_default; + var init_get = __esm({ +- "node_modules/lodash-es/get.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/get.js"() { + init_baseGet(); + get_default = get; + } + }); + +-// node_modules/lodash-es/_arrayPush.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_arrayPush.js + function arrayPush(array, values) { + var index = -1, length = values.length, offset = array.length; + while (++index < length) { +@@ -1697,18 +1697,18 @@ function arrayPush(array, values) { + } + var arrayPush_default; + var init_arrayPush = __esm({ +- "node_modules/lodash-es/_arrayPush.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_arrayPush.js"() { + arrayPush_default = arrayPush; + } + }); + +-// node_modules/lodash-es/_isFlattenable.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_isFlattenable.js + function isFlattenable(value) { + return isArray_default(value) || isArguments_default(value) || !!(spreadableSymbol && value && value[spreadableSymbol]); + } + var spreadableSymbol, isFlattenable_default; + var init_isFlattenable = __esm({ +- "node_modules/lodash-es/_isFlattenable.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_isFlattenable.js"() { + init_Symbol(); + init_isArguments(); + init_isArray(); +@@ -1717,7 +1717,7 @@ var init_isFlattenable = __esm({ + } + }); + +-// node_modules/lodash-es/_baseFlatten.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseFlatten.js + function baseFlatten(array, depth, predicate, isStrict, result) { + var index = -1, length = array.length; + predicate || (predicate = isFlattenable_default); +@@ -1738,14 +1738,14 @@ function baseFlatten(array, depth, predicate, isStrict, result) { + } + var baseFlatten_default; + var init_baseFlatten = __esm({ +- "node_modules/lodash-es/_baseFlatten.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseFlatten.js"() { + init_arrayPush(); + init_isFlattenable(); + baseFlatten_default = baseFlatten; + } + }); + +-// node_modules/lodash-es/flatten.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/flatten.js + var flatten_exports = {}; + __export(flatten_exports, { + default: () => flatten_default +@@ -1756,19 +1756,19 @@ function flatten(array) { + } + var flatten_default; + var init_flatten = __esm({ +- "node_modules/lodash-es/flatten.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/flatten.js"() { + init_baseFlatten(); + flatten_default = flatten; + } + }); + +-// node_modules/lodash-es/_flatRest.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_flatRest.js + function flatRest(func) { + return setToString_default(overRest_default(func, void 0, flatten_default), func + ""); + } + var flatRest_default; + var init_flatRest = __esm({ +- "node_modules/lodash-es/_flatRest.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_flatRest.js"() { + init_flatten(); + init_overRest(); + init_setToString(); +@@ -1776,17 +1776,17 @@ var init_flatRest = __esm({ + } + }); + +-// node_modules/lodash-es/_getPrototype.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_getPrototype.js + var getPrototype, getPrototype_default; + var init_getPrototype = __esm({ +- "node_modules/lodash-es/_getPrototype.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_getPrototype.js"() { + init_overArg(); + getPrototype = overArg_default(Object.getPrototypeOf, Object); + getPrototype_default = getPrototype; + } + }); + +-// node_modules/lodash-es/isPlainObject.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/isPlainObject.js + var isPlainObject_exports = {}; + __export(isPlainObject_exports, { + default: () => isPlainObject_default +@@ -1804,7 +1804,7 @@ function isPlainObject(value) { + } + var objectTag2, funcProto3, objectProto12, funcToString3, hasOwnProperty10, objectCtorString, isPlainObject_default; + var init_isPlainObject = __esm({ +- "node_modules/lodash-es/isPlainObject.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/isPlainObject.js"() { + init_baseGetTag(); + init_getPrototype(); + init_isObjectLike(); +@@ -1818,20 +1818,20 @@ var init_isPlainObject = __esm({ + } + }); + +-// node_modules/lodash-es/_stackClear.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_stackClear.js + function stackClear() { + this.__data__ = new ListCache_default(); + this.size = 0; + } + var stackClear_default; + var init_stackClear = __esm({ +- "node_modules/lodash-es/_stackClear.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_stackClear.js"() { + init_ListCache(); + stackClear_default = stackClear; + } + }); + +-// node_modules/lodash-es/_stackDelete.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_stackDelete.js + function stackDelete(key) { + var data = this.__data__, result = data["delete"](key); + this.size = data.size; +@@ -1839,34 +1839,34 @@ function stackDelete(key) { + } + var stackDelete_default; + var init_stackDelete = __esm({ +- "node_modules/lodash-es/_stackDelete.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_stackDelete.js"() { + stackDelete_default = stackDelete; + } + }); + +-// node_modules/lodash-es/_stackGet.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_stackGet.js + function stackGet(key) { + return this.__data__.get(key); + } + var stackGet_default; + var init_stackGet = __esm({ +- "node_modules/lodash-es/_stackGet.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_stackGet.js"() { + stackGet_default = stackGet; + } + }); + +-// node_modules/lodash-es/_stackHas.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_stackHas.js + function stackHas(key) { + return this.__data__.has(key); + } + var stackHas_default; + var init_stackHas = __esm({ +- "node_modules/lodash-es/_stackHas.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_stackHas.js"() { + stackHas_default = stackHas; + } + }); + +-// node_modules/lodash-es/_stackSet.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_stackSet.js + function stackSet(key, value) { + var data = this.__data__; + if (data instanceof ListCache_default) { +@@ -1884,7 +1884,7 @@ function stackSet(key, value) { + } + var LARGE_ARRAY_SIZE, stackSet_default; + var init_stackSet = __esm({ +- "node_modules/lodash-es/_stackSet.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_stackSet.js"() { + init_ListCache(); + init_Map(); + init_MapCache(); +@@ -1893,14 +1893,14 @@ var init_stackSet = __esm({ + } + }); + +-// node_modules/lodash-es/_Stack.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_Stack.js + function Stack(entries) { + var data = this.__data__ = new ListCache_default(entries); + this.size = data.size; + } + var Stack_default; + var init_Stack = __esm({ +- "node_modules/lodash-es/_Stack.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_Stack.js"() { + init_ListCache(); + init_stackClear(); + init_stackDelete(); +@@ -1916,7 +1916,7 @@ var init_Stack = __esm({ + } + }); + +-// node_modules/lodash-es/_cloneBuffer.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_cloneBuffer.js + function cloneBuffer(buffer, isDeep) { + if (isDeep) { + return buffer.slice(); +@@ -1927,7 +1927,7 @@ function cloneBuffer(buffer, isDeep) { + } + var freeExports3, freeModule3, moduleExports3, Buffer3, allocUnsafe, cloneBuffer_default; + var init_cloneBuffer = __esm({ +- "node_modules/lodash-es/_cloneBuffer.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_cloneBuffer.js"() { + init_root(); + freeExports3 = typeof exports == "object" && exports && !exports.nodeType && exports; + freeModule3 = freeExports3 && typeof module == "object" && module && !module.nodeType && module; +@@ -1938,7 +1938,7 @@ var init_cloneBuffer = __esm({ + } + }); + +-// node_modules/lodash-es/_arrayFilter.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_arrayFilter.js + function arrayFilter(array, predicate) { + var index = -1, length = array == null ? 0 : array.length, resIndex = 0, result = []; + while (++index < length) { +@@ -1951,26 +1951,26 @@ function arrayFilter(array, predicate) { + } + var arrayFilter_default; + var init_arrayFilter = __esm({ +- "node_modules/lodash-es/_arrayFilter.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_arrayFilter.js"() { + arrayFilter_default = arrayFilter; + } + }); + +-// node_modules/lodash-es/stubArray.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/stubArray.js + function stubArray() { + return []; + } + var stubArray_default; + var init_stubArray = __esm({ +- "node_modules/lodash-es/stubArray.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/stubArray.js"() { + stubArray_default = stubArray; + } + }); + +-// node_modules/lodash-es/_getSymbols.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_getSymbols.js + var objectProto13, propertyIsEnumerable2, nativeGetSymbols, getSymbols, getSymbols_default; + var init_getSymbols = __esm({ +- "node_modules/lodash-es/_getSymbols.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_getSymbols.js"() { + init_arrayFilter(); + init_stubArray(); + objectProto13 = Object.prototype; +@@ -1989,27 +1989,27 @@ var init_getSymbols = __esm({ + } + }); + +-// node_modules/lodash-es/_baseGetAllKeys.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseGetAllKeys.js + function baseGetAllKeys(object, keysFunc, symbolsFunc) { + var result = keysFunc(object); + return isArray_default(object) ? result : arrayPush_default(result, symbolsFunc(object)); + } + var baseGetAllKeys_default; + var init_baseGetAllKeys = __esm({ +- "node_modules/lodash-es/_baseGetAllKeys.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseGetAllKeys.js"() { + init_arrayPush(); + init_isArray(); + baseGetAllKeys_default = baseGetAllKeys; + } + }); + +-// node_modules/lodash-es/_getAllKeys.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_getAllKeys.js + function getAllKeys(object) { + return baseGetAllKeys_default(object, keys_default, getSymbols_default); + } + var getAllKeys_default; + var init_getAllKeys = __esm({ +- "node_modules/lodash-es/_getAllKeys.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_getAllKeys.js"() { + init_baseGetAllKeys(); + init_getSymbols(); + init_keys(); +@@ -2017,10 +2017,10 @@ var init_getAllKeys = __esm({ + } + }); + +-// node_modules/lodash-es/_DataView.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_DataView.js + var DataView, DataView_default; + var init_DataView = __esm({ +- "node_modules/lodash-es/_DataView.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_DataView.js"() { + init_getNative(); + init_root(); + DataView = getNative_default(root_default, "DataView"); +@@ -2028,10 +2028,10 @@ var init_DataView = __esm({ + } + }); + +-// node_modules/lodash-es/_Promise.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_Promise.js + var Promise2, Promise_default; + var init_Promise = __esm({ +- "node_modules/lodash-es/_Promise.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_Promise.js"() { + init_getNative(); + init_root(); + Promise2 = getNative_default(root_default, "Promise"); +@@ -2039,10 +2039,10 @@ var init_Promise = __esm({ + } + }); + +-// node_modules/lodash-es/_Set.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_Set.js + var Set2, Set_default; + var init_Set = __esm({ +- "node_modules/lodash-es/_Set.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_Set.js"() { + init_getNative(); + init_root(); + Set2 = getNative_default(root_default, "Set"); +@@ -2050,10 +2050,10 @@ var init_Set = __esm({ + } + }); + +-// node_modules/lodash-es/_getTag.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_getTag.js + var mapTag2, objectTag3, promiseTag, setTag2, weakMapTag2, dataViewTag2, dataViewCtorString, mapCtorString, promiseCtorString, setCtorString, weakMapCtorString, getTag, getTag_default; + var init_getTag = __esm({ +- "node_modules/lodash-es/_getTag.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_getTag.js"() { + init_DataView(); + init_Map(); + init_Promise(); +@@ -2097,17 +2097,17 @@ var init_getTag = __esm({ + } + }); + +-// node_modules/lodash-es/_Uint8Array.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_Uint8Array.js + var Uint8Array2, Uint8Array_default; + var init_Uint8Array = __esm({ +- "node_modules/lodash-es/_Uint8Array.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_Uint8Array.js"() { + init_root(); + Uint8Array2 = root_default.Uint8Array; + Uint8Array_default = Uint8Array2; + } + }); + +-// node_modules/lodash-es/_cloneArrayBuffer.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_cloneArrayBuffer.js + function cloneArrayBuffer(arrayBuffer) { + var result = new arrayBuffer.constructor(arrayBuffer.byteLength); + new Uint8Array_default(result).set(new Uint8Array_default(arrayBuffer)); +@@ -2115,32 +2115,32 @@ function cloneArrayBuffer(arrayBuffer) { + } + var cloneArrayBuffer_default; + var init_cloneArrayBuffer = __esm({ +- "node_modules/lodash-es/_cloneArrayBuffer.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_cloneArrayBuffer.js"() { + init_Uint8Array(); + cloneArrayBuffer_default = cloneArrayBuffer; + } + }); + +-// node_modules/lodash-es/_cloneTypedArray.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_cloneTypedArray.js + function cloneTypedArray(typedArray, isDeep) { + var buffer = isDeep ? cloneArrayBuffer_default(typedArray.buffer) : typedArray.buffer; + return new typedArray.constructor(buffer, typedArray.byteOffset, typedArray.length); + } + var cloneTypedArray_default; + var init_cloneTypedArray = __esm({ +- "node_modules/lodash-es/_cloneTypedArray.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_cloneTypedArray.js"() { + init_cloneArrayBuffer(); + cloneTypedArray_default = cloneTypedArray; + } + }); + +-// node_modules/lodash-es/_initCloneObject.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_initCloneObject.js + function initCloneObject(object) { + return typeof object.constructor == "function" && !isPrototype_default(object) ? baseCreate_default(getPrototype_default(object)) : {}; + } + var initCloneObject_default; + var init_initCloneObject = __esm({ +- "node_modules/lodash-es/_initCloneObject.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_initCloneObject.js"() { + init_baseCreate(); + init_getPrototype(); + init_isPrototype(); +@@ -2148,7 +2148,7 @@ var init_initCloneObject = __esm({ + } + }); + +-// node_modules/lodash-es/compact.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/compact.js + var compact_exports = {}; + __export(compact_exports, { + default: () => compact_default +@@ -2165,36 +2165,36 @@ function compact(array) { + } + var compact_default; + var init_compact = __esm({ +- "node_modules/lodash-es/compact.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/compact.js"() { + compact_default = compact; + } + }); + +-// node_modules/lodash-es/_setCacheAdd.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_setCacheAdd.js + function setCacheAdd(value) { + this.__data__.set(value, HASH_UNDEFINED3); + return this; + } + var HASH_UNDEFINED3, setCacheAdd_default; + var init_setCacheAdd = __esm({ +- "node_modules/lodash-es/_setCacheAdd.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_setCacheAdd.js"() { + HASH_UNDEFINED3 = "__lodash_hash_undefined__"; + setCacheAdd_default = setCacheAdd; + } + }); + +-// node_modules/lodash-es/_setCacheHas.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_setCacheHas.js + function setCacheHas(value) { + return this.__data__.has(value); + } + var setCacheHas_default; + var init_setCacheHas = __esm({ +- "node_modules/lodash-es/_setCacheHas.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_setCacheHas.js"() { + setCacheHas_default = setCacheHas; + } + }); + +-// node_modules/lodash-es/_SetCache.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_SetCache.js + function SetCache(values) { + var index = -1, length = values == null ? 0 : values.length; + this.__data__ = new MapCache_default(); +@@ -2204,7 +2204,7 @@ function SetCache(values) { + } + var SetCache_default; + var init_SetCache = __esm({ +- "node_modules/lodash-es/_SetCache.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_SetCache.js"() { + init_MapCache(); + init_setCacheAdd(); + init_setCacheHas(); +@@ -2214,7 +2214,7 @@ var init_SetCache = __esm({ + } + }); + +-// node_modules/lodash-es/_arraySome.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_arraySome.js + function arraySome(array, predicate) { + var index = -1, length = array == null ? 0 : array.length; + while (++index < length) { +@@ -2226,23 +2226,23 @@ function arraySome(array, predicate) { + } + var arraySome_default; + var init_arraySome = __esm({ +- "node_modules/lodash-es/_arraySome.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_arraySome.js"() { + arraySome_default = arraySome; + } + }); + +-// node_modules/lodash-es/_cacheHas.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_cacheHas.js + function cacheHas(cache, key) { + return cache.has(key); + } + var cacheHas_default; + var init_cacheHas = __esm({ +- "node_modules/lodash-es/_cacheHas.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_cacheHas.js"() { + cacheHas_default = cacheHas; + } + }); + +-// node_modules/lodash-es/_equalArrays.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_equalArrays.js + function equalArrays(array, other, bitmask, customizer, equalFunc, stack) { + var isPartial = bitmask & COMPARE_PARTIAL_FLAG, arrLength = array.length, othLength = other.length; + if (arrLength != othLength && !(isPartial && othLength > arrLength)) { +@@ -2288,7 +2288,7 @@ function equalArrays(array, other, bitmask, customizer, equalFunc, stack) { + } + var COMPARE_PARTIAL_FLAG, COMPARE_UNORDERED_FLAG, equalArrays_default; + var init_equalArrays = __esm({ +- "node_modules/lodash-es/_equalArrays.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_equalArrays.js"() { + init_SetCache(); + init_arraySome(); + init_cacheHas(); +@@ -2298,7 +2298,7 @@ var init_equalArrays = __esm({ + } + }); + +-// node_modules/lodash-es/_mapToArray.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_mapToArray.js + function mapToArray(map) { + var index = -1, result = Array(map.size); + map.forEach(function(value, key) { +@@ -2308,12 +2308,12 @@ function mapToArray(map) { + } + var mapToArray_default; + var init_mapToArray = __esm({ +- "node_modules/lodash-es/_mapToArray.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_mapToArray.js"() { + mapToArray_default = mapToArray; + } + }); + +-// node_modules/lodash-es/_setToArray.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_setToArray.js + function setToArray(set) { + var index = -1, result = Array(set.size); + set.forEach(function(value) { +@@ -2323,12 +2323,12 @@ function setToArray(set) { + } + var setToArray_default; + var init_setToArray = __esm({ +- "node_modules/lodash-es/_setToArray.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_setToArray.js"() { + setToArray_default = setToArray; + } + }); + +-// node_modules/lodash-es/_equalByTag.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_equalByTag.js + function equalByTag(object, other, tag, bitmask, customizer, equalFunc, stack) { + switch (tag) { + case dataViewTag3: +@@ -2377,7 +2377,7 @@ function equalByTag(object, other, tag, bitmask, customizer, equalFunc, stack) { + } + var COMPARE_PARTIAL_FLAG2, COMPARE_UNORDERED_FLAG2, boolTag2, dateTag2, errorTag2, mapTag3, numberTag2, regexpTag2, setTag3, stringTag2, symbolTag2, arrayBufferTag2, dataViewTag3, symbolProto2, symbolValueOf, equalByTag_default; + var init_equalByTag = __esm({ +- "node_modules/lodash-es/_equalByTag.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_equalByTag.js"() { + init_Symbol(); + init_Uint8Array(); + init_eq(); +@@ -2403,7 +2403,7 @@ var init_equalByTag = __esm({ + } + }); + +-// node_modules/lodash-es/_equalObjects.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_equalObjects.js + function equalObjects(object, other, bitmask, customizer, equalFunc, stack) { + var isPartial = bitmask & COMPARE_PARTIAL_FLAG3, objProps = getAllKeys_default(object), objLength = objProps.length, othProps = getAllKeys_default(other), othLength = othProps.length; + if (objLength != othLength && !isPartial) { +@@ -2449,7 +2449,7 @@ function equalObjects(object, other, bitmask, customizer, equalFunc, stack) { + } + var COMPARE_PARTIAL_FLAG3, objectProto14, hasOwnProperty11, equalObjects_default; + var init_equalObjects = __esm({ +- "node_modules/lodash-es/_equalObjects.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_equalObjects.js"() { + init_getAllKeys(); + COMPARE_PARTIAL_FLAG3 = 1; + objectProto14 = Object.prototype; +@@ -2458,7 +2458,7 @@ var init_equalObjects = __esm({ + } + }); + +-// node_modules/lodash-es/_baseIsEqualDeep.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseIsEqualDeep.js + function baseIsEqualDeep(object, other, bitmask, customizer, equalFunc, stack) { + var objIsArr = isArray_default(object), othIsArr = isArray_default(other), objTag = objIsArr ? arrayTag2 : getTag_default(object), othTag = othIsArr ? arrayTag2 : getTag_default(other); + objTag = objTag == argsTag3 ? objectTag4 : objTag; +@@ -2491,7 +2491,7 @@ function baseIsEqualDeep(object, other, bitmask, customizer, equalFunc, stack) { + } + var COMPARE_PARTIAL_FLAG4, argsTag3, arrayTag2, objectTag4, objectProto15, hasOwnProperty12, baseIsEqualDeep_default; + var init_baseIsEqualDeep = __esm({ +- "node_modules/lodash-es/_baseIsEqualDeep.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseIsEqualDeep.js"() { + init_Stack(); + init_equalArrays(); + init_equalByTag(); +@@ -2510,7 +2510,7 @@ var init_baseIsEqualDeep = __esm({ + } + }); + +-// node_modules/lodash-es/_baseIsEqual.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseIsEqual.js + function baseIsEqual(value, other, bitmask, customizer, stack) { + if (value === other) { + return true; +@@ -2522,14 +2522,14 @@ function baseIsEqual(value, other, bitmask, customizer, stack) { + } + var baseIsEqual_default; + var init_baseIsEqual = __esm({ +- "node_modules/lodash-es/_baseIsEqual.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseIsEqual.js"() { + init_baseIsEqualDeep(); + init_isObjectLike(); + baseIsEqual_default = baseIsEqual; + } + }); + +-// node_modules/lodash-es/_baseIsMatch.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseIsMatch.js + function baseIsMatch(object, source, matchData, customizer) { + var index = matchData.length, length = index, noCustomizer = !customizer; + if (object == null) { +@@ -2563,7 +2563,7 @@ function baseIsMatch(object, source, matchData, customizer) { + } + var COMPARE_PARTIAL_FLAG5, COMPARE_UNORDERED_FLAG3, baseIsMatch_default; + var init_baseIsMatch = __esm({ +- "node_modules/lodash-es/_baseIsMatch.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseIsMatch.js"() { + init_Stack(); + init_baseIsEqual(); + COMPARE_PARTIAL_FLAG5 = 1; +@@ -2572,19 +2572,19 @@ var init_baseIsMatch = __esm({ + } + }); + +-// node_modules/lodash-es/_isStrictComparable.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_isStrictComparable.js + function isStrictComparable(value) { + return value === value && !isObject_default(value); + } + var isStrictComparable_default; + var init_isStrictComparable = __esm({ +- "node_modules/lodash-es/_isStrictComparable.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_isStrictComparable.js"() { + init_isObject(); + isStrictComparable_default = isStrictComparable; + } + }); + +-// node_modules/lodash-es/_getMatchData.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_getMatchData.js + function getMatchData(object) { + var result = keys_default(object), length = result.length; + while (length--) { +@@ -2595,14 +2595,14 @@ function getMatchData(object) { + } + var getMatchData_default; + var init_getMatchData = __esm({ +- "node_modules/lodash-es/_getMatchData.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_getMatchData.js"() { + init_isStrictComparable(); + init_keys(); + getMatchData_default = getMatchData; + } + }); + +-// node_modules/lodash-es/_matchesStrictComparable.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_matchesStrictComparable.js + function matchesStrictComparable(key, srcValue) { + return function(object) { + if (object == null) { +@@ -2613,12 +2613,12 @@ function matchesStrictComparable(key, srcValue) { + } + var matchesStrictComparable_default; + var init_matchesStrictComparable = __esm({ +- "node_modules/lodash-es/_matchesStrictComparable.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_matchesStrictComparable.js"() { + matchesStrictComparable_default = matchesStrictComparable; + } + }); + +-// node_modules/lodash-es/_baseMatches.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseMatches.js + function baseMatches(source) { + var matchData = getMatchData_default(source); + if (matchData.length == 1 && matchData[0][2]) { +@@ -2630,7 +2630,7 @@ function baseMatches(source) { + } + var baseMatches_default; + var init_baseMatches = __esm({ +- "node_modules/lodash-es/_baseMatches.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseMatches.js"() { + init_baseIsMatch(); + init_getMatchData(); + init_matchesStrictComparable(); +@@ -2638,18 +2638,18 @@ var init_baseMatches = __esm({ + } + }); + +-// node_modules/lodash-es/_baseHasIn.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseHasIn.js + function baseHasIn(object, key) { + return object != null && key in Object(object); + } + var baseHasIn_default; + var init_baseHasIn = __esm({ +- "node_modules/lodash-es/_baseHasIn.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseHasIn.js"() { + baseHasIn_default = baseHasIn; + } + }); + +-// node_modules/lodash-es/_hasPath.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_hasPath.js + function hasPath(object, path, hasFunc) { + path = castPath_default(path, object); + var index = -1, length = path.length, result = false; +@@ -2668,7 +2668,7 @@ function hasPath(object, path, hasFunc) { + } + var hasPath_default; + var init_hasPath = __esm({ +- "node_modules/lodash-es/_hasPath.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_hasPath.js"() { + init_castPath(); + init_isArguments(); + init_isArray(); +@@ -2679,20 +2679,20 @@ var init_hasPath = __esm({ + } + }); + +-// node_modules/lodash-es/hasIn.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/hasIn.js + function hasIn(object, path) { + return object != null && hasPath_default(object, path, baseHasIn_default); + } + var hasIn_default; + var init_hasIn = __esm({ +- "node_modules/lodash-es/hasIn.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/hasIn.js"() { + init_baseHasIn(); + init_hasPath(); + hasIn_default = hasIn; + } + }); + +-// node_modules/lodash-es/_baseMatchesProperty.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseMatchesProperty.js + function baseMatchesProperty(path, srcValue) { + if (isKey_default(path) && isStrictComparable_default(srcValue)) { + return matchesStrictComparable_default(toKey_default(path), srcValue); +@@ -2704,7 +2704,7 @@ function baseMatchesProperty(path, srcValue) { + } + var COMPARE_PARTIAL_FLAG6, COMPARE_UNORDERED_FLAG4, baseMatchesProperty_default; + var init_baseMatchesProperty = __esm({ +- "node_modules/lodash-es/_baseMatchesProperty.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseMatchesProperty.js"() { + init_baseIsEqual(); + init_get(); + init_hasIn(); +@@ -2718,7 +2718,7 @@ var init_baseMatchesProperty = __esm({ + } + }); + +-// node_modules/lodash-es/_baseProperty.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseProperty.js + function baseProperty(key) { + return function(object) { + return object == null ? void 0 : object[key]; +@@ -2726,12 +2726,12 @@ function baseProperty(key) { + } + var baseProperty_default; + var init_baseProperty = __esm({ +- "node_modules/lodash-es/_baseProperty.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseProperty.js"() { + baseProperty_default = baseProperty; + } + }); + +-// node_modules/lodash-es/_basePropertyDeep.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_basePropertyDeep.js + function basePropertyDeep(path) { + return function(object) { + return baseGet_default(object, path); +@@ -2739,19 +2739,19 @@ function basePropertyDeep(path) { + } + var basePropertyDeep_default; + var init_basePropertyDeep = __esm({ +- "node_modules/lodash-es/_basePropertyDeep.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_basePropertyDeep.js"() { + init_baseGet(); + basePropertyDeep_default = basePropertyDeep; + } + }); + +-// node_modules/lodash-es/property.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/property.js + function property(path) { + return isKey_default(path) ? baseProperty_default(toKey_default(path)) : basePropertyDeep_default(path); + } + var property_default; + var init_property = __esm({ +- "node_modules/lodash-es/property.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/property.js"() { + init_baseProperty(); + init_basePropertyDeep(); + init_isKey(); +@@ -2760,7 +2760,7 @@ var init_property = __esm({ + } + }); + +-// node_modules/lodash-es/_baseIteratee.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseIteratee.js + function baseIteratee(value) { + if (typeof value == "function") { + return value; +@@ -2775,7 +2775,7 @@ function baseIteratee(value) { + } + var baseIteratee_default; + var init_baseIteratee = __esm({ +- "node_modules/lodash-es/_baseIteratee.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseIteratee.js"() { + init_baseMatches(); + init_baseMatchesProperty(); + init_identity(); +@@ -2785,7 +2785,7 @@ var init_baseIteratee = __esm({ + } + }); + +-// node_modules/lodash-es/_createBaseFor.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_createBaseFor.js + function createBaseFor(fromRight) { + return function(object, iteratee, keysFunc) { + var index = -1, iterable = Object(object), props = keysFunc(object), length = props.length; +@@ -2800,35 +2800,35 @@ function createBaseFor(fromRight) { + } + var createBaseFor_default; + var init_createBaseFor = __esm({ +- "node_modules/lodash-es/_createBaseFor.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_createBaseFor.js"() { + createBaseFor_default = createBaseFor; + } + }); + +-// node_modules/lodash-es/_baseFor.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseFor.js + var baseFor, baseFor_default; + var init_baseFor = __esm({ +- "node_modules/lodash-es/_baseFor.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseFor.js"() { + init_createBaseFor(); + baseFor = createBaseFor_default(); + baseFor_default = baseFor; + } + }); + +-// node_modules/lodash-es/_baseForOwn.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseForOwn.js + function baseForOwn(object, iteratee) { + return object && baseFor_default(object, iteratee, keys_default); + } + var baseForOwn_default; + var init_baseForOwn = __esm({ +- "node_modules/lodash-es/_baseForOwn.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseForOwn.js"() { + init_baseFor(); + init_keys(); + baseForOwn_default = baseForOwn; + } + }); + +-// node_modules/lodash-es/_createBaseEach.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_createBaseEach.js + function createBaseEach(eachFunc, fromRight) { + return function(collection, iteratee) { + if (collection == null) { +@@ -2848,16 +2848,16 @@ function createBaseEach(eachFunc, fromRight) { + } + var createBaseEach_default; + var init_createBaseEach = __esm({ +- "node_modules/lodash-es/_createBaseEach.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_createBaseEach.js"() { + init_isArrayLike(); + createBaseEach_default = createBaseEach; + } + }); + +-// node_modules/lodash-es/_baseEach.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseEach.js + var baseEach, baseEach_default; + var init_baseEach = __esm({ +- "node_modules/lodash-es/_baseEach.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseEach.js"() { + init_baseForOwn(); + init_createBaseEach(); + baseEach = createBaseEach_default(baseForOwn_default); +@@ -2865,14 +2865,14 @@ var init_baseEach = __esm({ + } + }); + +-// node_modules/lodash-es/defaults.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/defaults.js + var defaults_exports = {}; + __export(defaults_exports, { + default: () => defaults_default + }); + var objectProto16, hasOwnProperty13, defaults, defaults_default; + var init_defaults = __esm({ +- "node_modules/lodash-es/defaults.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/defaults.js"() { + init_baseRest(); + init_eq(); + init_isIterateeCall(); +@@ -2906,7 +2906,7 @@ var init_defaults = __esm({ + } + }); + +-// node_modules/lodash-es/_assignMergeValue.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_assignMergeValue.js + function assignMergeValue(object, key, value) { + if (value !== void 0 && !eq_default(object[key], value) || value === void 0 && !(key in object)) { + baseAssignValue_default(object, key, value); +@@ -2914,27 +2914,27 @@ function assignMergeValue(object, key, value) { + } + var assignMergeValue_default; + var init_assignMergeValue = __esm({ +- "node_modules/lodash-es/_assignMergeValue.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_assignMergeValue.js"() { + init_baseAssignValue(); + init_eq(); + assignMergeValue_default = assignMergeValue; + } + }); + +-// node_modules/lodash-es/isArrayLikeObject.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/isArrayLikeObject.js + function isArrayLikeObject(value) { + return isObjectLike_default(value) && isArrayLike_default(value); + } + var isArrayLikeObject_default; + var init_isArrayLikeObject = __esm({ +- "node_modules/lodash-es/isArrayLikeObject.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/isArrayLikeObject.js"() { + init_isArrayLike(); + init_isObjectLike(); + isArrayLikeObject_default = isArrayLikeObject; + } + }); + +-// node_modules/lodash-es/_safeGet.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_safeGet.js + function safeGet(object, key) { + if (key === "constructor" && typeof object[key] === "function") { + return; +@@ -2946,25 +2946,25 @@ function safeGet(object, key) { + } + var safeGet_default; + var init_safeGet = __esm({ +- "node_modules/lodash-es/_safeGet.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_safeGet.js"() { + safeGet_default = safeGet; + } + }); + +-// node_modules/lodash-es/toPlainObject.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/toPlainObject.js + function toPlainObject(value) { + return copyObject_default(value, keysIn_default(value)); + } + var toPlainObject_default; + var init_toPlainObject = __esm({ +- "node_modules/lodash-es/toPlainObject.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/toPlainObject.js"() { + init_copyObject(); + init_keysIn(); + toPlainObject_default = toPlainObject; + } + }); + +-// node_modules/lodash-es/_baseMergeDeep.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseMergeDeep.js + function baseMergeDeep(object, source, key, srcIndex, mergeFunc, customizer, stack) { + var objValue = safeGet_default(object, key), srcValue = safeGet_default(source, key), stacked = stack.get(srcValue); + if (stacked) { +@@ -3010,7 +3010,7 @@ function baseMergeDeep(object, source, key, srcIndex, mergeFunc, customizer, sta + } + var baseMergeDeep_default; + var init_baseMergeDeep = __esm({ +- "node_modules/lodash-es/_baseMergeDeep.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseMergeDeep.js"() { + init_assignMergeValue(); + init_cloneBuffer(); + init_cloneTypedArray(); +@@ -3030,7 +3030,7 @@ var init_baseMergeDeep = __esm({ + } + }); + +-// node_modules/lodash-es/_baseMerge.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseMerge.js + function baseMerge(object, source, srcIndex, customizer, stack) { + if (object === source) { + return; +@@ -3050,7 +3050,7 @@ function baseMerge(object, source, srcIndex, customizer, stack) { + } + var baseMerge_default; + var init_baseMerge = __esm({ +- "node_modules/lodash-es/_baseMerge.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseMerge.js"() { + init_Stack(); + init_assignMergeValue(); + init_baseFor(); +@@ -3062,7 +3062,7 @@ var init_baseMerge = __esm({ + } + }); + +-// node_modules/lodash-es/_customDefaultsMerge.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_customDefaultsMerge.js + function customDefaultsMerge(objValue, srcValue, key, object, source, stack) { + if (isObject_default(objValue) && isObject_default(srcValue)) { + stack.set(srcValue, objValue); +@@ -3073,17 +3073,17 @@ function customDefaultsMerge(objValue, srcValue, key, object, source, stack) { + } + var customDefaultsMerge_default; + var init_customDefaultsMerge = __esm({ +- "node_modules/lodash-es/_customDefaultsMerge.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_customDefaultsMerge.js"() { + init_baseMerge(); + init_isObject(); + customDefaultsMerge_default = customDefaultsMerge; + } + }); + +-// node_modules/lodash-es/mergeWith.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/mergeWith.js + var mergeWith, mergeWith_default; + var init_mergeWith = __esm({ +- "node_modules/lodash-es/mergeWith.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/mergeWith.js"() { + init_baseMerge(); + init_createAssigner(); + mergeWith = createAssigner_default(function(object, source, srcIndex, customizer) { +@@ -3093,14 +3093,14 @@ var init_mergeWith = __esm({ + } + }); + +-// node_modules/lodash-es/defaultsDeep.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/defaultsDeep.js + var defaultsDeep_exports = {}; + __export(defaultsDeep_exports, { + default: () => defaultsDeep_default + }); + var defaultsDeep, defaultsDeep_default; + var init_defaultsDeep = __esm({ +- "node_modules/lodash-es/defaultsDeep.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/defaultsDeep.js"() { + init_apply(); + init_baseRest(); + init_customDefaultsMerge(); +@@ -3113,7 +3113,7 @@ var init_defaultsDeep = __esm({ + } + }); + +-// node_modules/lodash-es/_arrayIncludesWith.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_arrayIncludesWith.js + function arrayIncludesWith(array, value, comparator) { + var index = -1, length = array == null ? 0 : array.length; + while (++index < length) { +@@ -3125,12 +3125,12 @@ function arrayIncludesWith(array, value, comparator) { + } + var arrayIncludesWith_default; + var init_arrayIncludesWith = __esm({ +- "node_modules/lodash-es/_arrayIncludesWith.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_arrayIncludesWith.js"() { + arrayIncludesWith_default = arrayIncludesWith; + } + }); + +-// node_modules/lodash-es/_baseDifference.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseDifference.js + function baseDifference(array, values, iteratee, comparator) { + var index = -1, includes = arrayIncludes_default, isCommon = true, length = array.length, result = [], valuesLength = values.length; + if (!length) { +@@ -3167,7 +3167,7 @@ function baseDifference(array, values, iteratee, comparator) { + } + var LARGE_ARRAY_SIZE2, baseDifference_default; + var init_baseDifference = __esm({ +- "node_modules/lodash-es/_baseDifference.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseDifference.js"() { + init_SetCache(); + init_arrayIncludes(); + init_arrayIncludesWith(); +@@ -3179,31 +3179,31 @@ var init_baseDifference = __esm({ + } + }); + +-// node_modules/lodash-es/last.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/last.js + function last(array) { + var length = array == null ? 0 : array.length; + return length ? array[length - 1] : void 0; + } + var last_default; + var init_last = __esm({ +- "node_modules/lodash-es/last.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/last.js"() { + last_default = last; + } + }); + +-// node_modules/lodash-es/_castFunction.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_castFunction.js + function castFunction(value) { + return typeof value == "function" ? value : identity_default; + } + var castFunction_default; + var init_castFunction = __esm({ +- "node_modules/lodash-es/_castFunction.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_castFunction.js"() { + init_identity(); + castFunction_default = castFunction; + } + }); + +-// node_modules/lodash-es/forEach.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/forEach.js + var forEach_exports = {}; + __export(forEach_exports, { + default: () => forEach_default +@@ -3214,7 +3214,7 @@ function forEach(collection, iteratee) { + } + var forEach_default; + var init_forEach = __esm({ +- "node_modules/lodash-es/forEach.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/forEach.js"() { + init_arrayEach(); + init_baseEach(); + init_castFunction(); +@@ -3223,7 +3223,7 @@ var init_forEach = __esm({ + } + }); + +-// node_modules/lodash-es/_baseMap.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseMap.js + function baseMap(collection, iteratee) { + var index = -1, result = isArrayLike_default(collection) ? Array(collection.length) : []; + baseEach_default(collection, function(value, key, collection2) { +@@ -3233,14 +3233,14 @@ function baseMap(collection, iteratee) { + } + var baseMap_default; + var init_baseMap = __esm({ +- "node_modules/lodash-es/_baseMap.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseMap.js"() { + init_baseEach(); + init_isArrayLike(); + baseMap_default = baseMap; + } + }); + +-// node_modules/lodash-es/flattenDeep.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/flattenDeep.js + var flattenDeep_exports = {}; + __export(flattenDeep_exports, { + default: () => flattenDeep_default +@@ -3251,14 +3251,14 @@ function flattenDeep(array) { + } + var INFINITY3, flattenDeep_default; + var init_flattenDeep = __esm({ +- "node_modules/lodash-es/flattenDeep.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/flattenDeep.js"() { + init_baseFlatten(); + INFINITY3 = 1 / 0; + flattenDeep_default = flattenDeep; + } + }); + +-// node_modules/lodash-es/_baseIntersection.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseIntersection.js + function baseIntersection(arrays, iteratee, comparator) { + var includes = comparator ? arrayIncludesWith_default : arrayIncludes_default, length = arrays[0].length, othLength = arrays.length, othIndex = othLength, caches = Array(othLength), maxLength = Infinity, result = []; + while (othIndex--) { +@@ -3293,7 +3293,7 @@ function baseIntersection(arrays, iteratee, comparator) { + } + var nativeMin, baseIntersection_default; + var init_baseIntersection = __esm({ +- "node_modules/lodash-es/_baseIntersection.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseIntersection.js"() { + init_SetCache(); + init_arrayIncludes(); + init_arrayIncludesWith(); +@@ -3305,26 +3305,26 @@ var init_baseIntersection = __esm({ + } + }); + +-// node_modules/lodash-es/_castArrayLikeObject.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_castArrayLikeObject.js + function castArrayLikeObject(value) { + return isArrayLikeObject_default(value) ? value : []; + } + var castArrayLikeObject_default; + var init_castArrayLikeObject = __esm({ +- "node_modules/lodash-es/_castArrayLikeObject.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_castArrayLikeObject.js"() { + init_isArrayLikeObject(); + castArrayLikeObject_default = castArrayLikeObject; + } + }); + +-// node_modules/lodash-es/intersection.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/intersection.js + var intersection_exports = {}; + __export(intersection_exports, { + default: () => intersection_default + }); + var intersection, intersection_default; + var init_intersection = __esm({ +- "node_modules/lodash-es/intersection.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/intersection.js"() { + init_arrayMap(); + init_baseIntersection(); + init_baseRest(); +@@ -3337,14 +3337,14 @@ var init_intersection = __esm({ + } + }); + +-// node_modules/lodash-es/intersectionWith.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/intersectionWith.js + var intersectionWith_exports = {}; + __export(intersectionWith_exports, { + default: () => intersectionWith_default + }); + var intersectionWith, intersectionWith_default; + var init_intersectionWith = __esm({ +- "node_modules/lodash-es/intersectionWith.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/intersectionWith.js"() { + init_arrayMap(); + init_baseIntersection(); + init_baseRest(); +@@ -3362,7 +3362,7 @@ var init_intersectionWith = __esm({ + } + }); + +-// node_modules/lodash-es/isBoolean.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/isBoolean.js + var isBoolean_exports = {}; + __export(isBoolean_exports, { + default: () => isBoolean_default +@@ -3372,7 +3372,7 @@ function isBoolean(value) { + } + var boolTag3, isBoolean_default; + var init_isBoolean = __esm({ +- "node_modules/lodash-es/isBoolean.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/isBoolean.js"() { + init_baseGetTag(); + init_isObjectLike(); + boolTag3 = "[object Boolean]"; +@@ -3380,7 +3380,7 @@ var init_isBoolean = __esm({ + } + }); + +-// node_modules/lodash-es/isEqual.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/isEqual.js + var isEqual_exports = {}; + __export(isEqual_exports, { + default: () => isEqual_default +@@ -3390,13 +3390,13 @@ function isEqual(value, other) { + } + var isEqual_default; + var init_isEqual = __esm({ +- "node_modules/lodash-es/isEqual.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/isEqual.js"() { + init_baseIsEqual(); + isEqual_default = isEqual; + } + }); + +-// node_modules/lodash-es/_baseSet.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseSet.js + function baseSet(object, path, value, customizer) { + if (!isObject_default(object)) { + return object; +@@ -3422,7 +3422,7 @@ function baseSet(object, path, value, customizer) { + } + var baseSet_default; + var init_baseSet = __esm({ +- "node_modules/lodash-es/_baseSet.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseSet.js"() { + init_assignValue(); + init_castPath(); + init_isIndex(); +@@ -3432,7 +3432,7 @@ var init_baseSet = __esm({ + } + }); + +-// node_modules/lodash-es/_basePickBy.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_basePickBy.js + function basePickBy(object, paths, predicate) { + var index = -1, length = paths.length, result = {}; + while (++index < length) { +@@ -3445,7 +3445,7 @@ function basePickBy(object, paths, predicate) { + } + var basePickBy_default; + var init_basePickBy = __esm({ +- "node_modules/lodash-es/_basePickBy.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_basePickBy.js"() { + init_baseGet(); + init_baseSet(); + init_castPath(); +@@ -3453,7 +3453,7 @@ var init_basePickBy = __esm({ + } + }); + +-// node_modules/lodash-es/_baseSortBy.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseSortBy.js + function baseSortBy(array, comparer) { + var length = array.length; + array.sort(comparer); +@@ -3464,12 +3464,12 @@ function baseSortBy(array, comparer) { + } + var baseSortBy_default; + var init_baseSortBy = __esm({ +- "node_modules/lodash-es/_baseSortBy.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseSortBy.js"() { + baseSortBy_default = baseSortBy; + } + }); + +-// node_modules/lodash-es/_compareAscending.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_compareAscending.js + function compareAscending(value, other) { + if (value !== other) { + var valIsDefined = value !== void 0, valIsNull = value === null, valIsReflexive = value === value, valIsSymbol = isSymbol_default(value); +@@ -3485,13 +3485,13 @@ function compareAscending(value, other) { + } + var compareAscending_default; + var init_compareAscending = __esm({ +- "node_modules/lodash-es/_compareAscending.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_compareAscending.js"() { + init_isSymbol(); + compareAscending_default = compareAscending; + } + }); + +-// node_modules/lodash-es/_compareMultiple.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_compareMultiple.js + function compareMultiple(object, other, orders) { + var index = -1, objCriteria = object.criteria, othCriteria = other.criteria, length = objCriteria.length, ordersLength = orders.length; + while (++index < length) { +@@ -3508,13 +3508,13 @@ function compareMultiple(object, other, orders) { + } + var compareMultiple_default; + var init_compareMultiple = __esm({ +- "node_modules/lodash-es/_compareMultiple.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_compareMultiple.js"() { + init_compareAscending(); + compareMultiple_default = compareMultiple; + } + }); + +-// node_modules/lodash-es/_baseOrderBy.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseOrderBy.js + function baseOrderBy(collection, iteratees, orders) { + if (iteratees.length) { + iteratees = arrayMap_default(iteratees, function(iteratee) { +@@ -3542,7 +3542,7 @@ function baseOrderBy(collection, iteratees, orders) { + } + var baseOrderBy_default; + var init_baseOrderBy = __esm({ +- "node_modules/lodash-es/_baseOrderBy.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseOrderBy.js"() { + init_arrayMap(); + init_baseGet(); + init_baseIteratee(); +@@ -3556,7 +3556,7 @@ var init_baseOrderBy = __esm({ + } + }); + +-// node_modules/lodash-es/_basePick.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_basePick.js + function basePick(object, paths) { + return basePickBy_default(object, paths, function(value, path) { + return hasIn_default(object, path); +@@ -3564,21 +3564,21 @@ function basePick(object, paths) { + } + var basePick_default; + var init_basePick = __esm({ +- "node_modules/lodash-es/_basePick.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_basePick.js"() { + init_basePickBy(); + init_hasIn(); + basePick_default = basePick; + } + }); + +-// node_modules/lodash-es/pick.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/pick.js + var pick_exports = {}; + __export(pick_exports, { + default: () => pick_default + }); + var pick, pick_default; + var init_pick = __esm({ +- "node_modules/lodash-es/pick.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/pick.js"() { + init_basePick(); + init_flatRest(); + pick = flatRest_default(function(object, paths) { +@@ -3588,7 +3588,7 @@ var init_pick = __esm({ + } + }); + +-// node_modules/lodash-es/_baseIndexOfWith.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseIndexOfWith.js + function baseIndexOfWith(array, value, fromIndex, comparator) { + var index = fromIndex - 1, length = array.length; + while (++index < length) { +@@ -3600,12 +3600,12 @@ function baseIndexOfWith(array, value, fromIndex, comparator) { + } + var baseIndexOfWith_default; + var init_baseIndexOfWith = __esm({ +- "node_modules/lodash-es/_baseIndexOfWith.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseIndexOfWith.js"() { + baseIndexOfWith_default = baseIndexOfWith; + } + }); + +-// node_modules/lodash-es/_basePullAll.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_basePullAll.js + function basePullAll(array, values, iteratee, comparator) { + var indexOf = comparator ? baseIndexOfWith_default : baseIndexOf_default, index = -1, length = values.length, seen = array; + if (array === values) { +@@ -3627,7 +3627,7 @@ function basePullAll(array, values, iteratee, comparator) { + } + var arrayProto2, splice2, basePullAll_default; + var init_basePullAll = __esm({ +- "node_modules/lodash-es/_basePullAll.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_basePullAll.js"() { + init_arrayMap(); + init_baseIndexOf(); + init_baseIndexOfWith(); +@@ -3639,7 +3639,7 @@ var init_basePullAll = __esm({ + } + }); + +-// node_modules/lodash-es/pullAll.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/pullAll.js + var pullAll_exports = {}; + __export(pullAll_exports, { + default: () => pullAll_default +@@ -3649,20 +3649,20 @@ function pullAll(array, values) { + } + var pullAll_default; + var init_pullAll = __esm({ +- "node_modules/lodash-es/pullAll.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/pullAll.js"() { + init_basePullAll(); + pullAll_default = pullAll; + } + }); + +-// node_modules/lodash-es/sortBy.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/sortBy.js + var sortBy_exports = {}; + __export(sortBy_exports, { + default: () => sortBy_default + }); + var sortBy, sortBy_default; + var init_sortBy = __esm({ +- "node_modules/lodash-es/sortBy.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/sortBy.js"() { + init_baseFlatten(); + init_baseOrderBy(); + init_baseRest(); +@@ -3683,10 +3683,10 @@ var init_sortBy = __esm({ + } + }); + +-// node_modules/lodash-es/_createSet.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_createSet.js + var INFINITY4, createSet, createSet_default; + var init_createSet = __esm({ +- "node_modules/lodash-es/_createSet.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_createSet.js"() { + init_Set(); + init_noop(); + init_setToArray(); +@@ -3698,7 +3698,7 @@ var init_createSet = __esm({ + } + }); + +-// node_modules/lodash-es/_baseUniq.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseUniq.js + function baseUniq(array, iteratee, comparator) { + var index = -1, includes = arrayIncludes_default, length = array.length, isCommon = true, result = [], seen = result; + if (comparator) { +@@ -3741,7 +3741,7 @@ function baseUniq(array, iteratee, comparator) { + } + var LARGE_ARRAY_SIZE3, baseUniq_default; + var init_baseUniq = __esm({ +- "node_modules/lodash-es/_baseUniq.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseUniq.js"() { + init_SetCache(); + init_arrayIncludes(); + init_arrayIncludesWith(); +@@ -3753,7 +3753,7 @@ var init_baseUniq = __esm({ + } + }); + +-// node_modules/lodash-es/uniq.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/uniq.js + var uniq_exports = {}; + __export(uniq_exports, { + default: () => uniq_default +@@ -3763,13 +3763,13 @@ function uniq(array) { + } + var uniq_default; + var init_uniq = __esm({ +- "node_modules/lodash-es/uniq.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/uniq.js"() { + init_baseUniq(); + uniq_default = uniq; + } + }); + +-// node_modules/lodash-es/uniqWith.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/uniqWith.js + var uniqWith_exports = {}; + __export(uniqWith_exports, { + default: () => uniqWith_default +@@ -3780,20 +3780,20 @@ function uniqWith(array, comparator) { + } + var uniqWith_default; + var init_uniqWith = __esm({ +- "node_modules/lodash-es/uniqWith.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/uniqWith.js"() { + init_baseUniq(); + uniqWith_default = uniqWith; + } + }); + +-// node_modules/lodash-es/without.js ++// node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/without.js + var without_exports = {}; + __export(without_exports, { + default: () => without_default + }); + var without, without_default; + var init_without = __esm({ +- "node_modules/lodash-es/without.js"() { ++ "node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/without.js"() { + init_baseDifference(); + init_baseRest(); + init_isArrayLikeObject(); +@@ -3804,9 +3804,9 @@ var init_without = __esm({ + } + }); + +-// node_modules/safe-stable-stringify/stable.js ++// node_modules/.pnpm/safe-stable-stringify@1.1.1/node_modules/safe-stable-stringify/stable.js + var require_stable = __commonJS({ +- "node_modules/safe-stable-stringify/stable.js"(exports2, module2) { ++ "node_modules/.pnpm/safe-stable-stringify@1.1.1/node_modules/safe-stable-stringify/stable.js"(exports2, module2) { + module2.exports = stringify; + var indentation = ""; + var strEscapeSequencesRegExp = /[\x00-\x1f\x22\x5c]/; +@@ -4418,16 +4418,16 @@ ${originalIndentation}`; + } + }); + +-// node_modules/safe-stable-stringify/index.js ++// node_modules/.pnpm/safe-stable-stringify@1.1.1/node_modules/safe-stable-stringify/index.js + var require_safe_stable_stringify = __commonJS({ +- "node_modules/safe-stable-stringify/index.js"(exports2, module2) { ++ "node_modules/.pnpm/safe-stable-stringify@1.1.1/node_modules/safe-stable-stringify/index.js"(exports2, module2) { + var stringify = require_stable(); + module2.exports = stringify; + stringify.default = stringify; + } + }); + +-// node_modules/tslib/tslib.es6.mjs ++// node_modules/.pnpm/tslib@2.8.1/node_modules/tslib/tslib.es6.mjs + var tslib_es6_exports = {}; + __export(tslib_es6_exports, { + __addDisposableResource: () => __addDisposableResource, +@@ -4866,7 +4866,7 @@ function __rewriteRelativeImportExtension(path, preserveJsx) { + } + var extendStatics, __assign, __createBinding, __setModuleDefault, ownKeys, _SuppressedError, tslib_es6_default; + var init_tslib_es6 = __esm({ +- "node_modules/tslib/tslib.es6.mjs"() { ++ "node_modules/.pnpm/tslib@2.8.1/node_modules/tslib/tslib.es6.mjs"() { + extendStatics = function(d, b2) { + extendStatics = Object.setPrototypeOf || { __proto__: [] } instanceof Array && function(d2, b3) { + d2.__proto__ = b3; +@@ -4952,9 +4952,9 @@ var init_tslib_es6 = __esm({ + } + }); + +-// node_modules/@stoplight/lifecycle/activatable/activatable.js ++// node_modules/.pnpm/@stoplight+lifecycle@2.3.3/node_modules/@stoplight/lifecycle/activatable/activatable.js + var require_activatable = __commonJS({ +- "node_modules/@stoplight/lifecycle/activatable/activatable.js"(exports2) { ++ "node_modules/.pnpm/@stoplight+lifecycle@2.3.3/node_modules/@stoplight/lifecycle/activatable/activatable.js"(exports2) { + Object.defineProperty(exports2, "__esModule", { value: true }); + var tslib_1 = (init_tslib_es6(), __toCommonJS(tslib_es6_exports)); + var Activatable = class { +@@ -5046,18 +5046,18 @@ var require_activatable = __commonJS({ + } + }); + +-// node_modules/@stoplight/lifecycle/activatable/index.js ++// node_modules/.pnpm/@stoplight+lifecycle@2.3.3/node_modules/@stoplight/lifecycle/activatable/index.js + var require_activatable2 = __commonJS({ +- "node_modules/@stoplight/lifecycle/activatable/index.js"(exports2) { ++ "node_modules/.pnpm/@stoplight+lifecycle@2.3.3/node_modules/@stoplight/lifecycle/activatable/index.js"(exports2) { + Object.defineProperty(exports2, "__esModule", { value: true }); + var tslib_1 = (init_tslib_es6(), __toCommonJS(tslib_es6_exports)); + tslib_1.__exportStar(require_activatable(), exports2); + } + }); + +-// node_modules/@stoplight/lifecycle/disposable/AsyncDisposer.js ++// node_modules/.pnpm/@stoplight+lifecycle@2.3.3/node_modules/@stoplight/lifecycle/disposable/AsyncDisposer.js + var require_AsyncDisposer = __commonJS({ +- "node_modules/@stoplight/lifecycle/disposable/AsyncDisposer.js"(exports2) { ++ "node_modules/.pnpm/@stoplight+lifecycle@2.3.3/node_modules/@stoplight/lifecycle/disposable/AsyncDisposer.js"(exports2) { + Object.defineProperty(exports2, "__esModule", { value: true }); + var AsyncDisposer = class { + constructor(dispose) { +@@ -5068,9 +5068,9 @@ var require_AsyncDisposer = __commonJS({ + } + }); + +-// node_modules/@stoplight/lifecycle/disposable/AsyncDisposableSet.js ++// node_modules/.pnpm/@stoplight+lifecycle@2.3.3/node_modules/@stoplight/lifecycle/disposable/AsyncDisposableSet.js + var require_AsyncDisposableSet = __commonJS({ +- "node_modules/@stoplight/lifecycle/disposable/AsyncDisposableSet.js"(exports2) { ++ "node_modules/.pnpm/@stoplight+lifecycle@2.3.3/node_modules/@stoplight/lifecycle/disposable/AsyncDisposableSet.js"(exports2) { + Object.defineProperty(exports2, "__esModule", { value: true }); + var tslib_1 = (init_tslib_es6(), __toCommonJS(tslib_es6_exports)); + var AsyncDisposableSet = class { +@@ -5104,9 +5104,9 @@ var require_AsyncDisposableSet = __commonJS({ + } + }); + +-// node_modules/@stoplight/lifecycle/disposable/Disposer.js ++// node_modules/.pnpm/@stoplight+lifecycle@2.3.3/node_modules/@stoplight/lifecycle/disposable/Disposer.js + var require_Disposer = __commonJS({ +- "node_modules/@stoplight/lifecycle/disposable/Disposer.js"(exports2) { ++ "node_modules/.pnpm/@stoplight+lifecycle@2.3.3/node_modules/@stoplight/lifecycle/disposable/Disposer.js"(exports2) { + Object.defineProperty(exports2, "__esModule", { value: true }); + var Disposer = class { + constructor(dispose) { +@@ -5117,9 +5117,9 @@ var require_Disposer = __commonJS({ + } + }); + +-// node_modules/@stoplight/lifecycle/disposable/DisposableSet.js ++// node_modules/.pnpm/@stoplight+lifecycle@2.3.3/node_modules/@stoplight/lifecycle/disposable/DisposableSet.js + var require_DisposableSet = __commonJS({ +- "node_modules/@stoplight/lifecycle/disposable/DisposableSet.js"(exports2) { ++ "node_modules/.pnpm/@stoplight+lifecycle@2.3.3/node_modules/@stoplight/lifecycle/disposable/DisposableSet.js"(exports2) { + Object.defineProperty(exports2, "__esModule", { value: true }); + var DisposableSet = class { + constructor() { +@@ -5150,9 +5150,9 @@ var require_DisposableSet = __commonJS({ + } + }); + +-// node_modules/@stoplight/lifecycle/disposable/createDisposable.js ++// node_modules/.pnpm/@stoplight+lifecycle@2.3.3/node_modules/@stoplight/lifecycle/disposable/createDisposable.js + var require_createDisposable = __commonJS({ +- "node_modules/@stoplight/lifecycle/disposable/createDisposable.js"(exports2) { ++ "node_modules/.pnpm/@stoplight+lifecycle@2.3.3/node_modules/@stoplight/lifecycle/disposable/createDisposable.js"(exports2) { + Object.defineProperty(exports2, "__esModule", { value: true }); + function createDisposable(func) { + return { +@@ -5163,9 +5163,9 @@ var require_createDisposable = __commonJS({ + } + }); + +-// node_modules/@stoplight/lifecycle/disposable/DisposableCollection.js ++// node_modules/.pnpm/@stoplight+lifecycle@2.3.3/node_modules/@stoplight/lifecycle/disposable/DisposableCollection.js + var require_DisposableCollection = __commonJS({ +- "node_modules/@stoplight/lifecycle/disposable/DisposableCollection.js"(exports2) { ++ "node_modules/.pnpm/@stoplight+lifecycle@2.3.3/node_modules/@stoplight/lifecycle/disposable/DisposableCollection.js"(exports2) { + Object.defineProperty(exports2, "__esModule", { value: true }); + var createDisposable_1 = require_createDisposable(); + var DisposableCollection = class { +@@ -5205,9 +5205,9 @@ var require_DisposableCollection = __commonJS({ + } + }); + +-// node_modules/@stoplight/lifecycle/disposable/index.js ++// node_modules/.pnpm/@stoplight+lifecycle@2.3.3/node_modules/@stoplight/lifecycle/disposable/index.js + var require_disposable = __commonJS({ +- "node_modules/@stoplight/lifecycle/disposable/index.js"(exports2) { ++ "node_modules/.pnpm/@stoplight+lifecycle@2.3.3/node_modules/@stoplight/lifecycle/disposable/index.js"(exports2) { + Object.defineProperty(exports2, "__esModule", { value: true }); + var tslib_1 = (init_tslib_es6(), __toCommonJS(tslib_es6_exports)); + tslib_1.__exportStar(require_AsyncDisposer(), exports2); +@@ -5219,9 +5219,9 @@ var require_disposable = __commonJS({ + } + }); + +-// node_modules/wolfy87-eventemitter/EventEmitter.js ++// node_modules/.pnpm/wolfy87-eventemitter@5.2.9/node_modules/wolfy87-eventemitter/EventEmitter.js + var require_EventEmitter = __commonJS({ +- "node_modules/wolfy87-eventemitter/EventEmitter.js"(exports2, module2) { ++ "node_modules/.pnpm/wolfy87-eventemitter@5.2.9/node_modules/wolfy87-eventemitter/EventEmitter.js"(exports2, module2) { + (function(exports3) { + function EventEmitter2() { + } +@@ -5440,9 +5440,9 @@ var require_EventEmitter = __commonJS({ + } + }); + +-// node_modules/@stoplight/lifecycle/emitter/emitter.js ++// node_modules/.pnpm/@stoplight+lifecycle@2.3.3/node_modules/@stoplight/lifecycle/emitter/emitter.js + var require_emitter = __commonJS({ +- "node_modules/@stoplight/lifecycle/emitter/emitter.js"(exports2) { ++ "node_modules/.pnpm/@stoplight+lifecycle@2.3.3/node_modules/@stoplight/lifecycle/emitter/emitter.js"(exports2) { + Object.defineProperty(exports2, "__esModule", { value: true }); + var Emitter = require_EventEmitter(); + var disposable_1 = require_disposable(); +@@ -5529,18 +5529,18 @@ var require_emitter = __commonJS({ + } + }); + +-// node_modules/@stoplight/lifecycle/emitter/index.js ++// node_modules/.pnpm/@stoplight+lifecycle@2.3.3/node_modules/@stoplight/lifecycle/emitter/index.js + var require_emitter2 = __commonJS({ +- "node_modules/@stoplight/lifecycle/emitter/index.js"(exports2) { ++ "node_modules/.pnpm/@stoplight+lifecycle@2.3.3/node_modules/@stoplight/lifecycle/emitter/index.js"(exports2) { + Object.defineProperty(exports2, "__esModule", { value: true }); + var tslib_1 = (init_tslib_es6(), __toCommonJS(tslib_es6_exports)); + tslib_1.__exportStar(require_emitter(), exports2); + } + }); + +-// node_modules/@stoplight/lifecycle/index.js ++// node_modules/.pnpm/@stoplight+lifecycle@2.3.3/node_modules/@stoplight/lifecycle/index.js + var require_lifecycle = __commonJS({ +- "node_modules/@stoplight/lifecycle/index.js"(exports2) { ++ "node_modules/.pnpm/@stoplight+lifecycle@2.3.3/node_modules/@stoplight/lifecycle/index.js"(exports2) { + Object.defineProperty(exports2, "__esModule", { value: true }); + var tslib_1 = (init_tslib_es6(), __toCommonJS(tslib_es6_exports)); + tslib_1.__exportStar(require_activatable2(), exports2); +@@ -5549,9 +5549,9 @@ var require_lifecycle = __commonJS({ + } + }); + +-// node_modules/json-schema-compare/src/index.js ++// node_modules/.pnpm/json-schema-compare@0.2.2/node_modules/json-schema-compare/src/index.js + var require_src = __commonJS({ +- "node_modules/json-schema-compare/src/index.js"(exports2, module2) { ++ "node_modules/.pnpm/json-schema-compare@0.2.2/node_modules/json-schema-compare/src/index.js"(exports2, module2) { + var isEqual2 = (init_isEqual(), __toCommonJS(isEqual_exports)); + var sortBy2 = (init_sortBy(), __toCommonJS(sortBy_exports)); + var uniq3 = (init_uniq(), __toCommonJS(uniq_exports)); +@@ -5710,9 +5710,9 @@ var require_src = __commonJS({ + } + }); + +-// node_modules/validate.io-array/lib/index.js ++// node_modules/.pnpm/validate.io-array@1.0.6/node_modules/validate.io-array/lib/index.js + var require_lib = __commonJS({ +- "node_modules/validate.io-array/lib/index.js"(exports2, module2) { ++ "node_modules/.pnpm/validate.io-array@1.0.6/node_modules/validate.io-array/lib/index.js"(exports2, module2) { + function isArray2(value) { + return Object.prototype.toString.call(value) === "[object Array]"; + } +@@ -5720,9 +5720,9 @@ var require_lib = __commonJS({ + } + }); + +-// node_modules/validate.io-number/lib/index.js ++// node_modules/.pnpm/validate.io-number@1.0.3/node_modules/validate.io-number/lib/index.js + var require_lib2 = __commonJS({ +- "node_modules/validate.io-number/lib/index.js"(exports2, module2) { ++ "node_modules/.pnpm/validate.io-number@1.0.3/node_modules/validate.io-number/lib/index.js"(exports2, module2) { + function isNumber(value) { + return (typeof value === "number" || Object.prototype.toString.call(value) === "[object Number]") && value.valueOf() === value.valueOf(); + } +@@ -5730,9 +5730,9 @@ var require_lib2 = __commonJS({ + } + }); + +-// node_modules/validate.io-integer/lib/index.js ++// node_modules/.pnpm/validate.io-integer@1.0.5/node_modules/validate.io-integer/lib/index.js + var require_lib3 = __commonJS({ +- "node_modules/validate.io-integer/lib/index.js"(exports2, module2) { ++ "node_modules/.pnpm/validate.io-integer@1.0.5/node_modules/validate.io-integer/lib/index.js"(exports2, module2) { + var isNumber = require_lib2(); + function isInteger(value) { + return isNumber(value) && value % 1 === 0; +@@ -5741,9 +5741,9 @@ var require_lib3 = __commonJS({ + } + }); + +-// node_modules/validate.io-integer-array/lib/index.js ++// node_modules/.pnpm/validate.io-integer-array@1.0.0/node_modules/validate.io-integer-array/lib/index.js + var require_lib4 = __commonJS({ +- "node_modules/validate.io-integer-array/lib/index.js"(exports2, module2) { ++ "node_modules/.pnpm/validate.io-integer-array@1.0.0/node_modules/validate.io-integer-array/lib/index.js"(exports2, module2) { + var isArray2 = require_lib(); + var isInteger = require_lib3(); + function isIntegerArray(value) { +@@ -5766,9 +5766,9 @@ var require_lib4 = __commonJS({ + } + }); + +-// node_modules/validate.io-function/lib/index.js ++// node_modules/.pnpm/validate.io-function@1.0.2/node_modules/validate.io-function/lib/index.js + var require_lib5 = __commonJS({ +- "node_modules/validate.io-function/lib/index.js"(exports2, module2) { ++ "node_modules/.pnpm/validate.io-function@1.0.2/node_modules/validate.io-function/lib/index.js"(exports2, module2) { + function isFunction2(value) { + return typeof value === "function"; + } +@@ -5776,9 +5776,9 @@ var require_lib5 = __commonJS({ + } + }); + +-// node_modules/compute-gcd/lib/index.js ++// node_modules/.pnpm/compute-gcd@1.2.1/node_modules/compute-gcd/lib/index.js + var require_lib6 = __commonJS({ +- "node_modules/compute-gcd/lib/index.js"(exports2, module2) { ++ "node_modules/.pnpm/compute-gcd@1.2.1/node_modules/compute-gcd/lib/index.js"(exports2, module2) { + var isArray2 = require_lib(); + var isIntegerArray = require_lib4(); + var isFunction2 = require_lib5(); +@@ -5912,9 +5912,9 @@ var require_lib6 = __commonJS({ + } + }); + +-// node_modules/compute-lcm/lib/index.js ++// node_modules/.pnpm/compute-lcm@1.1.2/node_modules/compute-lcm/lib/index.js + var require_lib7 = __commonJS({ +- "node_modules/compute-lcm/lib/index.js"(exports2, module2) { ++ "node_modules/.pnpm/compute-lcm@1.1.2/node_modules/compute-lcm/lib/index.js"(exports2, module2) { + var gcd = require_lib6(); + var isArray2 = require_lib(); + var isIntegerArray = require_lib4(); +@@ -5988,9 +5988,9 @@ var require_lib7 = __commonJS({ + } + }); + +-// node_modules/@stoplight/json-schema-merge-allof/src/index.js ++// node_modules/.pnpm/@stoplight+json-schema-merge-allof@0.8.0/node_modules/@stoplight/json-schema-merge-allof/src/index.js + var require_src2 = __commonJS({ +- "node_modules/@stoplight/json-schema-merge-allof/src/index.js"(exports2, module2) { ++ "node_modules/.pnpm/@stoplight+json-schema-merge-allof@0.8.0/node_modules/@stoplight/json-schema-merge-allof/src/index.js"(exports2, module2) { + var compact2 = (init_compact(), __toCommonJS(compact_exports)); + var compare = require_src(); + var computeLcm = require_lib7(); +@@ -6519,7 +6519,7 @@ var require_src2 = __commonJS({ + } + }); + +-// node_modules/jsonc-parser/lib/esm/impl/parser.js ++// node_modules/.pnpm/jsonc-parser@2.2.1/node_modules/jsonc-parser/lib/esm/impl/parser.js + var ParseOptions; + (function(ParseOptions2) { + ParseOptions2.DEFAULT = { +@@ -6527,7 +6527,7 @@ var ParseOptions; + }; + })(ParseOptions || (ParseOptions = {})); + +-// node_modules/@stoplight/json/index.es.js ++// node_modules/.pnpm/@stoplight+json@3.21.7/node_modules/@stoplight/json/index.es.js + __toESM(require_safe_stable_stringify()); + function w(e) { + if ("object" != typeof e || null === e) return false; +@@ -6634,10 +6634,10 @@ function ne(e) { + return Q(e.split("/").pop() || ""); + } + +-// node_modules/@stoplight/json-schema-tree/index.es.js ++// node_modules/.pnpm/@stoplight+json-schema-tree@4.0.0/node_modules/@stoplight/json-schema-tree/index.es.js + var import_lifecycle = __toESM(require_lifecycle()); + +-// node_modules/magic-error/index.mjs ++// node_modules/.pnpm/magic-error@0.0.1/node_modules/magic-error/index.mjs + function magic_error_default(err) { + return new Proxy(err, { + getOwnPropertyDescriptor(target, key) { +@@ -6672,7 +6672,7 @@ function* traversePrototypeUntilErrorPrototype(prototype) { + } + } + +-// node_modules/@stoplight/json-schema-tree/index.es.js ++// node_modules/.pnpm/@stoplight+json-schema-tree@4.0.0/node_modules/@stoplight/json-schema-tree/index.es.js + var SEED = BigInt(0); + var BaseNode = class { + constructor() { +@@ -7786,16 +7786,23 @@ var ChildStack = React2.memo( + } + ); + ChildStack.displayName = "ChildStack"; ++var Markdown = React2.lazy(async () => { ++ return await import('react-markdown'); ++}); ++var MarkupWithFallback = ({ value }) => { ++ return /* @__PURE__ */ jsx(JsonSchemaViewerErrorBoundary, { fallback: value, children: /* @__PURE__ */ jsx(React2.Suspense, { children: /* @__PURE__ */ jsx(Markdown, { children: value }) }) }); ++}; + var Description = ({ value }) => { + const [showAll, setShowAll] = React2.useState(false); ++ const { markup = false } = useJSVOptionsContext(); + if (typeof value !== "string" || value.trim().length === 0) return null; + const paragraphs = value.split("\n\n"); + if (paragraphs.length <= 1 || showAll) { +- return /* @__PURE__ */ jsx("div", { className: "jsv-description", "data-test": "property-description", children: value }); ++ return /* @__PURE__ */ jsx("div", { className: "jsv-description", "data-test": "property-description", children: markup ? /* @__PURE__ */ jsx(MarkupWithFallback, { value }) : value }); + } + const firstParagraph = paragraphs[0]; + return /* @__PURE__ */ jsx("div", { className: "jsv-description", "data-test": "property-description", children: /* @__PURE__ */ jsxs("p", { children: [ +- /* @__PURE__ */ jsx("span", { className: "mr-1", children: firstParagraph }), ++ /* @__PURE__ */ jsx("span", { className: "mr-1", children: markup ? /* @__PURE__ */ jsx(MarkupWithFallback, { value: firstParagraph }) : firstParagraph }), + /* @__PURE__ */ jsx( + "button", + { +@@ -8238,11 +8245,37 @@ function last2(arr) { + function calculateChoiceTitle(node, isPlural) { + const primitiveSuffix = isPlural ? "s" : ""; + if (isRegularNode(node)) { ++ const fragment = node.originalFragment; ++ if (fragment.title) { ++ return fragment.title; ++ } + const realName = printName(node, { shouldUseRefNameFallback: true }); + if (realName) { + return realName; + } +- return node.primaryType !== null ? node.primaryType + primitiveSuffix : String(node.originalFragment.title || "any"); ++ if (node.primaryType === "object") { ++ const nestedCombiner = fragment.oneOf || fragment.anyOf; ++ if (nestedCombiner && nestedCombiner.length > 0) { ++ const nestedTitles = nestedCombiner.map((item) => item.title).filter((t) => typeof t === "string"); ++ if (nestedTitles.length > 0) { ++ return nestedTitles.join(" / "); ++ } ++ } ++ if (fragment.properties) { ++ const propKeys = Object.keys(fragment.properties); ++ if (propKeys.length > 0) { ++ const firstProp = fragment.properties[propKeys[0]]; ++ if (firstProp?.type && propKeys.length <= 3) { ++ return `object (${propKeys[0]}: ${firstProp.type})`; ++ } ++ if (propKeys.length <= 2) { ++ return `object {${propKeys.join(", ")}}`; ++ } ++ } ++ } ++ return "object" + primitiveSuffix; ++ } ++ return node.primaryType !== null ? node.primaryType + primitiveSuffix : "any"; + } + if (isReferenceNode(node)) { + if (node.value) { +@@ -8278,7 +8311,7 @@ var useChoices = (schemaNode) => { + ); + } + if (isNonEmptyParentNode(schemaNode) && shouldShowChildSelector(schemaNode)) { +- return schemaNode.children.map(makeChoice); ++ return schemaNode.children.map((child) => makeChoice(child)); + } + return [makeChoice(schemaNode)]; + }, [schemaNode]); +@@ -8468,22 +8501,6 @@ var TopLevelSchemaRow = ({ + [schemaNode.fragment] + ); + const hasVendorProperties = totalVendorExtensions > 0; +- if (isRegularNode(schemaNode) && isPureObjectNode(schemaNode)) { +- return /* @__PURE__ */ jsxs(Fragment, { children: [ +- !skipDescription ? /* @__PURE__ */ jsx(Description, { value: schemaNode.annotations.description }) : null, +- hasVendorProperties && renderExtensionAddon ? renderExtensionAddon({ schemaNode, nestingLevel, vendorExtensions }) : null, +- /* @__PURE__ */ jsx( +- ChildStack, +- { +- schemaNode, +- childNodes, +- currentNestingLevel: nestingLevel, +- parentNodeId: nodeId +- } +- ), +- /* @__PURE__ */ jsx(Error2, { schemaNode }) +- ] }); +- } + if (isRegularNode(schemaNode) && choices.length > 1) { + const combiner = isRegularNode(schemaNode) && schemaNode.combiners?.length ? schemaNode.combiners[0] : null; + return /* @__PURE__ */ jsxs(Fragment, { children: [ +@@ -8517,6 +8534,22 @@ var TopLevelSchemaRow = ({ + ) : combiner ? /* @__PURE__ */ jsx(SchemaRow, { schemaNode: selectedChoice.type, nestingLevel }) : null + ] }); + } ++ if (isRegularNode(schemaNode) && isPureObjectNode(schemaNode)) { ++ return /* @__PURE__ */ jsxs(Fragment, { children: [ ++ !skipDescription ? /* @__PURE__ */ jsx(Description, { value: schemaNode.annotations.description }) : null, ++ hasVendorProperties && renderExtensionAddon ? renderExtensionAddon({ schemaNode, nestingLevel, vendorExtensions }) : null, ++ /* @__PURE__ */ jsx( ++ ChildStack, ++ { ++ schemaNode, ++ childNodes, ++ currentNestingLevel: nestingLevel, ++ parentNodeId: nodeId ++ } ++ ), ++ /* @__PURE__ */ jsx(Error2, { schemaNode }) ++ ] }); ++ } + if (isComplexArray(schemaNode) && isPureObjectNode(schemaNode.children[0])) { + const validations = isRegularNode(schemaNode) ? getValidationsFromSchema(schemaNode) : {}; + return /* @__PURE__ */ jsxs(Fragment, { children: [ +@@ -8550,6 +8583,7 @@ var JsonSchemaViewer = ({ + disableCrumbs, + nodeHasChanged, + skipTopLevelDescription, ++ markup, + ...rest + }) => { + const options = React2.useMemo( +@@ -8562,7 +8596,8 @@ var JsonSchemaViewer = ({ + hideExamples, + renderRootTreeLines, + disableCrumbs, +- nodeHasChanged ++ nodeHasChanged, ++ markup + }), + [ + defaultExpandedDepth, +@@ -8573,7 +8608,8 @@ var JsonSchemaViewer = ({ + hideExamples, + renderRootTreeLines, + disableCrumbs, +- nodeHasChanged ++ nodeHasChanged, ++ markup + ] + ); + return /* @__PURE__ */ jsx(JSVOptionsContextProvider, { value: options, children: /* @__PURE__ */ jsx(Provider, { children: /* @__PURE__ */ jsx( +diff --git a/node_modules/cf-json-schema-viz/dist/index.js.map b/node_modules/cf-json-schema-viz/dist/index.js.map +index ecef5aa..9820d78 100644 +--- a/node_modules/cf-json-schema-viz/dist/index.js.map ++++ b/node_modules/cf-json-schema-viz/dist/index.js.map +@@ -1 +1 @@ +-{"version":3,"sources":["../node_modules/lodash-es/_freeGlobal.js","../node_modules/lodash-es/_root.js","../node_modules/lodash-es/_Symbol.js","../node_modules/lodash-es/_getRawTag.js","../node_modules/lodash-es/_objectToString.js","../node_modules/lodash-es/_baseGetTag.js","../node_modules/lodash-es/isObjectLike.js","../node_modules/lodash-es/isSymbol.js","../node_modules/lodash-es/_arrayMap.js","../node_modules/lodash-es/isArray.js","../node_modules/lodash-es/_baseToString.js","../node_modules/lodash-es/isObject.js","../node_modules/lodash-es/identity.js","../node_modules/lodash-es/isFunction.js","../node_modules/lodash-es/_coreJsData.js","../node_modules/lodash-es/_isMasked.js","../node_modules/lodash-es/_toSource.js","../node_modules/lodash-es/_baseIsNative.js","../node_modules/lodash-es/_getValue.js","../node_modules/lodash-es/_getNative.js","../node_modules/lodash-es/_WeakMap.js","../node_modules/lodash-es/_baseCreate.js","../node_modules/lodash-es/_apply.js","../node_modules/lodash-es/noop.js","../node_modules/lodash-es/_copyArray.js","../node_modules/lodash-es/_shortOut.js","../node_modules/lodash-es/constant.js","../node_modules/lodash-es/_defineProperty.js","../node_modules/lodash-es/_baseSetToString.js","../node_modules/lodash-es/_setToString.js","../node_modules/lodash-es/_arrayEach.js","../node_modules/lodash-es/_baseFindIndex.js","../node_modules/lodash-es/_baseIsNaN.js","../node_modules/lodash-es/_strictIndexOf.js","../node_modules/lodash-es/_baseIndexOf.js","../node_modules/lodash-es/_arrayIncludes.js","../node_modules/lodash-es/_isIndex.js","../node_modules/lodash-es/_baseAssignValue.js","../node_modules/lodash-es/eq.js","../node_modules/lodash-es/_assignValue.js","../node_modules/lodash-es/_copyObject.js","../node_modules/lodash-es/_overRest.js","../node_modules/lodash-es/_baseRest.js","../node_modules/lodash-es/isLength.js","../node_modules/lodash-es/isArrayLike.js","../node_modules/lodash-es/_isIterateeCall.js","../node_modules/lodash-es/_createAssigner.js","../node_modules/lodash-es/_isPrototype.js","../node_modules/lodash-es/_baseTimes.js","../node_modules/lodash-es/_baseIsArguments.js","../node_modules/lodash-es/isArguments.js","../node_modules/lodash-es/stubFalse.js","../node_modules/lodash-es/isBuffer.js","../node_modules/lodash-es/_baseIsTypedArray.js","../node_modules/lodash-es/_baseUnary.js","../node_modules/lodash-es/_nodeUtil.js","../node_modules/lodash-es/isTypedArray.js","../node_modules/lodash-es/_arrayLikeKeys.js","../node_modules/lodash-es/_overArg.js","../node_modules/lodash-es/_nativeKeys.js","../node_modules/lodash-es/_baseKeys.js","../node_modules/lodash-es/keys.js","../node_modules/lodash-es/_nativeKeysIn.js","../node_modules/lodash-es/_baseKeysIn.js","../node_modules/lodash-es/keysIn.js","../node_modules/lodash-es/_isKey.js","../node_modules/lodash-es/_nativeCreate.js","../node_modules/lodash-es/_hashClear.js","../node_modules/lodash-es/_hashDelete.js","../node_modules/lodash-es/_hashGet.js","../node_modules/lodash-es/_hashHas.js","../node_modules/lodash-es/_hashSet.js","../node_modules/lodash-es/_Hash.js","../node_modules/lodash-es/_listCacheClear.js","../node_modules/lodash-es/_assocIndexOf.js","../node_modules/lodash-es/_listCacheDelete.js","../node_modules/lodash-es/_listCacheGet.js","../node_modules/lodash-es/_listCacheHas.js","../node_modules/lodash-es/_listCacheSet.js","../node_modules/lodash-es/_ListCache.js","../node_modules/lodash-es/_Map.js","../node_modules/lodash-es/_mapCacheClear.js","../node_modules/lodash-es/_isKeyable.js","../node_modules/lodash-es/_getMapData.js","../node_modules/lodash-es/_mapCacheDelete.js","../node_modules/lodash-es/_mapCacheGet.js","../node_modules/lodash-es/_mapCacheHas.js","../node_modules/lodash-es/_mapCacheSet.js","../node_modules/lodash-es/_MapCache.js","../node_modules/lodash-es/memoize.js","../node_modules/lodash-es/_memoizeCapped.js","../node_modules/lodash-es/_stringToPath.js","../node_modules/lodash-es/toString.js","../node_modules/lodash-es/_castPath.js","../node_modules/lodash-es/_toKey.js","../node_modules/lodash-es/_baseGet.js","../node_modules/lodash-es/get.js","../node_modules/lodash-es/_arrayPush.js","../node_modules/lodash-es/_isFlattenable.js","../node_modules/lodash-es/_baseFlatten.js","../node_modules/lodash-es/flatten.js","../node_modules/lodash-es/_flatRest.js","../node_modules/lodash-es/_getPrototype.js","../node_modules/lodash-es/isPlainObject.js","../node_modules/lodash-es/_stackClear.js","../node_modules/lodash-es/_stackDelete.js","../node_modules/lodash-es/_stackGet.js","../node_modules/lodash-es/_stackHas.js","../node_modules/lodash-es/_stackSet.js","../node_modules/lodash-es/_Stack.js","../node_modules/lodash-es/_cloneBuffer.js","../node_modules/lodash-es/_arrayFilter.js","../node_modules/lodash-es/stubArray.js","../node_modules/lodash-es/_getSymbols.js","../node_modules/lodash-es/_baseGetAllKeys.js","../node_modules/lodash-es/_getAllKeys.js","../node_modules/lodash-es/_DataView.js","../node_modules/lodash-es/_Promise.js","../node_modules/lodash-es/_Set.js","../node_modules/lodash-es/_getTag.js","../node_modules/lodash-es/_Uint8Array.js","../node_modules/lodash-es/_cloneArrayBuffer.js","../node_modules/lodash-es/_cloneTypedArray.js","../node_modules/lodash-es/_initCloneObject.js","../node_modules/lodash-es/compact.js","../node_modules/lodash-es/_setCacheAdd.js","../node_modules/lodash-es/_setCacheHas.js","../node_modules/lodash-es/_SetCache.js","../node_modules/lodash-es/_arraySome.js","../node_modules/lodash-es/_cacheHas.js","../node_modules/lodash-es/_equalArrays.js","../node_modules/lodash-es/_mapToArray.js","../node_modules/lodash-es/_setToArray.js","../node_modules/lodash-es/_equalByTag.js","../node_modules/lodash-es/_equalObjects.js","../node_modules/lodash-es/_baseIsEqualDeep.js","../node_modules/lodash-es/_baseIsEqual.js","../node_modules/lodash-es/_baseIsMatch.js","../node_modules/lodash-es/_isStrictComparable.js","../node_modules/lodash-es/_getMatchData.js","../node_modules/lodash-es/_matchesStrictComparable.js","../node_modules/lodash-es/_baseMatches.js","../node_modules/lodash-es/_baseHasIn.js","../node_modules/lodash-es/_hasPath.js","../node_modules/lodash-es/hasIn.js","../node_modules/lodash-es/_baseMatchesProperty.js","../node_modules/lodash-es/_baseProperty.js","../node_modules/lodash-es/_basePropertyDeep.js","../node_modules/lodash-es/property.js","../node_modules/lodash-es/_baseIteratee.js","../node_modules/lodash-es/_createBaseFor.js","../node_modules/lodash-es/_baseFor.js","../node_modules/lodash-es/_baseForOwn.js","../node_modules/lodash-es/_createBaseEach.js","../node_modules/lodash-es/_baseEach.js","../node_modules/lodash-es/defaults.js","../node_modules/lodash-es/_assignMergeValue.js","../node_modules/lodash-es/isArrayLikeObject.js","../node_modules/lodash-es/_safeGet.js","../node_modules/lodash-es/toPlainObject.js","../node_modules/lodash-es/_baseMergeDeep.js","../node_modules/lodash-es/_baseMerge.js","../node_modules/lodash-es/_customDefaultsMerge.js","../node_modules/lodash-es/mergeWith.js","../node_modules/lodash-es/defaultsDeep.js","../node_modules/lodash-es/_arrayIncludesWith.js","../node_modules/lodash-es/_baseDifference.js","../node_modules/lodash-es/last.js","../node_modules/lodash-es/_castFunction.js","../node_modules/lodash-es/forEach.js","../node_modules/lodash-es/_baseMap.js","../node_modules/lodash-es/flattenDeep.js","../node_modules/lodash-es/_baseIntersection.js","../node_modules/lodash-es/_castArrayLikeObject.js","../node_modules/lodash-es/intersection.js","../node_modules/lodash-es/intersectionWith.js","../node_modules/lodash-es/isBoolean.js","../node_modules/lodash-es/isEqual.js","../node_modules/lodash-es/_baseSet.js","../node_modules/lodash-es/_basePickBy.js","../node_modules/lodash-es/_baseSortBy.js","../node_modules/lodash-es/_compareAscending.js","../node_modules/lodash-es/_compareMultiple.js","../node_modules/lodash-es/_baseOrderBy.js","../node_modules/lodash-es/_basePick.js","../node_modules/lodash-es/pick.js","../node_modules/lodash-es/_baseIndexOfWith.js","../node_modules/lodash-es/_basePullAll.js","../node_modules/lodash-es/pullAll.js","../node_modules/lodash-es/sortBy.js","../node_modules/lodash-es/_createSet.js","../node_modules/lodash-es/_baseUniq.js","../node_modules/lodash-es/uniq.js","../node_modules/lodash-es/uniqWith.js","../node_modules/lodash-es/without.js","../node_modules/safe-stable-stringify/stable.js","../node_modules/safe-stable-stringify/index.js","../node_modules/tslib/tslib.es6.mjs","../node_modules/@stoplight/src/activatable/activatable.ts","../node_modules/@stoplight/src/activatable/index.ts","../node_modules/@stoplight/src/disposable/AsyncDisposer.ts","../node_modules/@stoplight/src/disposable/AsyncDisposableSet.ts","../node_modules/@stoplight/src/disposable/Disposer.ts","../node_modules/@stoplight/src/disposable/DisposableSet.ts","../node_modules/@stoplight/src/disposable/createDisposable.ts","../node_modules/@stoplight/src/disposable/DisposableCollection.ts","../node_modules/@stoplight/src/disposable/index.ts","../node_modules/wolfy87-eventemitter/EventEmitter.js","../node_modules/@stoplight/src/emitter/emitter.ts","../node_modules/@stoplight/src/emitter/index.ts","../node_modules/@stoplight/src/index.ts","../node_modules/json-schema-compare/src/index.js","../node_modules/validate.io-array/lib/index.js","../node_modules/validate.io-number/lib/index.js","../node_modules/validate.io-integer/lib/index.js","../node_modules/validate.io-integer-array/lib/index.js","../node_modules/validate.io-function/lib/index.js","../node_modules/compute-gcd/lib/index.js","../node_modules/compute-lcm/lib/index.js","../node_modules/@stoplight/json-schema-merge-allof/src/index.js","../node_modules/jsonc-parser/lib/esm/impl/parser.js","../node_modules/@stoplight/json/index.es.js","../node_modules/magic-error/index.mjs","../node_modules/@stoplight/src/nodes/BaseNode.ts","../node_modules/@stoplight/src/nodes/BooleanishNode.ts","../node_modules/@stoplight/src/nodes/mirrored/MirroredReferenceNode.ts","../node_modules/@stoplight/src/utils/guards.ts","../node_modules/@stoplight/src/utils/pick.ts","../node_modules/@stoplight/src/nodes/mirrored/MirroredRegularNode.ts","../node_modules/@stoplight/src/accessors/unwrap.ts","../node_modules/@stoplight/src/nodes/ReferenceNode.ts","../node_modules/@stoplight/src/accessors/getAnnotations.ts","../node_modules/@stoplight/src/nodes/types.ts","../node_modules/@stoplight/src/accessors/getCombiners.ts","../node_modules/@stoplight/src/accessors/getPrimaryType.ts","../node_modules/@stoplight/src/accessors/getRequired.ts","../node_modules/@stoplight/src/accessors/guards/isValidType.ts","../node_modules/@stoplight/src/accessors/inferType.ts","../node_modules/@stoplight/src/accessors/getTypes.ts","../node_modules/@stoplight/src/accessors/getValidations.ts","../node_modules/@stoplight/src/accessors/isDeprecated.ts","../node_modules/@stoplight/src/nodes/RegularNode.ts","../node_modules/@stoplight/src/nodes/RootNode.ts","../node_modules/@stoplight/src/guards/nodes.ts","../node_modules/@stoplight/src/errors.ts","../node_modules/@stoplight/src/mergers/mergeAllOf.ts","../node_modules/@stoplight/src/mergers/mergeOneOrAnyOf.ts","../node_modules/@stoplight/src/walker/walker.ts","../node_modules/@stoplight/src/tree/tree.ts","../src/contexts/jsvOptions.tsx","../src/guards/isNonNullable.ts","../src/tree/utils.ts","../src/components/SchemaRow/state.ts","../src/components/PathCrumbs/state.ts","../src/components/PathCrumbs/index.tsx","../src/consts.ts","../src/hash.ts","../src/utils/extractVendorExtensions.ts","../src/components/shared/Caret.tsx","../src/components/shared/ChildStack.tsx","../src/components/shared/Description.tsx","../src/components/shared/Divider.tsx","../src/utils/getInternalSchemaError.ts","../src/components/shared/Error.tsx","../src/components/shared/NodeAnnotation.tsx","../src/components/shared/Properties.tsx","../src/components/shared/Select.tsx","../src/utils/getApplicableFormats.ts","../src/utils/printName.ts","../src/components/shared/Types.tsx","../src/components/shared/Validations.tsx","../src/components/SchemaRow/useChoices.ts","../src/components/SchemaRow/SchemaRow.tsx","../src/components/SchemaRow/TopLevelSchemaRow.tsx","../src/components/JsonSchemaViewer.tsx"],"names":["Symbol","nativeObjectToString","objectProto","symToStringTag","funcProto","funcToString","hasOwnProperty","WeakMap","MAX_SAFE_INTEGER","Buffer","argsTag","funcTag","freeExports","freeModule","moduleExports","HASH_UNDEFINED","Map","INFINITY","objectTag","propertyIsEnumerable","Promise","Set","mapTag","setTag","weakMapTag","dataViewTag","Uint8Array","othValue","arrayBufferTag","boolTag","dateTag","numberTag","errorTag","regexpTag","stringTag","COMPARE_PARTIAL_FLAG","COMPARE_UNORDERED_FLAG","symbolTag","symbolProto","arrayTag","LARGE_ARRAY_SIZE","collection","splice","arrayProto","exports","module","last","tmp","keys","j","b","_","x","P","k","v","d","__assign","k2","o","EventEmitter","isEqual","sortBy","uniq","uniqWith","defaults","intersectionWith","isPlainObject","isBoolean","compare","key","a","isArray","require_lib","isFunction","require_src","compact","defaultsDeep","flatten","flattenDeep","intersection","pullAll","pick","forEach","without","schemas","inferType","ownKeys","merged","first","merger","ParseOptions","e","t","r","isObject","SchemaNodeKind","SchemaCombinerName","resolved","root","_a","React","isNonNullable","get","atom","hash","jsx","React3","clsx","React4","jsxs","useAtomValue","React5","Error","Fragment","BaseSelect","format","getTypes","React6","React7","React8","getStoplightId","React9","CaretDown","React10","useSetAtom","nodeCount","isEmpty"],"mappings":"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","file":"index.js","sourcesContent":["/** Detect free variable `global` from Node.js. */\nvar freeGlobal = typeof global == 'object' && global && global.Object === Object && global;\n\nexport default freeGlobal;\n","import freeGlobal from './_freeGlobal.js';\n\n/** Detect free variable `self`. */\nvar freeSelf = typeof self == 'object' && self && self.Object === Object && self;\n\n/** Used as a reference to the global object. */\nvar root = freeGlobal || freeSelf || Function('return this')();\n\nexport default root;\n","import root from './_root.js';\n\n/** Built-in value references. */\nvar Symbol = root.Symbol;\n\nexport default Symbol;\n","import Symbol from './_Symbol.js';\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * Used to resolve the\n * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)\n * of values.\n */\nvar nativeObjectToString = objectProto.toString;\n\n/** Built-in value references. */\nvar symToStringTag = Symbol ? Symbol.toStringTag : undefined;\n\n/**\n * A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values.\n *\n * @private\n * @param {*} value The value to query.\n * @returns {string} Returns the raw `toStringTag`.\n */\nfunction getRawTag(value) {\n var isOwn = hasOwnProperty.call(value, symToStringTag),\n tag = value[symToStringTag];\n\n try {\n value[symToStringTag] = undefined;\n var unmasked = true;\n } catch (e) {}\n\n var result = nativeObjectToString.call(value);\n if (unmasked) {\n if (isOwn) {\n value[symToStringTag] = tag;\n } else {\n delete value[symToStringTag];\n }\n }\n return result;\n}\n\nexport default getRawTag;\n","/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/**\n * Used to resolve the\n * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)\n * of values.\n */\nvar nativeObjectToString = objectProto.toString;\n\n/**\n * Converts `value` to a string using `Object.prototype.toString`.\n *\n * @private\n * @param {*} value The value to convert.\n * @returns {string} Returns the converted string.\n */\nfunction objectToString(value) {\n return nativeObjectToString.call(value);\n}\n\nexport default objectToString;\n","import Symbol from './_Symbol.js';\nimport getRawTag from './_getRawTag.js';\nimport objectToString from './_objectToString.js';\n\n/** `Object#toString` result references. */\nvar nullTag = '[object Null]',\n undefinedTag = '[object Undefined]';\n\n/** Built-in value references. */\nvar symToStringTag = Symbol ? Symbol.toStringTag : undefined;\n\n/**\n * The base implementation of `getTag` without fallbacks for buggy environments.\n *\n * @private\n * @param {*} value The value to query.\n * @returns {string} Returns the `toStringTag`.\n */\nfunction baseGetTag(value) {\n if (value == null) {\n return value === undefined ? undefinedTag : nullTag;\n }\n return (symToStringTag && symToStringTag in Object(value))\n ? getRawTag(value)\n : objectToString(value);\n}\n\nexport default baseGetTag;\n","/**\n * Checks if `value` is object-like. A value is object-like if it's not `null`\n * and has a `typeof` result of \"object\".\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is object-like, else `false`.\n * @example\n *\n * _.isObjectLike({});\n * // => true\n *\n * _.isObjectLike([1, 2, 3]);\n * // => true\n *\n * _.isObjectLike(_.noop);\n * // => false\n *\n * _.isObjectLike(null);\n * // => false\n */\nfunction isObjectLike(value) {\n return value != null && typeof value == 'object';\n}\n\nexport default isObjectLike;\n","import baseGetTag from './_baseGetTag.js';\nimport isObjectLike from './isObjectLike.js';\n\n/** `Object#toString` result references. */\nvar symbolTag = '[object Symbol]';\n\n/**\n * Checks if `value` is classified as a `Symbol` primitive or object.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a symbol, else `false`.\n * @example\n *\n * _.isSymbol(Symbol.iterator);\n * // => true\n *\n * _.isSymbol('abc');\n * // => false\n */\nfunction isSymbol(value) {\n return typeof value == 'symbol' ||\n (isObjectLike(value) && baseGetTag(value) == symbolTag);\n}\n\nexport default isSymbol;\n","/**\n * A specialized version of `_.map` for arrays without support for iteratee\n * shorthands.\n *\n * @private\n * @param {Array} [array] The array to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @returns {Array} Returns the new mapped array.\n */\nfunction arrayMap(array, iteratee) {\n var index = -1,\n length = array == null ? 0 : array.length,\n result = Array(length);\n\n while (++index < length) {\n result[index] = iteratee(array[index], index, array);\n }\n return result;\n}\n\nexport default arrayMap;\n","/**\n * Checks if `value` is classified as an `Array` object.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an array, else `false`.\n * @example\n *\n * _.isArray([1, 2, 3]);\n * // => true\n *\n * _.isArray(document.body.children);\n * // => false\n *\n * _.isArray('abc');\n * // => false\n *\n * _.isArray(_.noop);\n * // => false\n */\nvar isArray = Array.isArray;\n\nexport default isArray;\n","import Symbol from './_Symbol.js';\nimport arrayMap from './_arrayMap.js';\nimport isArray from './isArray.js';\nimport isSymbol from './isSymbol.js';\n\n/** Used as references for various `Number` constants. */\nvar INFINITY = 1 / 0;\n\n/** Used to convert symbols to primitives and strings. */\nvar symbolProto = Symbol ? Symbol.prototype : undefined,\n symbolToString = symbolProto ? symbolProto.toString : undefined;\n\n/**\n * The base implementation of `_.toString` which doesn't convert nullish\n * values to empty strings.\n *\n * @private\n * @param {*} value The value to process.\n * @returns {string} Returns the string.\n */\nfunction baseToString(value) {\n // Exit early for strings to avoid a performance hit in some environments.\n if (typeof value == 'string') {\n return value;\n }\n if (isArray(value)) {\n // Recursively convert values (susceptible to call stack limits).\n return arrayMap(value, baseToString) + '';\n }\n if (isSymbol(value)) {\n return symbolToString ? symbolToString.call(value) : '';\n }\n var result = (value + '');\n return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result;\n}\n\nexport default baseToString;\n","/**\n * Checks if `value` is the\n * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)\n * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an object, else `false`.\n * @example\n *\n * _.isObject({});\n * // => true\n *\n * _.isObject([1, 2, 3]);\n * // => true\n *\n * _.isObject(_.noop);\n * // => true\n *\n * _.isObject(null);\n * // => false\n */\nfunction isObject(value) {\n var type = typeof value;\n return value != null && (type == 'object' || type == 'function');\n}\n\nexport default isObject;\n","/**\n * This method returns the first argument it receives.\n *\n * @static\n * @since 0.1.0\n * @memberOf _\n * @category Util\n * @param {*} value Any value.\n * @returns {*} Returns `value`.\n * @example\n *\n * var object = { 'a': 1 };\n *\n * console.log(_.identity(object) === object);\n * // => true\n */\nfunction identity(value) {\n return value;\n}\n\nexport default identity;\n","import baseGetTag from './_baseGetTag.js';\nimport isObject from './isObject.js';\n\n/** `Object#toString` result references. */\nvar asyncTag = '[object AsyncFunction]',\n funcTag = '[object Function]',\n genTag = '[object GeneratorFunction]',\n proxyTag = '[object Proxy]';\n\n/**\n * Checks if `value` is classified as a `Function` object.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a function, else `false`.\n * @example\n *\n * _.isFunction(_);\n * // => true\n *\n * _.isFunction(/abc/);\n * // => false\n */\nfunction isFunction(value) {\n if (!isObject(value)) {\n return false;\n }\n // The use of `Object#toString` avoids issues with the `typeof` operator\n // in Safari 9 which returns 'object' for typed arrays and other constructors.\n var tag = baseGetTag(value);\n return tag == funcTag || tag == genTag || tag == asyncTag || tag == proxyTag;\n}\n\nexport default isFunction;\n","import root from './_root.js';\n\n/** Used to detect overreaching core-js shims. */\nvar coreJsData = root['__core-js_shared__'];\n\nexport default coreJsData;\n","import coreJsData from './_coreJsData.js';\n\n/** Used to detect methods masquerading as native. */\nvar maskSrcKey = (function() {\n var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || '');\n return uid ? ('Symbol(src)_1.' + uid) : '';\n}());\n\n/**\n * Checks if `func` has its source masked.\n *\n * @private\n * @param {Function} func The function to check.\n * @returns {boolean} Returns `true` if `func` is masked, else `false`.\n */\nfunction isMasked(func) {\n return !!maskSrcKey && (maskSrcKey in func);\n}\n\nexport default isMasked;\n","/** Used for built-in method references. */\nvar funcProto = Function.prototype;\n\n/** Used to resolve the decompiled source of functions. */\nvar funcToString = funcProto.toString;\n\n/**\n * Converts `func` to its source code.\n *\n * @private\n * @param {Function} func The function to convert.\n * @returns {string} Returns the source code.\n */\nfunction toSource(func) {\n if (func != null) {\n try {\n return funcToString.call(func);\n } catch (e) {}\n try {\n return (func + '');\n } catch (e) {}\n }\n return '';\n}\n\nexport default toSource;\n","import isFunction from './isFunction.js';\nimport isMasked from './_isMasked.js';\nimport isObject from './isObject.js';\nimport toSource from './_toSource.js';\n\n/**\n * Used to match `RegExp`\n * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns).\n */\nvar reRegExpChar = /[\\\\^$.*+?()[\\]{}|]/g;\n\n/** Used to detect host constructors (Safari). */\nvar reIsHostCtor = /^\\[object .+?Constructor\\]$/;\n\n/** Used for built-in method references. */\nvar funcProto = Function.prototype,\n objectProto = Object.prototype;\n\n/** Used to resolve the decompiled source of functions. */\nvar funcToString = funcProto.toString;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/** Used to detect if a method is native. */\nvar reIsNative = RegExp('^' +\n funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\\\$&')\n .replace(/hasOwnProperty|(function).*?(?=\\\\\\()| for .+?(?=\\\\\\])/g, '$1.*?') + '$'\n);\n\n/**\n * The base implementation of `_.isNative` without bad shim checks.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a native function,\n * else `false`.\n */\nfunction baseIsNative(value) {\n if (!isObject(value) || isMasked(value)) {\n return false;\n }\n var pattern = isFunction(value) ? reIsNative : reIsHostCtor;\n return pattern.test(toSource(value));\n}\n\nexport default baseIsNative;\n","/**\n * Gets the value at `key` of `object`.\n *\n * @private\n * @param {Object} [object] The object to query.\n * @param {string} key The key of the property to get.\n * @returns {*} Returns the property value.\n */\nfunction getValue(object, key) {\n return object == null ? undefined : object[key];\n}\n\nexport default getValue;\n","import baseIsNative from './_baseIsNative.js';\nimport getValue from './_getValue.js';\n\n/**\n * Gets the native function at `key` of `object`.\n *\n * @private\n * @param {Object} object The object to query.\n * @param {string} key The key of the method to get.\n * @returns {*} Returns the function if it's native, else `undefined`.\n */\nfunction getNative(object, key) {\n var value = getValue(object, key);\n return baseIsNative(value) ? value : undefined;\n}\n\nexport default getNative;\n","import getNative from './_getNative.js';\nimport root from './_root.js';\n\n/* Built-in method references that are verified to be native. */\nvar WeakMap = getNative(root, 'WeakMap');\n\nexport default WeakMap;\n","import isObject from './isObject.js';\n\n/** Built-in value references. */\nvar objectCreate = Object.create;\n\n/**\n * The base implementation of `_.create` without support for assigning\n * properties to the created object.\n *\n * @private\n * @param {Object} proto The object to inherit from.\n * @returns {Object} Returns the new object.\n */\nvar baseCreate = (function() {\n function object() {}\n return function(proto) {\n if (!isObject(proto)) {\n return {};\n }\n if (objectCreate) {\n return objectCreate(proto);\n }\n object.prototype = proto;\n var result = new object;\n object.prototype = undefined;\n return result;\n };\n}());\n\nexport default baseCreate;\n","/**\n * A faster alternative to `Function#apply`, this function invokes `func`\n * with the `this` binding of `thisArg` and the arguments of `args`.\n *\n * @private\n * @param {Function} func The function to invoke.\n * @param {*} thisArg The `this` binding of `func`.\n * @param {Array} args The arguments to invoke `func` with.\n * @returns {*} Returns the result of `func`.\n */\nfunction apply(func, thisArg, args) {\n switch (args.length) {\n case 0: return func.call(thisArg);\n case 1: return func.call(thisArg, args[0]);\n case 2: return func.call(thisArg, args[0], args[1]);\n case 3: return func.call(thisArg, args[0], args[1], args[2]);\n }\n return func.apply(thisArg, args);\n}\n\nexport default apply;\n","/**\n * This method returns `undefined`.\n *\n * @static\n * @memberOf _\n * @since 2.3.0\n * @category Util\n * @example\n *\n * _.times(2, _.noop);\n * // => [undefined, undefined]\n */\nfunction noop() {\n // No operation performed.\n}\n\nexport default noop;\n","/**\n * Copies the values of `source` to `array`.\n *\n * @private\n * @param {Array} source The array to copy values from.\n * @param {Array} [array=[]] The array to copy values to.\n * @returns {Array} Returns `array`.\n */\nfunction copyArray(source, array) {\n var index = -1,\n length = source.length;\n\n array || (array = Array(length));\n while (++index < length) {\n array[index] = source[index];\n }\n return array;\n}\n\nexport default copyArray;\n","/** Used to detect hot functions by number of calls within a span of milliseconds. */\nvar HOT_COUNT = 800,\n HOT_SPAN = 16;\n\n/* Built-in method references for those with the same name as other `lodash` methods. */\nvar nativeNow = Date.now;\n\n/**\n * Creates a function that'll short out and invoke `identity` instead\n * of `func` when it's called `HOT_COUNT` or more times in `HOT_SPAN`\n * milliseconds.\n *\n * @private\n * @param {Function} func The function to restrict.\n * @returns {Function} Returns the new shortable function.\n */\nfunction shortOut(func) {\n var count = 0,\n lastCalled = 0;\n\n return function() {\n var stamp = nativeNow(),\n remaining = HOT_SPAN - (stamp - lastCalled);\n\n lastCalled = stamp;\n if (remaining > 0) {\n if (++count >= HOT_COUNT) {\n return arguments[0];\n }\n } else {\n count = 0;\n }\n return func.apply(undefined, arguments);\n };\n}\n\nexport default shortOut;\n","/**\n * Creates a function that returns `value`.\n *\n * @static\n * @memberOf _\n * @since 2.4.0\n * @category Util\n * @param {*} value The value to return from the new function.\n * @returns {Function} Returns the new constant function.\n * @example\n *\n * var objects = _.times(2, _.constant({ 'a': 1 }));\n *\n * console.log(objects);\n * // => [{ 'a': 1 }, { 'a': 1 }]\n *\n * console.log(objects[0] === objects[1]);\n * // => true\n */\nfunction constant(value) {\n return function() {\n return value;\n };\n}\n\nexport default constant;\n","import getNative from './_getNative.js';\n\nvar defineProperty = (function() {\n try {\n var func = getNative(Object, 'defineProperty');\n func({}, '', {});\n return func;\n } catch (e) {}\n}());\n\nexport default defineProperty;\n","import constant from './constant.js';\nimport defineProperty from './_defineProperty.js';\nimport identity from './identity.js';\n\n/**\n * The base implementation of `setToString` without support for hot loop shorting.\n *\n * @private\n * @param {Function} func The function to modify.\n * @param {Function} string The `toString` result.\n * @returns {Function} Returns `func`.\n */\nvar baseSetToString = !defineProperty ? identity : function(func, string) {\n return defineProperty(func, 'toString', {\n 'configurable': true,\n 'enumerable': false,\n 'value': constant(string),\n 'writable': true\n });\n};\n\nexport default baseSetToString;\n","import baseSetToString from './_baseSetToString.js';\nimport shortOut from './_shortOut.js';\n\n/**\n * Sets the `toString` method of `func` to return `string`.\n *\n * @private\n * @param {Function} func The function to modify.\n * @param {Function} string The `toString` result.\n * @returns {Function} Returns `func`.\n */\nvar setToString = shortOut(baseSetToString);\n\nexport default setToString;\n","/**\n * A specialized version of `_.forEach` for arrays without support for\n * iteratee shorthands.\n *\n * @private\n * @param {Array} [array] The array to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @returns {Array} Returns `array`.\n */\nfunction arrayEach(array, iteratee) {\n var index = -1,\n length = array == null ? 0 : array.length;\n\n while (++index < length) {\n if (iteratee(array[index], index, array) === false) {\n break;\n }\n }\n return array;\n}\n\nexport default arrayEach;\n","/**\n * The base implementation of `_.findIndex` and `_.findLastIndex` without\n * support for iteratee shorthands.\n *\n * @private\n * @param {Array} array The array to inspect.\n * @param {Function} predicate The function invoked per iteration.\n * @param {number} fromIndex The index to search from.\n * @param {boolean} [fromRight] Specify iterating from right to left.\n * @returns {number} Returns the index of the matched value, else `-1`.\n */\nfunction baseFindIndex(array, predicate, fromIndex, fromRight) {\n var length = array.length,\n index = fromIndex + (fromRight ? 1 : -1);\n\n while ((fromRight ? index-- : ++index < length)) {\n if (predicate(array[index], index, array)) {\n return index;\n }\n }\n return -1;\n}\n\nexport default baseFindIndex;\n","/**\n * The base implementation of `_.isNaN` without support for number objects.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`.\n */\nfunction baseIsNaN(value) {\n return value !== value;\n}\n\nexport default baseIsNaN;\n","/**\n * A specialized version of `_.indexOf` which performs strict equality\n * comparisons of values, i.e. `===`.\n *\n * @private\n * @param {Array} array The array to inspect.\n * @param {*} value The value to search for.\n * @param {number} fromIndex The index to search from.\n * @returns {number} Returns the index of the matched value, else `-1`.\n */\nfunction strictIndexOf(array, value, fromIndex) {\n var index = fromIndex - 1,\n length = array.length;\n\n while (++index < length) {\n if (array[index] === value) {\n return index;\n }\n }\n return -1;\n}\n\nexport default strictIndexOf;\n","import baseFindIndex from './_baseFindIndex.js';\nimport baseIsNaN from './_baseIsNaN.js';\nimport strictIndexOf from './_strictIndexOf.js';\n\n/**\n * The base implementation of `_.indexOf` without `fromIndex` bounds checks.\n *\n * @private\n * @param {Array} array The array to inspect.\n * @param {*} value The value to search for.\n * @param {number} fromIndex The index to search from.\n * @returns {number} Returns the index of the matched value, else `-1`.\n */\nfunction baseIndexOf(array, value, fromIndex) {\n return value === value\n ? strictIndexOf(array, value, fromIndex)\n : baseFindIndex(array, baseIsNaN, fromIndex);\n}\n\nexport default baseIndexOf;\n","import baseIndexOf from './_baseIndexOf.js';\n\n/**\n * A specialized version of `_.includes` for arrays without support for\n * specifying an index to search from.\n *\n * @private\n * @param {Array} [array] The array to inspect.\n * @param {*} target The value to search for.\n * @returns {boolean} Returns `true` if `target` is found, else `false`.\n */\nfunction arrayIncludes(array, value) {\n var length = array == null ? 0 : array.length;\n return !!length && baseIndexOf(array, value, 0) > -1;\n}\n\nexport default arrayIncludes;\n","/** Used as references for various `Number` constants. */\nvar MAX_SAFE_INTEGER = 9007199254740991;\n\n/** Used to detect unsigned integer values. */\nvar reIsUint = /^(?:0|[1-9]\\d*)$/;\n\n/**\n * Checks if `value` is a valid array-like index.\n *\n * @private\n * @param {*} value The value to check.\n * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index.\n * @returns {boolean} Returns `true` if `value` is a valid index, else `false`.\n */\nfunction isIndex(value, length) {\n var type = typeof value;\n length = length == null ? MAX_SAFE_INTEGER : length;\n\n return !!length &&\n (type == 'number' ||\n (type != 'symbol' && reIsUint.test(value))) &&\n (value > -1 && value % 1 == 0 && value < length);\n}\n\nexport default isIndex;\n","import defineProperty from './_defineProperty.js';\n\n/**\n * The base implementation of `assignValue` and `assignMergeValue` without\n * value checks.\n *\n * @private\n * @param {Object} object The object to modify.\n * @param {string} key The key of the property to assign.\n * @param {*} value The value to assign.\n */\nfunction baseAssignValue(object, key, value) {\n if (key == '__proto__' && defineProperty) {\n defineProperty(object, key, {\n 'configurable': true,\n 'enumerable': true,\n 'value': value,\n 'writable': true\n });\n } else {\n object[key] = value;\n }\n}\n\nexport default baseAssignValue;\n","/**\n * Performs a\n * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)\n * comparison between two values to determine if they are equivalent.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to compare.\n * @param {*} other The other value to compare.\n * @returns {boolean} Returns `true` if the values are equivalent, else `false`.\n * @example\n *\n * var object = { 'a': 1 };\n * var other = { 'a': 1 };\n *\n * _.eq(object, object);\n * // => true\n *\n * _.eq(object, other);\n * // => false\n *\n * _.eq('a', 'a');\n * // => true\n *\n * _.eq('a', Object('a'));\n * // => false\n *\n * _.eq(NaN, NaN);\n * // => true\n */\nfunction eq(value, other) {\n return value === other || (value !== value && other !== other);\n}\n\nexport default eq;\n","import baseAssignValue from './_baseAssignValue.js';\nimport eq from './eq.js';\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * Assigns `value` to `key` of `object` if the existing value is not equivalent\n * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)\n * for equality comparisons.\n *\n * @private\n * @param {Object} object The object to modify.\n * @param {string} key The key of the property to assign.\n * @param {*} value The value to assign.\n */\nfunction assignValue(object, key, value) {\n var objValue = object[key];\n if (!(hasOwnProperty.call(object, key) && eq(objValue, value)) ||\n (value === undefined && !(key in object))) {\n baseAssignValue(object, key, value);\n }\n}\n\nexport default assignValue;\n","import assignValue from './_assignValue.js';\nimport baseAssignValue from './_baseAssignValue.js';\n\n/**\n * Copies properties of `source` to `object`.\n *\n * @private\n * @param {Object} source The object to copy properties from.\n * @param {Array} props The property identifiers to copy.\n * @param {Object} [object={}] The object to copy properties to.\n * @param {Function} [customizer] The function to customize copied values.\n * @returns {Object} Returns `object`.\n */\nfunction copyObject(source, props, object, customizer) {\n var isNew = !object;\n object || (object = {});\n\n var index = -1,\n length = props.length;\n\n while (++index < length) {\n var key = props[index];\n\n var newValue = customizer\n ? customizer(object[key], source[key], key, object, source)\n : undefined;\n\n if (newValue === undefined) {\n newValue = source[key];\n }\n if (isNew) {\n baseAssignValue(object, key, newValue);\n } else {\n assignValue(object, key, newValue);\n }\n }\n return object;\n}\n\nexport default copyObject;\n","import apply from './_apply.js';\n\n/* Built-in method references for those with the same name as other `lodash` methods. */\nvar nativeMax = Math.max;\n\n/**\n * A specialized version of `baseRest` which transforms the rest array.\n *\n * @private\n * @param {Function} func The function to apply a rest parameter to.\n * @param {number} [start=func.length-1] The start position of the rest parameter.\n * @param {Function} transform The rest array transform.\n * @returns {Function} Returns the new function.\n */\nfunction overRest(func, start, transform) {\n start = nativeMax(start === undefined ? (func.length - 1) : start, 0);\n return function() {\n var args = arguments,\n index = -1,\n length = nativeMax(args.length - start, 0),\n array = Array(length);\n\n while (++index < length) {\n array[index] = args[start + index];\n }\n index = -1;\n var otherArgs = Array(start + 1);\n while (++index < start) {\n otherArgs[index] = args[index];\n }\n otherArgs[start] = transform(array);\n return apply(func, this, otherArgs);\n };\n}\n\nexport default overRest;\n","import identity from './identity.js';\nimport overRest from './_overRest.js';\nimport setToString from './_setToString.js';\n\n/**\n * The base implementation of `_.rest` which doesn't validate or coerce arguments.\n *\n * @private\n * @param {Function} func The function to apply a rest parameter to.\n * @param {number} [start=func.length-1] The start position of the rest parameter.\n * @returns {Function} Returns the new function.\n */\nfunction baseRest(func, start) {\n return setToString(overRest(func, start, identity), func + '');\n}\n\nexport default baseRest;\n","/** Used as references for various `Number` constants. */\nvar MAX_SAFE_INTEGER = 9007199254740991;\n\n/**\n * Checks if `value` is a valid array-like length.\n *\n * **Note:** This method is loosely based on\n * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.\n * @example\n *\n * _.isLength(3);\n * // => true\n *\n * _.isLength(Number.MIN_VALUE);\n * // => false\n *\n * _.isLength(Infinity);\n * // => false\n *\n * _.isLength('3');\n * // => false\n */\nfunction isLength(value) {\n return typeof value == 'number' &&\n value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;\n}\n\nexport default isLength;\n","import isFunction from './isFunction.js';\nimport isLength from './isLength.js';\n\n/**\n * Checks if `value` is array-like. A value is considered array-like if it's\n * not a function and has a `value.length` that's an integer greater than or\n * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is array-like, else `false`.\n * @example\n *\n * _.isArrayLike([1, 2, 3]);\n * // => true\n *\n * _.isArrayLike(document.body.children);\n * // => true\n *\n * _.isArrayLike('abc');\n * // => true\n *\n * _.isArrayLike(_.noop);\n * // => false\n */\nfunction isArrayLike(value) {\n return value != null && isLength(value.length) && !isFunction(value);\n}\n\nexport default isArrayLike;\n","import eq from './eq.js';\nimport isArrayLike from './isArrayLike.js';\nimport isIndex from './_isIndex.js';\nimport isObject from './isObject.js';\n\n/**\n * Checks if the given arguments are from an iteratee call.\n *\n * @private\n * @param {*} value The potential iteratee value argument.\n * @param {*} index The potential iteratee index or key argument.\n * @param {*} object The potential iteratee object argument.\n * @returns {boolean} Returns `true` if the arguments are from an iteratee call,\n * else `false`.\n */\nfunction isIterateeCall(value, index, object) {\n if (!isObject(object)) {\n return false;\n }\n var type = typeof index;\n if (type == 'number'\n ? (isArrayLike(object) && isIndex(index, object.length))\n : (type == 'string' && index in object)\n ) {\n return eq(object[index], value);\n }\n return false;\n}\n\nexport default isIterateeCall;\n","import baseRest from './_baseRest.js';\nimport isIterateeCall from './_isIterateeCall.js';\n\n/**\n * Creates a function like `_.assign`.\n *\n * @private\n * @param {Function} assigner The function to assign values.\n * @returns {Function} Returns the new assigner function.\n */\nfunction createAssigner(assigner) {\n return baseRest(function(object, sources) {\n var index = -1,\n length = sources.length,\n customizer = length > 1 ? sources[length - 1] : undefined,\n guard = length > 2 ? sources[2] : undefined;\n\n customizer = (assigner.length > 3 && typeof customizer == 'function')\n ? (length--, customizer)\n : undefined;\n\n if (guard && isIterateeCall(sources[0], sources[1], guard)) {\n customizer = length < 3 ? undefined : customizer;\n length = 1;\n }\n object = Object(object);\n while (++index < length) {\n var source = sources[index];\n if (source) {\n assigner(object, source, index, customizer);\n }\n }\n return object;\n });\n}\n\nexport default createAssigner;\n","/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/**\n * Checks if `value` is likely a prototype object.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a prototype, else `false`.\n */\nfunction isPrototype(value) {\n var Ctor = value && value.constructor,\n proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto;\n\n return value === proto;\n}\n\nexport default isPrototype;\n","/**\n * The base implementation of `_.times` without support for iteratee shorthands\n * or max array length checks.\n *\n * @private\n * @param {number} n The number of times to invoke `iteratee`.\n * @param {Function} iteratee The function invoked per iteration.\n * @returns {Array} Returns the array of results.\n */\nfunction baseTimes(n, iteratee) {\n var index = -1,\n result = Array(n);\n\n while (++index < n) {\n result[index] = iteratee(index);\n }\n return result;\n}\n\nexport default baseTimes;\n","import baseGetTag from './_baseGetTag.js';\nimport isObjectLike from './isObjectLike.js';\n\n/** `Object#toString` result references. */\nvar argsTag = '[object Arguments]';\n\n/**\n * The base implementation of `_.isArguments`.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an `arguments` object,\n */\nfunction baseIsArguments(value) {\n return isObjectLike(value) && baseGetTag(value) == argsTag;\n}\n\nexport default baseIsArguments;\n","import baseIsArguments from './_baseIsArguments.js';\nimport isObjectLike from './isObjectLike.js';\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/** Built-in value references. */\nvar propertyIsEnumerable = objectProto.propertyIsEnumerable;\n\n/**\n * Checks if `value` is likely an `arguments` object.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an `arguments` object,\n * else `false`.\n * @example\n *\n * _.isArguments(function() { return arguments; }());\n * // => true\n *\n * _.isArguments([1, 2, 3]);\n * // => false\n */\nvar isArguments = baseIsArguments(function() { return arguments; }()) ? baseIsArguments : function(value) {\n return isObjectLike(value) && hasOwnProperty.call(value, 'callee') &&\n !propertyIsEnumerable.call(value, 'callee');\n};\n\nexport default isArguments;\n","/**\n * This method returns `false`.\n *\n * @static\n * @memberOf _\n * @since 4.13.0\n * @category Util\n * @returns {boolean} Returns `false`.\n * @example\n *\n * _.times(2, _.stubFalse);\n * // => [false, false]\n */\nfunction stubFalse() {\n return false;\n}\n\nexport default stubFalse;\n","import root from './_root.js';\nimport stubFalse from './stubFalse.js';\n\n/** Detect free variable `exports`. */\nvar freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports;\n\n/** Detect free variable `module`. */\nvar freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module;\n\n/** Detect the popular CommonJS extension `module.exports`. */\nvar moduleExports = freeModule && freeModule.exports === freeExports;\n\n/** Built-in value references. */\nvar Buffer = moduleExports ? root.Buffer : undefined;\n\n/* Built-in method references for those with the same name as other `lodash` methods. */\nvar nativeIsBuffer = Buffer ? Buffer.isBuffer : undefined;\n\n/**\n * Checks if `value` is a buffer.\n *\n * @static\n * @memberOf _\n * @since 4.3.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a buffer, else `false`.\n * @example\n *\n * _.isBuffer(new Buffer(2));\n * // => true\n *\n * _.isBuffer(new Uint8Array(2));\n * // => false\n */\nvar isBuffer = nativeIsBuffer || stubFalse;\n\nexport default isBuffer;\n","import baseGetTag from './_baseGetTag.js';\nimport isLength from './isLength.js';\nimport isObjectLike from './isObjectLike.js';\n\n/** `Object#toString` result references. */\nvar argsTag = '[object Arguments]',\n arrayTag = '[object Array]',\n boolTag = '[object Boolean]',\n dateTag = '[object Date]',\n errorTag = '[object Error]',\n funcTag = '[object Function]',\n mapTag = '[object Map]',\n numberTag = '[object Number]',\n objectTag = '[object Object]',\n regexpTag = '[object RegExp]',\n setTag = '[object Set]',\n stringTag = '[object String]',\n weakMapTag = '[object WeakMap]';\n\nvar arrayBufferTag = '[object ArrayBuffer]',\n dataViewTag = '[object DataView]',\n float32Tag = '[object Float32Array]',\n float64Tag = '[object Float64Array]',\n int8Tag = '[object Int8Array]',\n int16Tag = '[object Int16Array]',\n int32Tag = '[object Int32Array]',\n uint8Tag = '[object Uint8Array]',\n uint8ClampedTag = '[object Uint8ClampedArray]',\n uint16Tag = '[object Uint16Array]',\n uint32Tag = '[object Uint32Array]';\n\n/** Used to identify `toStringTag` values of typed arrays. */\nvar typedArrayTags = {};\ntypedArrayTags[float32Tag] = typedArrayTags[float64Tag] =\ntypedArrayTags[int8Tag] = typedArrayTags[int16Tag] =\ntypedArrayTags[int32Tag] = typedArrayTags[uint8Tag] =\ntypedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] =\ntypedArrayTags[uint32Tag] = true;\ntypedArrayTags[argsTag] = typedArrayTags[arrayTag] =\ntypedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] =\ntypedArrayTags[dataViewTag] = typedArrayTags[dateTag] =\ntypedArrayTags[errorTag] = typedArrayTags[funcTag] =\ntypedArrayTags[mapTag] = typedArrayTags[numberTag] =\ntypedArrayTags[objectTag] = typedArrayTags[regexpTag] =\ntypedArrayTags[setTag] = typedArrayTags[stringTag] =\ntypedArrayTags[weakMapTag] = false;\n\n/**\n * The base implementation of `_.isTypedArray` without Node.js optimizations.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a typed array, else `false`.\n */\nfunction baseIsTypedArray(value) {\n return isObjectLike(value) &&\n isLength(value.length) && !!typedArrayTags[baseGetTag(value)];\n}\n\nexport default baseIsTypedArray;\n","/**\n * The base implementation of `_.unary` without support for storing metadata.\n *\n * @private\n * @param {Function} func The function to cap arguments for.\n * @returns {Function} Returns the new capped function.\n */\nfunction baseUnary(func) {\n return function(value) {\n return func(value);\n };\n}\n\nexport default baseUnary;\n","import freeGlobal from './_freeGlobal.js';\n\n/** Detect free variable `exports`. */\nvar freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports;\n\n/** Detect free variable `module`. */\nvar freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module;\n\n/** Detect the popular CommonJS extension `module.exports`. */\nvar moduleExports = freeModule && freeModule.exports === freeExports;\n\n/** Detect free variable `process` from Node.js. */\nvar freeProcess = moduleExports && freeGlobal.process;\n\n/** Used to access faster Node.js helpers. */\nvar nodeUtil = (function() {\n try {\n // Use `util.types` for Node.js 10+.\n var types = freeModule && freeModule.require && freeModule.require('util').types;\n\n if (types) {\n return types;\n }\n\n // Legacy `process.binding('util')` for Node.js < 10.\n return freeProcess && freeProcess.binding && freeProcess.binding('util');\n } catch (e) {}\n}());\n\nexport default nodeUtil;\n","import baseIsTypedArray from './_baseIsTypedArray.js';\nimport baseUnary from './_baseUnary.js';\nimport nodeUtil from './_nodeUtil.js';\n\n/* Node.js helper references. */\nvar nodeIsTypedArray = nodeUtil && nodeUtil.isTypedArray;\n\n/**\n * Checks if `value` is classified as a typed array.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a typed array, else `false`.\n * @example\n *\n * _.isTypedArray(new Uint8Array);\n * // => true\n *\n * _.isTypedArray([]);\n * // => false\n */\nvar isTypedArray = nodeIsTypedArray ? baseUnary(nodeIsTypedArray) : baseIsTypedArray;\n\nexport default isTypedArray;\n","import baseTimes from './_baseTimes.js';\nimport isArguments from './isArguments.js';\nimport isArray from './isArray.js';\nimport isBuffer from './isBuffer.js';\nimport isIndex from './_isIndex.js';\nimport isTypedArray from './isTypedArray.js';\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * Creates an array of the enumerable property names of the array-like `value`.\n *\n * @private\n * @param {*} value The value to query.\n * @param {boolean} inherited Specify returning inherited property names.\n * @returns {Array} Returns the array of property names.\n */\nfunction arrayLikeKeys(value, inherited) {\n var isArr = isArray(value),\n isArg = !isArr && isArguments(value),\n isBuff = !isArr && !isArg && isBuffer(value),\n isType = !isArr && !isArg && !isBuff && isTypedArray(value),\n skipIndexes = isArr || isArg || isBuff || isType,\n result = skipIndexes ? baseTimes(value.length, String) : [],\n length = result.length;\n\n for (var key in value) {\n if ((inherited || hasOwnProperty.call(value, key)) &&\n !(skipIndexes && (\n // Safari 9 has enumerable `arguments.length` in strict mode.\n key == 'length' ||\n // Node.js 0.10 has enumerable non-index properties on buffers.\n (isBuff && (key == 'offset' || key == 'parent')) ||\n // PhantomJS 2 has enumerable non-index properties on typed arrays.\n (isType && (key == 'buffer' || key == 'byteLength' || key == 'byteOffset')) ||\n // Skip index properties.\n isIndex(key, length)\n ))) {\n result.push(key);\n }\n }\n return result;\n}\n\nexport default arrayLikeKeys;\n","/**\n * Creates a unary function that invokes `func` with its argument transformed.\n *\n * @private\n * @param {Function} func The function to wrap.\n * @param {Function} transform The argument transform.\n * @returns {Function} Returns the new function.\n */\nfunction overArg(func, transform) {\n return function(arg) {\n return func(transform(arg));\n };\n}\n\nexport default overArg;\n","import overArg from './_overArg.js';\n\n/* Built-in method references for those with the same name as other `lodash` methods. */\nvar nativeKeys = overArg(Object.keys, Object);\n\nexport default nativeKeys;\n","import isPrototype from './_isPrototype.js';\nimport nativeKeys from './_nativeKeys.js';\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * The base implementation of `_.keys` which doesn't treat sparse arrays as dense.\n *\n * @private\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of property names.\n */\nfunction baseKeys(object) {\n if (!isPrototype(object)) {\n return nativeKeys(object);\n }\n var result = [];\n for (var key in Object(object)) {\n if (hasOwnProperty.call(object, key) && key != 'constructor') {\n result.push(key);\n }\n }\n return result;\n}\n\nexport default baseKeys;\n","import arrayLikeKeys from './_arrayLikeKeys.js';\nimport baseKeys from './_baseKeys.js';\nimport isArrayLike from './isArrayLike.js';\n\n/**\n * Creates an array of the own enumerable property names of `object`.\n *\n * **Note:** Non-object values are coerced to objects. See the\n * [ES spec](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)\n * for more details.\n *\n * @static\n * @since 0.1.0\n * @memberOf _\n * @category Object\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of property names.\n * @example\n *\n * function Foo() {\n * this.a = 1;\n * this.b = 2;\n * }\n *\n * Foo.prototype.c = 3;\n *\n * _.keys(new Foo);\n * // => ['a', 'b'] (iteration order is not guaranteed)\n *\n * _.keys('hi');\n * // => ['0', '1']\n */\nfunction keys(object) {\n return isArrayLike(object) ? arrayLikeKeys(object) : baseKeys(object);\n}\n\nexport default keys;\n","/**\n * This function is like\n * [`Object.keys`](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)\n * except that it includes inherited enumerable properties.\n *\n * @private\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of property names.\n */\nfunction nativeKeysIn(object) {\n var result = [];\n if (object != null) {\n for (var key in Object(object)) {\n result.push(key);\n }\n }\n return result;\n}\n\nexport default nativeKeysIn;\n","import isObject from './isObject.js';\nimport isPrototype from './_isPrototype.js';\nimport nativeKeysIn from './_nativeKeysIn.js';\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * The base implementation of `_.keysIn` which doesn't treat sparse arrays as dense.\n *\n * @private\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of property names.\n */\nfunction baseKeysIn(object) {\n if (!isObject(object)) {\n return nativeKeysIn(object);\n }\n var isProto = isPrototype(object),\n result = [];\n\n for (var key in object) {\n if (!(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) {\n result.push(key);\n }\n }\n return result;\n}\n\nexport default baseKeysIn;\n","import arrayLikeKeys from './_arrayLikeKeys.js';\nimport baseKeysIn from './_baseKeysIn.js';\nimport isArrayLike from './isArrayLike.js';\n\n/**\n * Creates an array of the own and inherited enumerable property names of `object`.\n *\n * **Note:** Non-object values are coerced to objects.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Object\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of property names.\n * @example\n *\n * function Foo() {\n * this.a = 1;\n * this.b = 2;\n * }\n *\n * Foo.prototype.c = 3;\n *\n * _.keysIn(new Foo);\n * // => ['a', 'b', 'c'] (iteration order is not guaranteed)\n */\nfunction keysIn(object) {\n return isArrayLike(object) ? arrayLikeKeys(object, true) : baseKeysIn(object);\n}\n\nexport default keysIn;\n","import isArray from './isArray.js';\nimport isSymbol from './isSymbol.js';\n\n/** Used to match property names within property paths. */\nvar reIsDeepProp = /\\.|\\[(?:[^[\\]]*|([\"'])(?:(?!\\1)[^\\\\]|\\\\.)*?\\1)\\]/,\n reIsPlainProp = /^\\w*$/;\n\n/**\n * Checks if `value` is a property name and not a property path.\n *\n * @private\n * @param {*} value The value to check.\n * @param {Object} [object] The object to query keys on.\n * @returns {boolean} Returns `true` if `value` is a property name, else `false`.\n */\nfunction isKey(value, object) {\n if (isArray(value)) {\n return false;\n }\n var type = typeof value;\n if (type == 'number' || type == 'symbol' || type == 'boolean' ||\n value == null || isSymbol(value)) {\n return true;\n }\n return reIsPlainProp.test(value) || !reIsDeepProp.test(value) ||\n (object != null && value in Object(object));\n}\n\nexport default isKey;\n","import getNative from './_getNative.js';\n\n/* Built-in method references that are verified to be native. */\nvar nativeCreate = getNative(Object, 'create');\n\nexport default nativeCreate;\n","import nativeCreate from './_nativeCreate.js';\n\n/**\n * Removes all key-value entries from the hash.\n *\n * @private\n * @name clear\n * @memberOf Hash\n */\nfunction hashClear() {\n this.__data__ = nativeCreate ? nativeCreate(null) : {};\n this.size = 0;\n}\n\nexport default hashClear;\n","/**\n * Removes `key` and its value from the hash.\n *\n * @private\n * @name delete\n * @memberOf Hash\n * @param {Object} hash The hash to modify.\n * @param {string} key The key of the value to remove.\n * @returns {boolean} Returns `true` if the entry was removed, else `false`.\n */\nfunction hashDelete(key) {\n var result = this.has(key) && delete this.__data__[key];\n this.size -= result ? 1 : 0;\n return result;\n}\n\nexport default hashDelete;\n","import nativeCreate from './_nativeCreate.js';\n\n/** Used to stand-in for `undefined` hash values. */\nvar HASH_UNDEFINED = '__lodash_hash_undefined__';\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * Gets the hash value for `key`.\n *\n * @private\n * @name get\n * @memberOf Hash\n * @param {string} key The key of the value to get.\n * @returns {*} Returns the entry value.\n */\nfunction hashGet(key) {\n var data = this.__data__;\n if (nativeCreate) {\n var result = data[key];\n return result === HASH_UNDEFINED ? undefined : result;\n }\n return hasOwnProperty.call(data, key) ? data[key] : undefined;\n}\n\nexport default hashGet;\n","import nativeCreate from './_nativeCreate.js';\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * Checks if a hash value for `key` exists.\n *\n * @private\n * @name has\n * @memberOf Hash\n * @param {string} key The key of the entry to check.\n * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.\n */\nfunction hashHas(key) {\n var data = this.__data__;\n return nativeCreate ? (data[key] !== undefined) : hasOwnProperty.call(data, key);\n}\n\nexport default hashHas;\n","import nativeCreate from './_nativeCreate.js';\n\n/** Used to stand-in for `undefined` hash values. */\nvar HASH_UNDEFINED = '__lodash_hash_undefined__';\n\n/**\n * Sets the hash `key` to `value`.\n *\n * @private\n * @name set\n * @memberOf Hash\n * @param {string} key The key of the value to set.\n * @param {*} value The value to set.\n * @returns {Object} Returns the hash instance.\n */\nfunction hashSet(key, value) {\n var data = this.__data__;\n this.size += this.has(key) ? 0 : 1;\n data[key] = (nativeCreate && value === undefined) ? HASH_UNDEFINED : value;\n return this;\n}\n\nexport default hashSet;\n","import hashClear from './_hashClear.js';\nimport hashDelete from './_hashDelete.js';\nimport hashGet from './_hashGet.js';\nimport hashHas from './_hashHas.js';\nimport hashSet from './_hashSet.js';\n\n/**\n * Creates a hash object.\n *\n * @private\n * @constructor\n * @param {Array} [entries] The key-value pairs to cache.\n */\nfunction Hash(entries) {\n var index = -1,\n length = entries == null ? 0 : entries.length;\n\n this.clear();\n while (++index < length) {\n var entry = entries[index];\n this.set(entry[0], entry[1]);\n }\n}\n\n// Add methods to `Hash`.\nHash.prototype.clear = hashClear;\nHash.prototype['delete'] = hashDelete;\nHash.prototype.get = hashGet;\nHash.prototype.has = hashHas;\nHash.prototype.set = hashSet;\n\nexport default Hash;\n","/**\n * Removes all key-value entries from the list cache.\n *\n * @private\n * @name clear\n * @memberOf ListCache\n */\nfunction listCacheClear() {\n this.__data__ = [];\n this.size = 0;\n}\n\nexport default listCacheClear;\n","import eq from './eq.js';\n\n/**\n * Gets the index at which the `key` is found in `array` of key-value pairs.\n *\n * @private\n * @param {Array} array The array to inspect.\n * @param {*} key The key to search for.\n * @returns {number} Returns the index of the matched value, else `-1`.\n */\nfunction assocIndexOf(array, key) {\n var length = array.length;\n while (length--) {\n if (eq(array[length][0], key)) {\n return length;\n }\n }\n return -1;\n}\n\nexport default assocIndexOf;\n","import assocIndexOf from './_assocIndexOf.js';\n\n/** Used for built-in method references. */\nvar arrayProto = Array.prototype;\n\n/** Built-in value references. */\nvar splice = arrayProto.splice;\n\n/**\n * Removes `key` and its value from the list cache.\n *\n * @private\n * @name delete\n * @memberOf ListCache\n * @param {string} key The key of the value to remove.\n * @returns {boolean} Returns `true` if the entry was removed, else `false`.\n */\nfunction listCacheDelete(key) {\n var data = this.__data__,\n index = assocIndexOf(data, key);\n\n if (index < 0) {\n return false;\n }\n var lastIndex = data.length - 1;\n if (index == lastIndex) {\n data.pop();\n } else {\n splice.call(data, index, 1);\n }\n --this.size;\n return true;\n}\n\nexport default listCacheDelete;\n","import assocIndexOf from './_assocIndexOf.js';\n\n/**\n * Gets the list cache value for `key`.\n *\n * @private\n * @name get\n * @memberOf ListCache\n * @param {string} key The key of the value to get.\n * @returns {*} Returns the entry value.\n */\nfunction listCacheGet(key) {\n var data = this.__data__,\n index = assocIndexOf(data, key);\n\n return index < 0 ? undefined : data[index][1];\n}\n\nexport default listCacheGet;\n","import assocIndexOf from './_assocIndexOf.js';\n\n/**\n * Checks if a list cache value for `key` exists.\n *\n * @private\n * @name has\n * @memberOf ListCache\n * @param {string} key The key of the entry to check.\n * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.\n */\nfunction listCacheHas(key) {\n return assocIndexOf(this.__data__, key) > -1;\n}\n\nexport default listCacheHas;\n","import assocIndexOf from './_assocIndexOf.js';\n\n/**\n * Sets the list cache `key` to `value`.\n *\n * @private\n * @name set\n * @memberOf ListCache\n * @param {string} key The key of the value to set.\n * @param {*} value The value to set.\n * @returns {Object} Returns the list cache instance.\n */\nfunction listCacheSet(key, value) {\n var data = this.__data__,\n index = assocIndexOf(data, key);\n\n if (index < 0) {\n ++this.size;\n data.push([key, value]);\n } else {\n data[index][1] = value;\n }\n return this;\n}\n\nexport default listCacheSet;\n","import listCacheClear from './_listCacheClear.js';\nimport listCacheDelete from './_listCacheDelete.js';\nimport listCacheGet from './_listCacheGet.js';\nimport listCacheHas from './_listCacheHas.js';\nimport listCacheSet from './_listCacheSet.js';\n\n/**\n * Creates an list cache object.\n *\n * @private\n * @constructor\n * @param {Array} [entries] The key-value pairs to cache.\n */\nfunction ListCache(entries) {\n var index = -1,\n length = entries == null ? 0 : entries.length;\n\n this.clear();\n while (++index < length) {\n var entry = entries[index];\n this.set(entry[0], entry[1]);\n }\n}\n\n// Add methods to `ListCache`.\nListCache.prototype.clear = listCacheClear;\nListCache.prototype['delete'] = listCacheDelete;\nListCache.prototype.get = listCacheGet;\nListCache.prototype.has = listCacheHas;\nListCache.prototype.set = listCacheSet;\n\nexport default ListCache;\n","import getNative from './_getNative.js';\nimport root from './_root.js';\n\n/* Built-in method references that are verified to be native. */\nvar Map = getNative(root, 'Map');\n\nexport default Map;\n","import Hash from './_Hash.js';\nimport ListCache from './_ListCache.js';\nimport Map from './_Map.js';\n\n/**\n * Removes all key-value entries from the map.\n *\n * @private\n * @name clear\n * @memberOf MapCache\n */\nfunction mapCacheClear() {\n this.size = 0;\n this.__data__ = {\n 'hash': new Hash,\n 'map': new (Map || ListCache),\n 'string': new Hash\n };\n}\n\nexport default mapCacheClear;\n","/**\n * Checks if `value` is suitable for use as unique object key.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is suitable, else `false`.\n */\nfunction isKeyable(value) {\n var type = typeof value;\n return (type == 'string' || type == 'number' || type == 'symbol' || type == 'boolean')\n ? (value !== '__proto__')\n : (value === null);\n}\n\nexport default isKeyable;\n","import isKeyable from './_isKeyable.js';\n\n/**\n * Gets the data for `map`.\n *\n * @private\n * @param {Object} map The map to query.\n * @param {string} key The reference key.\n * @returns {*} Returns the map data.\n */\nfunction getMapData(map, key) {\n var data = map.__data__;\n return isKeyable(key)\n ? data[typeof key == 'string' ? 'string' : 'hash']\n : data.map;\n}\n\nexport default getMapData;\n","import getMapData from './_getMapData.js';\n\n/**\n * Removes `key` and its value from the map.\n *\n * @private\n * @name delete\n * @memberOf MapCache\n * @param {string} key The key of the value to remove.\n * @returns {boolean} Returns `true` if the entry was removed, else `false`.\n */\nfunction mapCacheDelete(key) {\n var result = getMapData(this, key)['delete'](key);\n this.size -= result ? 1 : 0;\n return result;\n}\n\nexport default mapCacheDelete;\n","import getMapData from './_getMapData.js';\n\n/**\n * Gets the map value for `key`.\n *\n * @private\n * @name get\n * @memberOf MapCache\n * @param {string} key The key of the value to get.\n * @returns {*} Returns the entry value.\n */\nfunction mapCacheGet(key) {\n return getMapData(this, key).get(key);\n}\n\nexport default mapCacheGet;\n","import getMapData from './_getMapData.js';\n\n/**\n * Checks if a map value for `key` exists.\n *\n * @private\n * @name has\n * @memberOf MapCache\n * @param {string} key The key of the entry to check.\n * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.\n */\nfunction mapCacheHas(key) {\n return getMapData(this, key).has(key);\n}\n\nexport default mapCacheHas;\n","import getMapData from './_getMapData.js';\n\n/**\n * Sets the map `key` to `value`.\n *\n * @private\n * @name set\n * @memberOf MapCache\n * @param {string} key The key of the value to set.\n * @param {*} value The value to set.\n * @returns {Object} Returns the map cache instance.\n */\nfunction mapCacheSet(key, value) {\n var data = getMapData(this, key),\n size = data.size;\n\n data.set(key, value);\n this.size += data.size == size ? 0 : 1;\n return this;\n}\n\nexport default mapCacheSet;\n","import mapCacheClear from './_mapCacheClear.js';\nimport mapCacheDelete from './_mapCacheDelete.js';\nimport mapCacheGet from './_mapCacheGet.js';\nimport mapCacheHas from './_mapCacheHas.js';\nimport mapCacheSet from './_mapCacheSet.js';\n\n/**\n * Creates a map cache object to store key-value pairs.\n *\n * @private\n * @constructor\n * @param {Array} [entries] The key-value pairs to cache.\n */\nfunction MapCache(entries) {\n var index = -1,\n length = entries == null ? 0 : entries.length;\n\n this.clear();\n while (++index < length) {\n var entry = entries[index];\n this.set(entry[0], entry[1]);\n }\n}\n\n// Add methods to `MapCache`.\nMapCache.prototype.clear = mapCacheClear;\nMapCache.prototype['delete'] = mapCacheDelete;\nMapCache.prototype.get = mapCacheGet;\nMapCache.prototype.has = mapCacheHas;\nMapCache.prototype.set = mapCacheSet;\n\nexport default MapCache;\n","import MapCache from './_MapCache.js';\n\n/** Error message constants. */\nvar FUNC_ERROR_TEXT = 'Expected a function';\n\n/**\n * Creates a function that memoizes the result of `func`. If `resolver` is\n * provided, it determines the cache key for storing the result based on the\n * arguments provided to the memoized function. By default, the first argument\n * provided to the memoized function is used as the map cache key. The `func`\n * is invoked with the `this` binding of the memoized function.\n *\n * **Note:** The cache is exposed as the `cache` property on the memoized\n * function. Its creation may be customized by replacing the `_.memoize.Cache`\n * constructor with one whose instances implement the\n * [`Map`](http://ecma-international.org/ecma-262/7.0/#sec-properties-of-the-map-prototype-object)\n * method interface of `clear`, `delete`, `get`, `has`, and `set`.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Function\n * @param {Function} func The function to have its output memoized.\n * @param {Function} [resolver] The function to resolve the cache key.\n * @returns {Function} Returns the new memoized function.\n * @example\n *\n * var object = { 'a': 1, 'b': 2 };\n * var other = { 'c': 3, 'd': 4 };\n *\n * var values = _.memoize(_.values);\n * values(object);\n * // => [1, 2]\n *\n * values(other);\n * // => [3, 4]\n *\n * object.a = 2;\n * values(object);\n * // => [1, 2]\n *\n * // Modify the result cache.\n * values.cache.set(object, ['a', 'b']);\n * values(object);\n * // => ['a', 'b']\n *\n * // Replace `_.memoize.Cache`.\n * _.memoize.Cache = WeakMap;\n */\nfunction memoize(func, resolver) {\n if (typeof func != 'function' || (resolver != null && typeof resolver != 'function')) {\n throw new TypeError(FUNC_ERROR_TEXT);\n }\n var memoized = function() {\n var args = arguments,\n key = resolver ? resolver.apply(this, args) : args[0],\n cache = memoized.cache;\n\n if (cache.has(key)) {\n return cache.get(key);\n }\n var result = func.apply(this, args);\n memoized.cache = cache.set(key, result) || cache;\n return result;\n };\n memoized.cache = new (memoize.Cache || MapCache);\n return memoized;\n}\n\n// Expose `MapCache`.\nmemoize.Cache = MapCache;\n\nexport default memoize;\n","import memoize from './memoize.js';\n\n/** Used as the maximum memoize cache size. */\nvar MAX_MEMOIZE_SIZE = 500;\n\n/**\n * A specialized version of `_.memoize` which clears the memoized function's\n * cache when it exceeds `MAX_MEMOIZE_SIZE`.\n *\n * @private\n * @param {Function} func The function to have its output memoized.\n * @returns {Function} Returns the new memoized function.\n */\nfunction memoizeCapped(func) {\n var result = memoize(func, function(key) {\n if (cache.size === MAX_MEMOIZE_SIZE) {\n cache.clear();\n }\n return key;\n });\n\n var cache = result.cache;\n return result;\n}\n\nexport default memoizeCapped;\n","import memoizeCapped from './_memoizeCapped.js';\n\n/** Used to match property names within property paths. */\nvar rePropName = /[^.[\\]]+|\\[(?:(-?\\d+(?:\\.\\d+)?)|([\"'])((?:(?!\\2)[^\\\\]|\\\\.)*?)\\2)\\]|(?=(?:\\.|\\[\\])(?:\\.|\\[\\]|$))/g;\n\n/** Used to match backslashes in property paths. */\nvar reEscapeChar = /\\\\(\\\\)?/g;\n\n/**\n * Converts `string` to a property path array.\n *\n * @private\n * @param {string} string The string to convert.\n * @returns {Array} Returns the property path array.\n */\nvar stringToPath = memoizeCapped(function(string) {\n var result = [];\n if (string.charCodeAt(0) === 46 /* . */) {\n result.push('');\n }\n string.replace(rePropName, function(match, number, quote, subString) {\n result.push(quote ? subString.replace(reEscapeChar, '$1') : (number || match));\n });\n return result;\n});\n\nexport default stringToPath;\n","import baseToString from './_baseToString.js';\n\n/**\n * Converts `value` to a string. An empty string is returned for `null`\n * and `undefined` values. The sign of `-0` is preserved.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to convert.\n * @returns {string} Returns the converted string.\n * @example\n *\n * _.toString(null);\n * // => ''\n *\n * _.toString(-0);\n * // => '-0'\n *\n * _.toString([1, 2, 3]);\n * // => '1,2,3'\n */\nfunction toString(value) {\n return value == null ? '' : baseToString(value);\n}\n\nexport default toString;\n","import isArray from './isArray.js';\nimport isKey from './_isKey.js';\nimport stringToPath from './_stringToPath.js';\nimport toString from './toString.js';\n\n/**\n * Casts `value` to a path array if it's not one.\n *\n * @private\n * @param {*} value The value to inspect.\n * @param {Object} [object] The object to query keys on.\n * @returns {Array} Returns the cast property path array.\n */\nfunction castPath(value, object) {\n if (isArray(value)) {\n return value;\n }\n return isKey(value, object) ? [value] : stringToPath(toString(value));\n}\n\nexport default castPath;\n","import isSymbol from './isSymbol.js';\n\n/** Used as references for various `Number` constants. */\nvar INFINITY = 1 / 0;\n\n/**\n * Converts `value` to a string key if it's not a string or symbol.\n *\n * @private\n * @param {*} value The value to inspect.\n * @returns {string|symbol} Returns the key.\n */\nfunction toKey(value) {\n if (typeof value == 'string' || isSymbol(value)) {\n return value;\n }\n var result = (value + '');\n return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result;\n}\n\nexport default toKey;\n","import castPath from './_castPath.js';\nimport toKey from './_toKey.js';\n\n/**\n * The base implementation of `_.get` without support for default values.\n *\n * @private\n * @param {Object} object The object to query.\n * @param {Array|string} path The path of the property to get.\n * @returns {*} Returns the resolved value.\n */\nfunction baseGet(object, path) {\n path = castPath(path, object);\n\n var index = 0,\n length = path.length;\n\n while (object != null && index < length) {\n object = object[toKey(path[index++])];\n }\n return (index && index == length) ? object : undefined;\n}\n\nexport default baseGet;\n","import baseGet from './_baseGet.js';\n\n/**\n * Gets the value at `path` of `object`. If the resolved value is\n * `undefined`, the `defaultValue` is returned in its place.\n *\n * @static\n * @memberOf _\n * @since 3.7.0\n * @category Object\n * @param {Object} object The object to query.\n * @param {Array|string} path The path of the property to get.\n * @param {*} [defaultValue] The value returned for `undefined` resolved values.\n * @returns {*} Returns the resolved value.\n * @example\n *\n * var object = { 'a': [{ 'b': { 'c': 3 } }] };\n *\n * _.get(object, 'a[0].b.c');\n * // => 3\n *\n * _.get(object, ['a', '0', 'b', 'c']);\n * // => 3\n *\n * _.get(object, 'a.b.c', 'default');\n * // => 'default'\n */\nfunction get(object, path, defaultValue) {\n var result = object == null ? undefined : baseGet(object, path);\n return result === undefined ? defaultValue : result;\n}\n\nexport default get;\n","/**\n * Appends the elements of `values` to `array`.\n *\n * @private\n * @param {Array} array The array to modify.\n * @param {Array} values The values to append.\n * @returns {Array} Returns `array`.\n */\nfunction arrayPush(array, values) {\n var index = -1,\n length = values.length,\n offset = array.length;\n\n while (++index < length) {\n array[offset + index] = values[index];\n }\n return array;\n}\n\nexport default arrayPush;\n","import Symbol from './_Symbol.js';\nimport isArguments from './isArguments.js';\nimport isArray from './isArray.js';\n\n/** Built-in value references. */\nvar spreadableSymbol = Symbol ? Symbol.isConcatSpreadable : undefined;\n\n/**\n * Checks if `value` is a flattenable `arguments` object or array.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is flattenable, else `false`.\n */\nfunction isFlattenable(value) {\n return isArray(value) || isArguments(value) ||\n !!(spreadableSymbol && value && value[spreadableSymbol]);\n}\n\nexport default isFlattenable;\n","import arrayPush from './_arrayPush.js';\nimport isFlattenable from './_isFlattenable.js';\n\n/**\n * The base implementation of `_.flatten` with support for restricting flattening.\n *\n * @private\n * @param {Array} array The array to flatten.\n * @param {number} depth The maximum recursion depth.\n * @param {boolean} [predicate=isFlattenable] The function invoked per iteration.\n * @param {boolean} [isStrict] Restrict to values that pass `predicate` checks.\n * @param {Array} [result=[]] The initial result value.\n * @returns {Array} Returns the new flattened array.\n */\nfunction baseFlatten(array, depth, predicate, isStrict, result) {\n var index = -1,\n length = array.length;\n\n predicate || (predicate = isFlattenable);\n result || (result = []);\n\n while (++index < length) {\n var value = array[index];\n if (depth > 0 && predicate(value)) {\n if (depth > 1) {\n // Recursively flatten arrays (susceptible to call stack limits).\n baseFlatten(value, depth - 1, predicate, isStrict, result);\n } else {\n arrayPush(result, value);\n }\n } else if (!isStrict) {\n result[result.length] = value;\n }\n }\n return result;\n}\n\nexport default baseFlatten;\n","import baseFlatten from './_baseFlatten.js';\n\n/**\n * Flattens `array` a single level deep.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Array\n * @param {Array} array The array to flatten.\n * @returns {Array} Returns the new flattened array.\n * @example\n *\n * _.flatten([1, [2, [3, [4]], 5]]);\n * // => [1, 2, [3, [4]], 5]\n */\nfunction flatten(array) {\n var length = array == null ? 0 : array.length;\n return length ? baseFlatten(array, 1) : [];\n}\n\nexport default flatten;\n","import flatten from './flatten.js';\nimport overRest from './_overRest.js';\nimport setToString from './_setToString.js';\n\n/**\n * A specialized version of `baseRest` which flattens the rest array.\n *\n * @private\n * @param {Function} func The function to apply a rest parameter to.\n * @returns {Function} Returns the new function.\n */\nfunction flatRest(func) {\n return setToString(overRest(func, undefined, flatten), func + '');\n}\n\nexport default flatRest;\n","import overArg from './_overArg.js';\n\n/** Built-in value references. */\nvar getPrototype = overArg(Object.getPrototypeOf, Object);\n\nexport default getPrototype;\n","import baseGetTag from './_baseGetTag.js';\nimport getPrototype from './_getPrototype.js';\nimport isObjectLike from './isObjectLike.js';\n\n/** `Object#toString` result references. */\nvar objectTag = '[object Object]';\n\n/** Used for built-in method references. */\nvar funcProto = Function.prototype,\n objectProto = Object.prototype;\n\n/** Used to resolve the decompiled source of functions. */\nvar funcToString = funcProto.toString;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/** Used to infer the `Object` constructor. */\nvar objectCtorString = funcToString.call(Object);\n\n/**\n * Checks if `value` is a plain object, that is, an object created by the\n * `Object` constructor or one with a `[[Prototype]]` of `null`.\n *\n * @static\n * @memberOf _\n * @since 0.8.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a plain object, else `false`.\n * @example\n *\n * function Foo() {\n * this.a = 1;\n * }\n *\n * _.isPlainObject(new Foo);\n * // => false\n *\n * _.isPlainObject([1, 2, 3]);\n * // => false\n *\n * _.isPlainObject({ 'x': 0, 'y': 0 });\n * // => true\n *\n * _.isPlainObject(Object.create(null));\n * // => true\n */\nfunction isPlainObject(value) {\n if (!isObjectLike(value) || baseGetTag(value) != objectTag) {\n return false;\n }\n var proto = getPrototype(value);\n if (proto === null) {\n return true;\n }\n var Ctor = hasOwnProperty.call(proto, 'constructor') && proto.constructor;\n return typeof Ctor == 'function' && Ctor instanceof Ctor &&\n funcToString.call(Ctor) == objectCtorString;\n}\n\nexport default isPlainObject;\n","import ListCache from './_ListCache.js';\n\n/**\n * Removes all key-value entries from the stack.\n *\n * @private\n * @name clear\n * @memberOf Stack\n */\nfunction stackClear() {\n this.__data__ = new ListCache;\n this.size = 0;\n}\n\nexport default stackClear;\n","/**\n * Removes `key` and its value from the stack.\n *\n * @private\n * @name delete\n * @memberOf Stack\n * @param {string} key The key of the value to remove.\n * @returns {boolean} Returns `true` if the entry was removed, else `false`.\n */\nfunction stackDelete(key) {\n var data = this.__data__,\n result = data['delete'](key);\n\n this.size = data.size;\n return result;\n}\n\nexport default stackDelete;\n","/**\n * Gets the stack value for `key`.\n *\n * @private\n * @name get\n * @memberOf Stack\n * @param {string} key The key of the value to get.\n * @returns {*} Returns the entry value.\n */\nfunction stackGet(key) {\n return this.__data__.get(key);\n}\n\nexport default stackGet;\n","/**\n * Checks if a stack value for `key` exists.\n *\n * @private\n * @name has\n * @memberOf Stack\n * @param {string} key The key of the entry to check.\n * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.\n */\nfunction stackHas(key) {\n return this.__data__.has(key);\n}\n\nexport default stackHas;\n","import ListCache from './_ListCache.js';\nimport Map from './_Map.js';\nimport MapCache from './_MapCache.js';\n\n/** Used as the size to enable large array optimizations. */\nvar LARGE_ARRAY_SIZE = 200;\n\n/**\n * Sets the stack `key` to `value`.\n *\n * @private\n * @name set\n * @memberOf Stack\n * @param {string} key The key of the value to set.\n * @param {*} value The value to set.\n * @returns {Object} Returns the stack cache instance.\n */\nfunction stackSet(key, value) {\n var data = this.__data__;\n if (data instanceof ListCache) {\n var pairs = data.__data__;\n if (!Map || (pairs.length < LARGE_ARRAY_SIZE - 1)) {\n pairs.push([key, value]);\n this.size = ++data.size;\n return this;\n }\n data = this.__data__ = new MapCache(pairs);\n }\n data.set(key, value);\n this.size = data.size;\n return this;\n}\n\nexport default stackSet;\n","import ListCache from './_ListCache.js';\nimport stackClear from './_stackClear.js';\nimport stackDelete from './_stackDelete.js';\nimport stackGet from './_stackGet.js';\nimport stackHas from './_stackHas.js';\nimport stackSet from './_stackSet.js';\n\n/**\n * Creates a stack cache object to store key-value pairs.\n *\n * @private\n * @constructor\n * @param {Array} [entries] The key-value pairs to cache.\n */\nfunction Stack(entries) {\n var data = this.__data__ = new ListCache(entries);\n this.size = data.size;\n}\n\n// Add methods to `Stack`.\nStack.prototype.clear = stackClear;\nStack.prototype['delete'] = stackDelete;\nStack.prototype.get = stackGet;\nStack.prototype.has = stackHas;\nStack.prototype.set = stackSet;\n\nexport default Stack;\n","import root from './_root.js';\n\n/** Detect free variable `exports`. */\nvar freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports;\n\n/** Detect free variable `module`. */\nvar freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module;\n\n/** Detect the popular CommonJS extension `module.exports`. */\nvar moduleExports = freeModule && freeModule.exports === freeExports;\n\n/** Built-in value references. */\nvar Buffer = moduleExports ? root.Buffer : undefined,\n allocUnsafe = Buffer ? Buffer.allocUnsafe : undefined;\n\n/**\n * Creates a clone of `buffer`.\n *\n * @private\n * @param {Buffer} buffer The buffer to clone.\n * @param {boolean} [isDeep] Specify a deep clone.\n * @returns {Buffer} Returns the cloned buffer.\n */\nfunction cloneBuffer(buffer, isDeep) {\n if (isDeep) {\n return buffer.slice();\n }\n var length = buffer.length,\n result = allocUnsafe ? allocUnsafe(length) : new buffer.constructor(length);\n\n buffer.copy(result);\n return result;\n}\n\nexport default cloneBuffer;\n","/**\n * A specialized version of `_.filter` for arrays without support for\n * iteratee shorthands.\n *\n * @private\n * @param {Array} [array] The array to iterate over.\n * @param {Function} predicate The function invoked per iteration.\n * @returns {Array} Returns the new filtered array.\n */\nfunction arrayFilter(array, predicate) {\n var index = -1,\n length = array == null ? 0 : array.length,\n resIndex = 0,\n result = [];\n\n while (++index < length) {\n var value = array[index];\n if (predicate(value, index, array)) {\n result[resIndex++] = value;\n }\n }\n return result;\n}\n\nexport default arrayFilter;\n","/**\n * This method returns a new empty array.\n *\n * @static\n * @memberOf _\n * @since 4.13.0\n * @category Util\n * @returns {Array} Returns the new empty array.\n * @example\n *\n * var arrays = _.times(2, _.stubArray);\n *\n * console.log(arrays);\n * // => [[], []]\n *\n * console.log(arrays[0] === arrays[1]);\n * // => false\n */\nfunction stubArray() {\n return [];\n}\n\nexport default stubArray;\n","import arrayFilter from './_arrayFilter.js';\nimport stubArray from './stubArray.js';\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Built-in value references. */\nvar propertyIsEnumerable = objectProto.propertyIsEnumerable;\n\n/* Built-in method references for those with the same name as other `lodash` methods. */\nvar nativeGetSymbols = Object.getOwnPropertySymbols;\n\n/**\n * Creates an array of the own enumerable symbols of `object`.\n *\n * @private\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of symbols.\n */\nvar getSymbols = !nativeGetSymbols ? stubArray : function(object) {\n if (object == null) {\n return [];\n }\n object = Object(object);\n return arrayFilter(nativeGetSymbols(object), function(symbol) {\n return propertyIsEnumerable.call(object, symbol);\n });\n};\n\nexport default getSymbols;\n","import arrayPush from './_arrayPush.js';\nimport isArray from './isArray.js';\n\n/**\n * The base implementation of `getAllKeys` and `getAllKeysIn` which uses\n * `keysFunc` and `symbolsFunc` to get the enumerable property names and\n * symbols of `object`.\n *\n * @private\n * @param {Object} object The object to query.\n * @param {Function} keysFunc The function to get the keys of `object`.\n * @param {Function} symbolsFunc The function to get the symbols of `object`.\n * @returns {Array} Returns the array of property names and symbols.\n */\nfunction baseGetAllKeys(object, keysFunc, symbolsFunc) {\n var result = keysFunc(object);\n return isArray(object) ? result : arrayPush(result, symbolsFunc(object));\n}\n\nexport default baseGetAllKeys;\n","import baseGetAllKeys from './_baseGetAllKeys.js';\nimport getSymbols from './_getSymbols.js';\nimport keys from './keys.js';\n\n/**\n * Creates an array of own enumerable property names and symbols of `object`.\n *\n * @private\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of property names and symbols.\n */\nfunction getAllKeys(object) {\n return baseGetAllKeys(object, keys, getSymbols);\n}\n\nexport default getAllKeys;\n","import getNative from './_getNative.js';\nimport root from './_root.js';\n\n/* Built-in method references that are verified to be native. */\nvar DataView = getNative(root, 'DataView');\n\nexport default DataView;\n","import getNative from './_getNative.js';\nimport root from './_root.js';\n\n/* Built-in method references that are verified to be native. */\nvar Promise = getNative(root, 'Promise');\n\nexport default Promise;\n","import getNative from './_getNative.js';\nimport root from './_root.js';\n\n/* Built-in method references that are verified to be native. */\nvar Set = getNative(root, 'Set');\n\nexport default Set;\n","import DataView from './_DataView.js';\nimport Map from './_Map.js';\nimport Promise from './_Promise.js';\nimport Set from './_Set.js';\nimport WeakMap from './_WeakMap.js';\nimport baseGetTag from './_baseGetTag.js';\nimport toSource from './_toSource.js';\n\n/** `Object#toString` result references. */\nvar mapTag = '[object Map]',\n objectTag = '[object Object]',\n promiseTag = '[object Promise]',\n setTag = '[object Set]',\n weakMapTag = '[object WeakMap]';\n\nvar dataViewTag = '[object DataView]';\n\n/** Used to detect maps, sets, and weakmaps. */\nvar dataViewCtorString = toSource(DataView),\n mapCtorString = toSource(Map),\n promiseCtorString = toSource(Promise),\n setCtorString = toSource(Set),\n weakMapCtorString = toSource(WeakMap);\n\n/**\n * Gets the `toStringTag` of `value`.\n *\n * @private\n * @param {*} value The value to query.\n * @returns {string} Returns the `toStringTag`.\n */\nvar getTag = baseGetTag;\n\n// Fallback for data views, maps, sets, and weak maps in IE 11 and promises in Node.js < 6.\nif ((DataView && getTag(new DataView(new ArrayBuffer(1))) != dataViewTag) ||\n (Map && getTag(new Map) != mapTag) ||\n (Promise && getTag(Promise.resolve()) != promiseTag) ||\n (Set && getTag(new Set) != setTag) ||\n (WeakMap && getTag(new WeakMap) != weakMapTag)) {\n getTag = function(value) {\n var result = baseGetTag(value),\n Ctor = result == objectTag ? value.constructor : undefined,\n ctorString = Ctor ? toSource(Ctor) : '';\n\n if (ctorString) {\n switch (ctorString) {\n case dataViewCtorString: return dataViewTag;\n case mapCtorString: return mapTag;\n case promiseCtorString: return promiseTag;\n case setCtorString: return setTag;\n case weakMapCtorString: return weakMapTag;\n }\n }\n return result;\n };\n}\n\nexport default getTag;\n","import root from './_root.js';\n\n/** Built-in value references. */\nvar Uint8Array = root.Uint8Array;\n\nexport default Uint8Array;\n","import Uint8Array from './_Uint8Array.js';\n\n/**\n * Creates a clone of `arrayBuffer`.\n *\n * @private\n * @param {ArrayBuffer} arrayBuffer The array buffer to clone.\n * @returns {ArrayBuffer} Returns the cloned array buffer.\n */\nfunction cloneArrayBuffer(arrayBuffer) {\n var result = new arrayBuffer.constructor(arrayBuffer.byteLength);\n new Uint8Array(result).set(new Uint8Array(arrayBuffer));\n return result;\n}\n\nexport default cloneArrayBuffer;\n","import cloneArrayBuffer from './_cloneArrayBuffer.js';\n\n/**\n * Creates a clone of `typedArray`.\n *\n * @private\n * @param {Object} typedArray The typed array to clone.\n * @param {boolean} [isDeep] Specify a deep clone.\n * @returns {Object} Returns the cloned typed array.\n */\nfunction cloneTypedArray(typedArray, isDeep) {\n var buffer = isDeep ? cloneArrayBuffer(typedArray.buffer) : typedArray.buffer;\n return new typedArray.constructor(buffer, typedArray.byteOffset, typedArray.length);\n}\n\nexport default cloneTypedArray;\n","import baseCreate from './_baseCreate.js';\nimport getPrototype from './_getPrototype.js';\nimport isPrototype from './_isPrototype.js';\n\n/**\n * Initializes an object clone.\n *\n * @private\n * @param {Object} object The object to clone.\n * @returns {Object} Returns the initialized clone.\n */\nfunction initCloneObject(object) {\n return (typeof object.constructor == 'function' && !isPrototype(object))\n ? baseCreate(getPrototype(object))\n : {};\n}\n\nexport default initCloneObject;\n","/**\n * Creates an array with all falsey values removed. The values `false`, `null`,\n * `0`, `\"\"`, `undefined`, and `NaN` are falsey.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Array\n * @param {Array} array The array to compact.\n * @returns {Array} Returns the new array of filtered values.\n * @example\n *\n * _.compact([0, 1, false, 2, '', 3]);\n * // => [1, 2, 3]\n */\nfunction compact(array) {\n var index = -1,\n length = array == null ? 0 : array.length,\n resIndex = 0,\n result = [];\n\n while (++index < length) {\n var value = array[index];\n if (value) {\n result[resIndex++] = value;\n }\n }\n return result;\n}\n\nexport default compact;\n","/** Used to stand-in for `undefined` hash values. */\nvar HASH_UNDEFINED = '__lodash_hash_undefined__';\n\n/**\n * Adds `value` to the array cache.\n *\n * @private\n * @name add\n * @memberOf SetCache\n * @alias push\n * @param {*} value The value to cache.\n * @returns {Object} Returns the cache instance.\n */\nfunction setCacheAdd(value) {\n this.__data__.set(value, HASH_UNDEFINED);\n return this;\n}\n\nexport default setCacheAdd;\n","/**\n * Checks if `value` is in the array cache.\n *\n * @private\n * @name has\n * @memberOf SetCache\n * @param {*} value The value to search for.\n * @returns {number} Returns `true` if `value` is found, else `false`.\n */\nfunction setCacheHas(value) {\n return this.__data__.has(value);\n}\n\nexport default setCacheHas;\n","import MapCache from './_MapCache.js';\nimport setCacheAdd from './_setCacheAdd.js';\nimport setCacheHas from './_setCacheHas.js';\n\n/**\n *\n * Creates an array cache object to store unique values.\n *\n * @private\n * @constructor\n * @param {Array} [values] The values to cache.\n */\nfunction SetCache(values) {\n var index = -1,\n length = values == null ? 0 : values.length;\n\n this.__data__ = new MapCache;\n while (++index < length) {\n this.add(values[index]);\n }\n}\n\n// Add methods to `SetCache`.\nSetCache.prototype.add = SetCache.prototype.push = setCacheAdd;\nSetCache.prototype.has = setCacheHas;\n\nexport default SetCache;\n","/**\n * A specialized version of `_.some` for arrays without support for iteratee\n * shorthands.\n *\n * @private\n * @param {Array} [array] The array to iterate over.\n * @param {Function} predicate The function invoked per iteration.\n * @returns {boolean} Returns `true` if any element passes the predicate check,\n * else `false`.\n */\nfunction arraySome(array, predicate) {\n var index = -1,\n length = array == null ? 0 : array.length;\n\n while (++index < length) {\n if (predicate(array[index], index, array)) {\n return true;\n }\n }\n return false;\n}\n\nexport default arraySome;\n","/**\n * Checks if a `cache` value for `key` exists.\n *\n * @private\n * @param {Object} cache The cache to query.\n * @param {string} key The key of the entry to check.\n * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.\n */\nfunction cacheHas(cache, key) {\n return cache.has(key);\n}\n\nexport default cacheHas;\n","import SetCache from './_SetCache.js';\nimport arraySome from './_arraySome.js';\nimport cacheHas from './_cacheHas.js';\n\n/** Used to compose bitmasks for value comparisons. */\nvar COMPARE_PARTIAL_FLAG = 1,\n COMPARE_UNORDERED_FLAG = 2;\n\n/**\n * A specialized version of `baseIsEqualDeep` for arrays with support for\n * partial deep comparisons.\n *\n * @private\n * @param {Array} array The array to compare.\n * @param {Array} other The other array to compare.\n * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.\n * @param {Function} customizer The function to customize comparisons.\n * @param {Function} equalFunc The function to determine equivalents of values.\n * @param {Object} stack Tracks traversed `array` and `other` objects.\n * @returns {boolean} Returns `true` if the arrays are equivalent, else `false`.\n */\nfunction equalArrays(array, other, bitmask, customizer, equalFunc, stack) {\n var isPartial = bitmask & COMPARE_PARTIAL_FLAG,\n arrLength = array.length,\n othLength = other.length;\n\n if (arrLength != othLength && !(isPartial && othLength > arrLength)) {\n return false;\n }\n // Check that cyclic values are equal.\n var arrStacked = stack.get(array);\n var othStacked = stack.get(other);\n if (arrStacked && othStacked) {\n return arrStacked == other && othStacked == array;\n }\n var index = -1,\n result = true,\n seen = (bitmask & COMPARE_UNORDERED_FLAG) ? new SetCache : undefined;\n\n stack.set(array, other);\n stack.set(other, array);\n\n // Ignore non-index properties.\n while (++index < arrLength) {\n var arrValue = array[index],\n othValue = other[index];\n\n if (customizer) {\n var compared = isPartial\n ? customizer(othValue, arrValue, index, other, array, stack)\n : customizer(arrValue, othValue, index, array, other, stack);\n }\n if (compared !== undefined) {\n if (compared) {\n continue;\n }\n result = false;\n break;\n }\n // Recursively compare arrays (susceptible to call stack limits).\n if (seen) {\n if (!arraySome(other, function(othValue, othIndex) {\n if (!cacheHas(seen, othIndex) &&\n (arrValue === othValue || equalFunc(arrValue, othValue, bitmask, customizer, stack))) {\n return seen.push(othIndex);\n }\n })) {\n result = false;\n break;\n }\n } else if (!(\n arrValue === othValue ||\n equalFunc(arrValue, othValue, bitmask, customizer, stack)\n )) {\n result = false;\n break;\n }\n }\n stack['delete'](array);\n stack['delete'](other);\n return result;\n}\n\nexport default equalArrays;\n","/**\n * Converts `map` to its key-value pairs.\n *\n * @private\n * @param {Object} map The map to convert.\n * @returns {Array} Returns the key-value pairs.\n */\nfunction mapToArray(map) {\n var index = -1,\n result = Array(map.size);\n\n map.forEach(function(value, key) {\n result[++index] = [key, value];\n });\n return result;\n}\n\nexport default mapToArray;\n","/**\n * Converts `set` to an array of its values.\n *\n * @private\n * @param {Object} set The set to convert.\n * @returns {Array} Returns the values.\n */\nfunction setToArray(set) {\n var index = -1,\n result = Array(set.size);\n\n set.forEach(function(value) {\n result[++index] = value;\n });\n return result;\n}\n\nexport default setToArray;\n","import Symbol from './_Symbol.js';\nimport Uint8Array from './_Uint8Array.js';\nimport eq from './eq.js';\nimport equalArrays from './_equalArrays.js';\nimport mapToArray from './_mapToArray.js';\nimport setToArray from './_setToArray.js';\n\n/** Used to compose bitmasks for value comparisons. */\nvar COMPARE_PARTIAL_FLAG = 1,\n COMPARE_UNORDERED_FLAG = 2;\n\n/** `Object#toString` result references. */\nvar boolTag = '[object Boolean]',\n dateTag = '[object Date]',\n errorTag = '[object Error]',\n mapTag = '[object Map]',\n numberTag = '[object Number]',\n regexpTag = '[object RegExp]',\n setTag = '[object Set]',\n stringTag = '[object String]',\n symbolTag = '[object Symbol]';\n\nvar arrayBufferTag = '[object ArrayBuffer]',\n dataViewTag = '[object DataView]';\n\n/** Used to convert symbols to primitives and strings. */\nvar symbolProto = Symbol ? Symbol.prototype : undefined,\n symbolValueOf = symbolProto ? symbolProto.valueOf : undefined;\n\n/**\n * A specialized version of `baseIsEqualDeep` for comparing objects of\n * the same `toStringTag`.\n *\n * **Note:** This function only supports comparing values with tags of\n * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`.\n *\n * @private\n * @param {Object} object The object to compare.\n * @param {Object} other The other object to compare.\n * @param {string} tag The `toStringTag` of the objects to compare.\n * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.\n * @param {Function} customizer The function to customize comparisons.\n * @param {Function} equalFunc The function to determine equivalents of values.\n * @param {Object} stack Tracks traversed `object` and `other` objects.\n * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.\n */\nfunction equalByTag(object, other, tag, bitmask, customizer, equalFunc, stack) {\n switch (tag) {\n case dataViewTag:\n if ((object.byteLength != other.byteLength) ||\n (object.byteOffset != other.byteOffset)) {\n return false;\n }\n object = object.buffer;\n other = other.buffer;\n\n case arrayBufferTag:\n if ((object.byteLength != other.byteLength) ||\n !equalFunc(new Uint8Array(object), new Uint8Array(other))) {\n return false;\n }\n return true;\n\n case boolTag:\n case dateTag:\n case numberTag:\n // Coerce booleans to `1` or `0` and dates to milliseconds.\n // Invalid dates are coerced to `NaN`.\n return eq(+object, +other);\n\n case errorTag:\n return object.name == other.name && object.message == other.message;\n\n case regexpTag:\n case stringTag:\n // Coerce regexes to strings and treat strings, primitives and objects,\n // as equal. See http://www.ecma-international.org/ecma-262/7.0/#sec-regexp.prototype.tostring\n // for more details.\n return object == (other + '');\n\n case mapTag:\n var convert = mapToArray;\n\n case setTag:\n var isPartial = bitmask & COMPARE_PARTIAL_FLAG;\n convert || (convert = setToArray);\n\n if (object.size != other.size && !isPartial) {\n return false;\n }\n // Assume cyclic values are equal.\n var stacked = stack.get(object);\n if (stacked) {\n return stacked == other;\n }\n bitmask |= COMPARE_UNORDERED_FLAG;\n\n // Recursively compare objects (susceptible to call stack limits).\n stack.set(object, other);\n var result = equalArrays(convert(object), convert(other), bitmask, customizer, equalFunc, stack);\n stack['delete'](object);\n return result;\n\n case symbolTag:\n if (symbolValueOf) {\n return symbolValueOf.call(object) == symbolValueOf.call(other);\n }\n }\n return false;\n}\n\nexport default equalByTag;\n","import getAllKeys from './_getAllKeys.js';\n\n/** Used to compose bitmasks for value comparisons. */\nvar COMPARE_PARTIAL_FLAG = 1;\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * A specialized version of `baseIsEqualDeep` for objects with support for\n * partial deep comparisons.\n *\n * @private\n * @param {Object} object The object to compare.\n * @param {Object} other The other object to compare.\n * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.\n * @param {Function} customizer The function to customize comparisons.\n * @param {Function} equalFunc The function to determine equivalents of values.\n * @param {Object} stack Tracks traversed `object` and `other` objects.\n * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.\n */\nfunction equalObjects(object, other, bitmask, customizer, equalFunc, stack) {\n var isPartial = bitmask & COMPARE_PARTIAL_FLAG,\n objProps = getAllKeys(object),\n objLength = objProps.length,\n othProps = getAllKeys(other),\n othLength = othProps.length;\n\n if (objLength != othLength && !isPartial) {\n return false;\n }\n var index = objLength;\n while (index--) {\n var key = objProps[index];\n if (!(isPartial ? key in other : hasOwnProperty.call(other, key))) {\n return false;\n }\n }\n // Check that cyclic values are equal.\n var objStacked = stack.get(object);\n var othStacked = stack.get(other);\n if (objStacked && othStacked) {\n return objStacked == other && othStacked == object;\n }\n var result = true;\n stack.set(object, other);\n stack.set(other, object);\n\n var skipCtor = isPartial;\n while (++index < objLength) {\n key = objProps[index];\n var objValue = object[key],\n othValue = other[key];\n\n if (customizer) {\n var compared = isPartial\n ? customizer(othValue, objValue, key, other, object, stack)\n : customizer(objValue, othValue, key, object, other, stack);\n }\n // Recursively compare objects (susceptible to call stack limits).\n if (!(compared === undefined\n ? (objValue === othValue || equalFunc(objValue, othValue, bitmask, customizer, stack))\n : compared\n )) {\n result = false;\n break;\n }\n skipCtor || (skipCtor = key == 'constructor');\n }\n if (result && !skipCtor) {\n var objCtor = object.constructor,\n othCtor = other.constructor;\n\n // Non `Object` object instances with different constructors are not equal.\n if (objCtor != othCtor &&\n ('constructor' in object && 'constructor' in other) &&\n !(typeof objCtor == 'function' && objCtor instanceof objCtor &&\n typeof othCtor == 'function' && othCtor instanceof othCtor)) {\n result = false;\n }\n }\n stack['delete'](object);\n stack['delete'](other);\n return result;\n}\n\nexport default equalObjects;\n","import Stack from './_Stack.js';\nimport equalArrays from './_equalArrays.js';\nimport equalByTag from './_equalByTag.js';\nimport equalObjects from './_equalObjects.js';\nimport getTag from './_getTag.js';\nimport isArray from './isArray.js';\nimport isBuffer from './isBuffer.js';\nimport isTypedArray from './isTypedArray.js';\n\n/** Used to compose bitmasks for value comparisons. */\nvar COMPARE_PARTIAL_FLAG = 1;\n\n/** `Object#toString` result references. */\nvar argsTag = '[object Arguments]',\n arrayTag = '[object Array]',\n objectTag = '[object Object]';\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * A specialized version of `baseIsEqual` for arrays and objects which performs\n * deep comparisons and tracks traversed objects enabling objects with circular\n * references to be compared.\n *\n * @private\n * @param {Object} object The object to compare.\n * @param {Object} other The other object to compare.\n * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.\n * @param {Function} customizer The function to customize comparisons.\n * @param {Function} equalFunc The function to determine equivalents of values.\n * @param {Object} [stack] Tracks traversed `object` and `other` objects.\n * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.\n */\nfunction baseIsEqualDeep(object, other, bitmask, customizer, equalFunc, stack) {\n var objIsArr = isArray(object),\n othIsArr = isArray(other),\n objTag = objIsArr ? arrayTag : getTag(object),\n othTag = othIsArr ? arrayTag : getTag(other);\n\n objTag = objTag == argsTag ? objectTag : objTag;\n othTag = othTag == argsTag ? objectTag : othTag;\n\n var objIsObj = objTag == objectTag,\n othIsObj = othTag == objectTag,\n isSameTag = objTag == othTag;\n\n if (isSameTag && isBuffer(object)) {\n if (!isBuffer(other)) {\n return false;\n }\n objIsArr = true;\n objIsObj = false;\n }\n if (isSameTag && !objIsObj) {\n stack || (stack = new Stack);\n return (objIsArr || isTypedArray(object))\n ? equalArrays(object, other, bitmask, customizer, equalFunc, stack)\n : equalByTag(object, other, objTag, bitmask, customizer, equalFunc, stack);\n }\n if (!(bitmask & COMPARE_PARTIAL_FLAG)) {\n var objIsWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'),\n othIsWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__');\n\n if (objIsWrapped || othIsWrapped) {\n var objUnwrapped = objIsWrapped ? object.value() : object,\n othUnwrapped = othIsWrapped ? other.value() : other;\n\n stack || (stack = new Stack);\n return equalFunc(objUnwrapped, othUnwrapped, bitmask, customizer, stack);\n }\n }\n if (!isSameTag) {\n return false;\n }\n stack || (stack = new Stack);\n return equalObjects(object, other, bitmask, customizer, equalFunc, stack);\n}\n\nexport default baseIsEqualDeep;\n","import baseIsEqualDeep from './_baseIsEqualDeep.js';\nimport isObjectLike from './isObjectLike.js';\n\n/**\n * The base implementation of `_.isEqual` which supports partial comparisons\n * and tracks traversed objects.\n *\n * @private\n * @param {*} value The value to compare.\n * @param {*} other The other value to compare.\n * @param {boolean} bitmask The bitmask flags.\n * 1 - Unordered comparison\n * 2 - Partial comparison\n * @param {Function} [customizer] The function to customize comparisons.\n * @param {Object} [stack] Tracks traversed `value` and `other` objects.\n * @returns {boolean} Returns `true` if the values are equivalent, else `false`.\n */\nfunction baseIsEqual(value, other, bitmask, customizer, stack) {\n if (value === other) {\n return true;\n }\n if (value == null || other == null || (!isObjectLike(value) && !isObjectLike(other))) {\n return value !== value && other !== other;\n }\n return baseIsEqualDeep(value, other, bitmask, customizer, baseIsEqual, stack);\n}\n\nexport default baseIsEqual;\n","import Stack from './_Stack.js';\nimport baseIsEqual from './_baseIsEqual.js';\n\n/** Used to compose bitmasks for value comparisons. */\nvar COMPARE_PARTIAL_FLAG = 1,\n COMPARE_UNORDERED_FLAG = 2;\n\n/**\n * The base implementation of `_.isMatch` without support for iteratee shorthands.\n *\n * @private\n * @param {Object} object The object to inspect.\n * @param {Object} source The object of property values to match.\n * @param {Array} matchData The property names, values, and compare flags to match.\n * @param {Function} [customizer] The function to customize comparisons.\n * @returns {boolean} Returns `true` if `object` is a match, else `false`.\n */\nfunction baseIsMatch(object, source, matchData, customizer) {\n var index = matchData.length,\n length = index,\n noCustomizer = !customizer;\n\n if (object == null) {\n return !length;\n }\n object = Object(object);\n while (index--) {\n var data = matchData[index];\n if ((noCustomizer && data[2])\n ? data[1] !== object[data[0]]\n : !(data[0] in object)\n ) {\n return false;\n }\n }\n while (++index < length) {\n data = matchData[index];\n var key = data[0],\n objValue = object[key],\n srcValue = data[1];\n\n if (noCustomizer && data[2]) {\n if (objValue === undefined && !(key in object)) {\n return false;\n }\n } else {\n var stack = new Stack;\n if (customizer) {\n var result = customizer(objValue, srcValue, key, object, source, stack);\n }\n if (!(result === undefined\n ? baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG, customizer, stack)\n : result\n )) {\n return false;\n }\n }\n }\n return true;\n}\n\nexport default baseIsMatch;\n","import isObject from './isObject.js';\n\n/**\n * Checks if `value` is suitable for strict equality comparisons, i.e. `===`.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` if suitable for strict\n * equality comparisons, else `false`.\n */\nfunction isStrictComparable(value) {\n return value === value && !isObject(value);\n}\n\nexport default isStrictComparable;\n","import isStrictComparable from './_isStrictComparable.js';\nimport keys from './keys.js';\n\n/**\n * Gets the property names, values, and compare flags of `object`.\n *\n * @private\n * @param {Object} object The object to query.\n * @returns {Array} Returns the match data of `object`.\n */\nfunction getMatchData(object) {\n var result = keys(object),\n length = result.length;\n\n while (length--) {\n var key = result[length],\n value = object[key];\n\n result[length] = [key, value, isStrictComparable(value)];\n }\n return result;\n}\n\nexport default getMatchData;\n","/**\n * A specialized version of `matchesProperty` for source values suitable\n * for strict equality comparisons, i.e. `===`.\n *\n * @private\n * @param {string} key The key of the property to get.\n * @param {*} srcValue The value to match.\n * @returns {Function} Returns the new spec function.\n */\nfunction matchesStrictComparable(key, srcValue) {\n return function(object) {\n if (object == null) {\n return false;\n }\n return object[key] === srcValue &&\n (srcValue !== undefined || (key in Object(object)));\n };\n}\n\nexport default matchesStrictComparable;\n","import baseIsMatch from './_baseIsMatch.js';\nimport getMatchData from './_getMatchData.js';\nimport matchesStrictComparable from './_matchesStrictComparable.js';\n\n/**\n * The base implementation of `_.matches` which doesn't clone `source`.\n *\n * @private\n * @param {Object} source The object of property values to match.\n * @returns {Function} Returns the new spec function.\n */\nfunction baseMatches(source) {\n var matchData = getMatchData(source);\n if (matchData.length == 1 && matchData[0][2]) {\n return matchesStrictComparable(matchData[0][0], matchData[0][1]);\n }\n return function(object) {\n return object === source || baseIsMatch(object, source, matchData);\n };\n}\n\nexport default baseMatches;\n","/**\n * The base implementation of `_.hasIn` without support for deep paths.\n *\n * @private\n * @param {Object} [object] The object to query.\n * @param {Array|string} key The key to check.\n * @returns {boolean} Returns `true` if `key` exists, else `false`.\n */\nfunction baseHasIn(object, key) {\n return object != null && key in Object(object);\n}\n\nexport default baseHasIn;\n","import castPath from './_castPath.js';\nimport isArguments from './isArguments.js';\nimport isArray from './isArray.js';\nimport isIndex from './_isIndex.js';\nimport isLength from './isLength.js';\nimport toKey from './_toKey.js';\n\n/**\n * Checks if `path` exists on `object`.\n *\n * @private\n * @param {Object} object The object to query.\n * @param {Array|string} path The path to check.\n * @param {Function} hasFunc The function to check properties.\n * @returns {boolean} Returns `true` if `path` exists, else `false`.\n */\nfunction hasPath(object, path, hasFunc) {\n path = castPath(path, object);\n\n var index = -1,\n length = path.length,\n result = false;\n\n while (++index < length) {\n var key = toKey(path[index]);\n if (!(result = object != null && hasFunc(object, key))) {\n break;\n }\n object = object[key];\n }\n if (result || ++index != length) {\n return result;\n }\n length = object == null ? 0 : object.length;\n return !!length && isLength(length) && isIndex(key, length) &&\n (isArray(object) || isArguments(object));\n}\n\nexport default hasPath;\n","import baseHasIn from './_baseHasIn.js';\nimport hasPath from './_hasPath.js';\n\n/**\n * Checks if `path` is a direct or inherited property of `object`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Object\n * @param {Object} object The object to query.\n * @param {Array|string} path The path to check.\n * @returns {boolean} Returns `true` if `path` exists, else `false`.\n * @example\n *\n * var object = _.create({ 'a': _.create({ 'b': 2 }) });\n *\n * _.hasIn(object, 'a');\n * // => true\n *\n * _.hasIn(object, 'a.b');\n * // => true\n *\n * _.hasIn(object, ['a', 'b']);\n * // => true\n *\n * _.hasIn(object, 'b');\n * // => false\n */\nfunction hasIn(object, path) {\n return object != null && hasPath(object, path, baseHasIn);\n}\n\nexport default hasIn;\n","import baseIsEqual from './_baseIsEqual.js';\nimport get from './get.js';\nimport hasIn from './hasIn.js';\nimport isKey from './_isKey.js';\nimport isStrictComparable from './_isStrictComparable.js';\nimport matchesStrictComparable from './_matchesStrictComparable.js';\nimport toKey from './_toKey.js';\n\n/** Used to compose bitmasks for value comparisons. */\nvar COMPARE_PARTIAL_FLAG = 1,\n COMPARE_UNORDERED_FLAG = 2;\n\n/**\n * The base implementation of `_.matchesProperty` which doesn't clone `srcValue`.\n *\n * @private\n * @param {string} path The path of the property to get.\n * @param {*} srcValue The value to match.\n * @returns {Function} Returns the new spec function.\n */\nfunction baseMatchesProperty(path, srcValue) {\n if (isKey(path) && isStrictComparable(srcValue)) {\n return matchesStrictComparable(toKey(path), srcValue);\n }\n return function(object) {\n var objValue = get(object, path);\n return (objValue === undefined && objValue === srcValue)\n ? hasIn(object, path)\n : baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG);\n };\n}\n\nexport default baseMatchesProperty;\n","/**\n * The base implementation of `_.property` without support for deep paths.\n *\n * @private\n * @param {string} key The key of the property to get.\n * @returns {Function} Returns the new accessor function.\n */\nfunction baseProperty(key) {\n return function(object) {\n return object == null ? undefined : object[key];\n };\n}\n\nexport default baseProperty;\n","import baseGet from './_baseGet.js';\n\n/**\n * A specialized version of `baseProperty` which supports deep paths.\n *\n * @private\n * @param {Array|string} path The path of the property to get.\n * @returns {Function} Returns the new accessor function.\n */\nfunction basePropertyDeep(path) {\n return function(object) {\n return baseGet(object, path);\n };\n}\n\nexport default basePropertyDeep;\n","import baseProperty from './_baseProperty.js';\nimport basePropertyDeep from './_basePropertyDeep.js';\nimport isKey from './_isKey.js';\nimport toKey from './_toKey.js';\n\n/**\n * Creates a function that returns the value at `path` of a given object.\n *\n * @static\n * @memberOf _\n * @since 2.4.0\n * @category Util\n * @param {Array|string} path The path of the property to get.\n * @returns {Function} Returns the new accessor function.\n * @example\n *\n * var objects = [\n * { 'a': { 'b': 2 } },\n * { 'a': { 'b': 1 } }\n * ];\n *\n * _.map(objects, _.property('a.b'));\n * // => [2, 1]\n *\n * _.map(_.sortBy(objects, _.property(['a', 'b'])), 'a.b');\n * // => [1, 2]\n */\nfunction property(path) {\n return isKey(path) ? baseProperty(toKey(path)) : basePropertyDeep(path);\n}\n\nexport default property;\n","import baseMatches from './_baseMatches.js';\nimport baseMatchesProperty from './_baseMatchesProperty.js';\nimport identity from './identity.js';\nimport isArray from './isArray.js';\nimport property from './property.js';\n\n/**\n * The base implementation of `_.iteratee`.\n *\n * @private\n * @param {*} [value=_.identity] The value to convert to an iteratee.\n * @returns {Function} Returns the iteratee.\n */\nfunction baseIteratee(value) {\n // Don't store the `typeof` result in a variable to avoid a JIT bug in Safari 9.\n // See https://bugs.webkit.org/show_bug.cgi?id=156034 for more details.\n if (typeof value == 'function') {\n return value;\n }\n if (value == null) {\n return identity;\n }\n if (typeof value == 'object') {\n return isArray(value)\n ? baseMatchesProperty(value[0], value[1])\n : baseMatches(value);\n }\n return property(value);\n}\n\nexport default baseIteratee;\n","/**\n * Creates a base function for methods like `_.forIn` and `_.forOwn`.\n *\n * @private\n * @param {boolean} [fromRight] Specify iterating from right to left.\n * @returns {Function} Returns the new base function.\n */\nfunction createBaseFor(fromRight) {\n return function(object, iteratee, keysFunc) {\n var index = -1,\n iterable = Object(object),\n props = keysFunc(object),\n length = props.length;\n\n while (length--) {\n var key = props[fromRight ? length : ++index];\n if (iteratee(iterable[key], key, iterable) === false) {\n break;\n }\n }\n return object;\n };\n}\n\nexport default createBaseFor;\n","import createBaseFor from './_createBaseFor.js';\n\n/**\n * The base implementation of `baseForOwn` which iterates over `object`\n * properties returned by `keysFunc` and invokes `iteratee` for each property.\n * Iteratee functions may exit iteration early by explicitly returning `false`.\n *\n * @private\n * @param {Object} object The object to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @param {Function} keysFunc The function to get the keys of `object`.\n * @returns {Object} Returns `object`.\n */\nvar baseFor = createBaseFor();\n\nexport default baseFor;\n","import baseFor from './_baseFor.js';\nimport keys from './keys.js';\n\n/**\n * The base implementation of `_.forOwn` without support for iteratee shorthands.\n *\n * @private\n * @param {Object} object The object to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @returns {Object} Returns `object`.\n */\nfunction baseForOwn(object, iteratee) {\n return object && baseFor(object, iteratee, keys);\n}\n\nexport default baseForOwn;\n","import isArrayLike from './isArrayLike.js';\n\n/**\n * Creates a `baseEach` or `baseEachRight` function.\n *\n * @private\n * @param {Function} eachFunc The function to iterate over a collection.\n * @param {boolean} [fromRight] Specify iterating from right to left.\n * @returns {Function} Returns the new base function.\n */\nfunction createBaseEach(eachFunc, fromRight) {\n return function(collection, iteratee) {\n if (collection == null) {\n return collection;\n }\n if (!isArrayLike(collection)) {\n return eachFunc(collection, iteratee);\n }\n var length = collection.length,\n index = fromRight ? length : -1,\n iterable = Object(collection);\n\n while ((fromRight ? index-- : ++index < length)) {\n if (iteratee(iterable[index], index, iterable) === false) {\n break;\n }\n }\n return collection;\n };\n}\n\nexport default createBaseEach;\n","import baseForOwn from './_baseForOwn.js';\nimport createBaseEach from './_createBaseEach.js';\n\n/**\n * The base implementation of `_.forEach` without support for iteratee shorthands.\n *\n * @private\n * @param {Array|Object} collection The collection to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @returns {Array|Object} Returns `collection`.\n */\nvar baseEach = createBaseEach(baseForOwn);\n\nexport default baseEach;\n","import baseRest from './_baseRest.js';\nimport eq from './eq.js';\nimport isIterateeCall from './_isIterateeCall.js';\nimport keysIn from './keysIn.js';\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * Assigns own and inherited enumerable string keyed properties of source\n * objects to the destination object for all destination properties that\n * resolve to `undefined`. Source objects are applied from left to right.\n * Once a property is set, additional values of the same property are ignored.\n *\n * **Note:** This method mutates `object`.\n *\n * @static\n * @since 0.1.0\n * @memberOf _\n * @category Object\n * @param {Object} object The destination object.\n * @param {...Object} [sources] The source objects.\n * @returns {Object} Returns `object`.\n * @see _.defaultsDeep\n * @example\n *\n * _.defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 });\n * // => { 'a': 1, 'b': 2 }\n */\nvar defaults = baseRest(function(object, sources) {\n object = Object(object);\n\n var index = -1;\n var length = sources.length;\n var guard = length > 2 ? sources[2] : undefined;\n\n if (guard && isIterateeCall(sources[0], sources[1], guard)) {\n length = 1;\n }\n\n while (++index < length) {\n var source = sources[index];\n var props = keysIn(source);\n var propsIndex = -1;\n var propsLength = props.length;\n\n while (++propsIndex < propsLength) {\n var key = props[propsIndex];\n var value = object[key];\n\n if (value === undefined ||\n (eq(value, objectProto[key]) && !hasOwnProperty.call(object, key))) {\n object[key] = source[key];\n }\n }\n }\n\n return object;\n});\n\nexport default defaults;\n","import baseAssignValue from './_baseAssignValue.js';\nimport eq from './eq.js';\n\n/**\n * This function is like `assignValue` except that it doesn't assign\n * `undefined` values.\n *\n * @private\n * @param {Object} object The object to modify.\n * @param {string} key The key of the property to assign.\n * @param {*} value The value to assign.\n */\nfunction assignMergeValue(object, key, value) {\n if ((value !== undefined && !eq(object[key], value)) ||\n (value === undefined && !(key in object))) {\n baseAssignValue(object, key, value);\n }\n}\n\nexport default assignMergeValue;\n","import isArrayLike from './isArrayLike.js';\nimport isObjectLike from './isObjectLike.js';\n\n/**\n * This method is like `_.isArrayLike` except that it also checks if `value`\n * is an object.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an array-like object,\n * else `false`.\n * @example\n *\n * _.isArrayLikeObject([1, 2, 3]);\n * // => true\n *\n * _.isArrayLikeObject(document.body.children);\n * // => true\n *\n * _.isArrayLikeObject('abc');\n * // => false\n *\n * _.isArrayLikeObject(_.noop);\n * // => false\n */\nfunction isArrayLikeObject(value) {\n return isObjectLike(value) && isArrayLike(value);\n}\n\nexport default isArrayLikeObject;\n","/**\n * Gets the value at `key`, unless `key` is \"__proto__\" or \"constructor\".\n *\n * @private\n * @param {Object} object The object to query.\n * @param {string} key The key of the property to get.\n * @returns {*} Returns the property value.\n */\nfunction safeGet(object, key) {\n if (key === 'constructor' && typeof object[key] === 'function') {\n return;\n }\n\n if (key == '__proto__') {\n return;\n }\n\n return object[key];\n}\n\nexport default safeGet;\n","import copyObject from './_copyObject.js';\nimport keysIn from './keysIn.js';\n\n/**\n * Converts `value` to a plain object flattening inherited enumerable string\n * keyed properties of `value` to own properties of the plain object.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Lang\n * @param {*} value The value to convert.\n * @returns {Object} Returns the converted plain object.\n * @example\n *\n * function Foo() {\n * this.b = 2;\n * }\n *\n * Foo.prototype.c = 3;\n *\n * _.assign({ 'a': 1 }, new Foo);\n * // => { 'a': 1, 'b': 2 }\n *\n * _.assign({ 'a': 1 }, _.toPlainObject(new Foo));\n * // => { 'a': 1, 'b': 2, 'c': 3 }\n */\nfunction toPlainObject(value) {\n return copyObject(value, keysIn(value));\n}\n\nexport default toPlainObject;\n","import assignMergeValue from './_assignMergeValue.js';\nimport cloneBuffer from './_cloneBuffer.js';\nimport cloneTypedArray from './_cloneTypedArray.js';\nimport copyArray from './_copyArray.js';\nimport initCloneObject from './_initCloneObject.js';\nimport isArguments from './isArguments.js';\nimport isArray from './isArray.js';\nimport isArrayLikeObject from './isArrayLikeObject.js';\nimport isBuffer from './isBuffer.js';\nimport isFunction from './isFunction.js';\nimport isObject from './isObject.js';\nimport isPlainObject from './isPlainObject.js';\nimport isTypedArray from './isTypedArray.js';\nimport safeGet from './_safeGet.js';\nimport toPlainObject from './toPlainObject.js';\n\n/**\n * A specialized version of `baseMerge` for arrays and objects which performs\n * deep merges and tracks traversed objects enabling objects with circular\n * references to be merged.\n *\n * @private\n * @param {Object} object The destination object.\n * @param {Object} source The source object.\n * @param {string} key The key of the value to merge.\n * @param {number} srcIndex The index of `source`.\n * @param {Function} mergeFunc The function to merge values.\n * @param {Function} [customizer] The function to customize assigned values.\n * @param {Object} [stack] Tracks traversed source values and their merged\n * counterparts.\n */\nfunction baseMergeDeep(object, source, key, srcIndex, mergeFunc, customizer, stack) {\n var objValue = safeGet(object, key),\n srcValue = safeGet(source, key),\n stacked = stack.get(srcValue);\n\n if (stacked) {\n assignMergeValue(object, key, stacked);\n return;\n }\n var newValue = customizer\n ? customizer(objValue, srcValue, (key + ''), object, source, stack)\n : undefined;\n\n var isCommon = newValue === undefined;\n\n if (isCommon) {\n var isArr = isArray(srcValue),\n isBuff = !isArr && isBuffer(srcValue),\n isTyped = !isArr && !isBuff && isTypedArray(srcValue);\n\n newValue = srcValue;\n if (isArr || isBuff || isTyped) {\n if (isArray(objValue)) {\n newValue = objValue;\n }\n else if (isArrayLikeObject(objValue)) {\n newValue = copyArray(objValue);\n }\n else if (isBuff) {\n isCommon = false;\n newValue = cloneBuffer(srcValue, true);\n }\n else if (isTyped) {\n isCommon = false;\n newValue = cloneTypedArray(srcValue, true);\n }\n else {\n newValue = [];\n }\n }\n else if (isPlainObject(srcValue) || isArguments(srcValue)) {\n newValue = objValue;\n if (isArguments(objValue)) {\n newValue = toPlainObject(objValue);\n }\n else if (!isObject(objValue) || isFunction(objValue)) {\n newValue = initCloneObject(srcValue);\n }\n }\n else {\n isCommon = false;\n }\n }\n if (isCommon) {\n // Recursively merge objects and arrays (susceptible to call stack limits).\n stack.set(srcValue, newValue);\n mergeFunc(newValue, srcValue, srcIndex, customizer, stack);\n stack['delete'](srcValue);\n }\n assignMergeValue(object, key, newValue);\n}\n\nexport default baseMergeDeep;\n","import Stack from './_Stack.js';\nimport assignMergeValue from './_assignMergeValue.js';\nimport baseFor from './_baseFor.js';\nimport baseMergeDeep from './_baseMergeDeep.js';\nimport isObject from './isObject.js';\nimport keysIn from './keysIn.js';\nimport safeGet from './_safeGet.js';\n\n/**\n * The base implementation of `_.merge` without support for multiple sources.\n *\n * @private\n * @param {Object} object The destination object.\n * @param {Object} source The source object.\n * @param {number} srcIndex The index of `source`.\n * @param {Function} [customizer] The function to customize merged values.\n * @param {Object} [stack] Tracks traversed source values and their merged\n * counterparts.\n */\nfunction baseMerge(object, source, srcIndex, customizer, stack) {\n if (object === source) {\n return;\n }\n baseFor(source, function(srcValue, key) {\n stack || (stack = new Stack);\n if (isObject(srcValue)) {\n baseMergeDeep(object, source, key, srcIndex, baseMerge, customizer, stack);\n }\n else {\n var newValue = customizer\n ? customizer(safeGet(object, key), srcValue, (key + ''), object, source, stack)\n : undefined;\n\n if (newValue === undefined) {\n newValue = srcValue;\n }\n assignMergeValue(object, key, newValue);\n }\n }, keysIn);\n}\n\nexport default baseMerge;\n","import baseMerge from './_baseMerge.js';\nimport isObject from './isObject.js';\n\n/**\n * Used by `_.defaultsDeep` to customize its `_.merge` use to merge source\n * objects into destination objects that are passed thru.\n *\n * @private\n * @param {*} objValue The destination value.\n * @param {*} srcValue The source value.\n * @param {string} key The key of the property to merge.\n * @param {Object} object The parent object of `objValue`.\n * @param {Object} source The parent object of `srcValue`.\n * @param {Object} [stack] Tracks traversed source values and their merged\n * counterparts.\n * @returns {*} Returns the value to assign.\n */\nfunction customDefaultsMerge(objValue, srcValue, key, object, source, stack) {\n if (isObject(objValue) && isObject(srcValue)) {\n // Recursively merge objects and arrays (susceptible to call stack limits).\n stack.set(srcValue, objValue);\n baseMerge(objValue, srcValue, undefined, customDefaultsMerge, stack);\n stack['delete'](srcValue);\n }\n return objValue;\n}\n\nexport default customDefaultsMerge;\n","import baseMerge from './_baseMerge.js';\nimport createAssigner from './_createAssigner.js';\n\n/**\n * This method is like `_.merge` except that it accepts `customizer` which\n * is invoked to produce the merged values of the destination and source\n * properties. If `customizer` returns `undefined`, merging is handled by the\n * method instead. The `customizer` is invoked with six arguments:\n * (objValue, srcValue, key, object, source, stack).\n *\n * **Note:** This method mutates `object`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Object\n * @param {Object} object The destination object.\n * @param {...Object} sources The source objects.\n * @param {Function} customizer The function to customize assigned values.\n * @returns {Object} Returns `object`.\n * @example\n *\n * function customizer(objValue, srcValue) {\n * if (_.isArray(objValue)) {\n * return objValue.concat(srcValue);\n * }\n * }\n *\n * var object = { 'a': [1], 'b': [2] };\n * var other = { 'a': [3], 'b': [4] };\n *\n * _.mergeWith(object, other, customizer);\n * // => { 'a': [1, 3], 'b': [2, 4] }\n */\nvar mergeWith = createAssigner(function(object, source, srcIndex, customizer) {\n baseMerge(object, source, srcIndex, customizer);\n});\n\nexport default mergeWith;\n","import apply from './_apply.js';\nimport baseRest from './_baseRest.js';\nimport customDefaultsMerge from './_customDefaultsMerge.js';\nimport mergeWith from './mergeWith.js';\n\n/**\n * This method is like `_.defaults` except that it recursively assigns\n * default properties.\n *\n * **Note:** This method mutates `object`.\n *\n * @static\n * @memberOf _\n * @since 3.10.0\n * @category Object\n * @param {Object} object The destination object.\n * @param {...Object} [sources] The source objects.\n * @returns {Object} Returns `object`.\n * @see _.defaults\n * @example\n *\n * _.defaultsDeep({ 'a': { 'b': 2 } }, { 'a': { 'b': 1, 'c': 3 } });\n * // => { 'a': { 'b': 2, 'c': 3 } }\n */\nvar defaultsDeep = baseRest(function(args) {\n args.push(undefined, customDefaultsMerge);\n return apply(mergeWith, undefined, args);\n});\n\nexport default defaultsDeep;\n","/**\n * This function is like `arrayIncludes` except that it accepts a comparator.\n *\n * @private\n * @param {Array} [array] The array to inspect.\n * @param {*} target The value to search for.\n * @param {Function} comparator The comparator invoked per element.\n * @returns {boolean} Returns `true` if `target` is found, else `false`.\n */\nfunction arrayIncludesWith(array, value, comparator) {\n var index = -1,\n length = array == null ? 0 : array.length;\n\n while (++index < length) {\n if (comparator(value, array[index])) {\n return true;\n }\n }\n return false;\n}\n\nexport default arrayIncludesWith;\n","import SetCache from './_SetCache.js';\nimport arrayIncludes from './_arrayIncludes.js';\nimport arrayIncludesWith from './_arrayIncludesWith.js';\nimport arrayMap from './_arrayMap.js';\nimport baseUnary from './_baseUnary.js';\nimport cacheHas from './_cacheHas.js';\n\n/** Used as the size to enable large array optimizations. */\nvar LARGE_ARRAY_SIZE = 200;\n\n/**\n * The base implementation of methods like `_.difference` without support\n * for excluding multiple arrays or iteratee shorthands.\n *\n * @private\n * @param {Array} array The array to inspect.\n * @param {Array} values The values to exclude.\n * @param {Function} [iteratee] The iteratee invoked per element.\n * @param {Function} [comparator] The comparator invoked per element.\n * @returns {Array} Returns the new array of filtered values.\n */\nfunction baseDifference(array, values, iteratee, comparator) {\n var index = -1,\n includes = arrayIncludes,\n isCommon = true,\n length = array.length,\n result = [],\n valuesLength = values.length;\n\n if (!length) {\n return result;\n }\n if (iteratee) {\n values = arrayMap(values, baseUnary(iteratee));\n }\n if (comparator) {\n includes = arrayIncludesWith;\n isCommon = false;\n }\n else if (values.length >= LARGE_ARRAY_SIZE) {\n includes = cacheHas;\n isCommon = false;\n values = new SetCache(values);\n }\n outer:\n while (++index < length) {\n var value = array[index],\n computed = iteratee == null ? value : iteratee(value);\n\n value = (comparator || value !== 0) ? value : 0;\n if (isCommon && computed === computed) {\n var valuesIndex = valuesLength;\n while (valuesIndex--) {\n if (values[valuesIndex] === computed) {\n continue outer;\n }\n }\n result.push(value);\n }\n else if (!includes(values, computed, comparator)) {\n result.push(value);\n }\n }\n return result;\n}\n\nexport default baseDifference;\n","/**\n * Gets the last element of `array`.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Array\n * @param {Array} array The array to query.\n * @returns {*} Returns the last element of `array`.\n * @example\n *\n * _.last([1, 2, 3]);\n * // => 3\n */\nfunction last(array) {\n var length = array == null ? 0 : array.length;\n return length ? array[length - 1] : undefined;\n}\n\nexport default last;\n","import identity from './identity.js';\n\n/**\n * Casts `value` to `identity` if it's not a function.\n *\n * @private\n * @param {*} value The value to inspect.\n * @returns {Function} Returns cast function.\n */\nfunction castFunction(value) {\n return typeof value == 'function' ? value : identity;\n}\n\nexport default castFunction;\n","import arrayEach from './_arrayEach.js';\nimport baseEach from './_baseEach.js';\nimport castFunction from './_castFunction.js';\nimport isArray from './isArray.js';\n\n/**\n * Iterates over elements of `collection` and invokes `iteratee` for each element.\n * The iteratee is invoked with three arguments: (value, index|key, collection).\n * Iteratee functions may exit iteration early by explicitly returning `false`.\n *\n * **Note:** As with other \"Collections\" methods, objects with a \"length\"\n * property are iterated like arrays. To avoid this behavior use `_.forIn`\n * or `_.forOwn` for object iteration.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @alias each\n * @category Collection\n * @param {Array|Object} collection The collection to iterate over.\n * @param {Function} [iteratee=_.identity] The function invoked per iteration.\n * @returns {Array|Object} Returns `collection`.\n * @see _.forEachRight\n * @example\n *\n * _.forEach([1, 2], function(value) {\n * console.log(value);\n * });\n * // => Logs `1` then `2`.\n *\n * _.forEach({ 'a': 1, 'b': 2 }, function(value, key) {\n * console.log(key);\n * });\n * // => Logs 'a' then 'b' (iteration order is not guaranteed).\n */\nfunction forEach(collection, iteratee) {\n var func = isArray(collection) ? arrayEach : baseEach;\n return func(collection, castFunction(iteratee));\n}\n\nexport default forEach;\n","import baseEach from './_baseEach.js';\nimport isArrayLike from './isArrayLike.js';\n\n/**\n * The base implementation of `_.map` without support for iteratee shorthands.\n *\n * @private\n * @param {Array|Object} collection The collection to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @returns {Array} Returns the new mapped array.\n */\nfunction baseMap(collection, iteratee) {\n var index = -1,\n result = isArrayLike(collection) ? Array(collection.length) : [];\n\n baseEach(collection, function(value, key, collection) {\n result[++index] = iteratee(value, key, collection);\n });\n return result;\n}\n\nexport default baseMap;\n","import baseFlatten from './_baseFlatten.js';\n\n/** Used as references for various `Number` constants. */\nvar INFINITY = 1 / 0;\n\n/**\n * Recursively flattens `array`.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Array\n * @param {Array} array The array to flatten.\n * @returns {Array} Returns the new flattened array.\n * @example\n *\n * _.flattenDeep([1, [2, [3, [4]], 5]]);\n * // => [1, 2, 3, 4, 5]\n */\nfunction flattenDeep(array) {\n var length = array == null ? 0 : array.length;\n return length ? baseFlatten(array, INFINITY) : [];\n}\n\nexport default flattenDeep;\n","import SetCache from './_SetCache.js';\nimport arrayIncludes from './_arrayIncludes.js';\nimport arrayIncludesWith from './_arrayIncludesWith.js';\nimport arrayMap from './_arrayMap.js';\nimport baseUnary from './_baseUnary.js';\nimport cacheHas from './_cacheHas.js';\n\n/* Built-in method references for those with the same name as other `lodash` methods. */\nvar nativeMin = Math.min;\n\n/**\n * The base implementation of methods like `_.intersection`, without support\n * for iteratee shorthands, that accepts an array of arrays to inspect.\n *\n * @private\n * @param {Array} arrays The arrays to inspect.\n * @param {Function} [iteratee] The iteratee invoked per element.\n * @param {Function} [comparator] The comparator invoked per element.\n * @returns {Array} Returns the new array of shared values.\n */\nfunction baseIntersection(arrays, iteratee, comparator) {\n var includes = comparator ? arrayIncludesWith : arrayIncludes,\n length = arrays[0].length,\n othLength = arrays.length,\n othIndex = othLength,\n caches = Array(othLength),\n maxLength = Infinity,\n result = [];\n\n while (othIndex--) {\n var array = arrays[othIndex];\n if (othIndex && iteratee) {\n array = arrayMap(array, baseUnary(iteratee));\n }\n maxLength = nativeMin(array.length, maxLength);\n caches[othIndex] = !comparator && (iteratee || (length >= 120 && array.length >= 120))\n ? new SetCache(othIndex && array)\n : undefined;\n }\n array = arrays[0];\n\n var index = -1,\n seen = caches[0];\n\n outer:\n while (++index < length && result.length < maxLength) {\n var value = array[index],\n computed = iteratee ? iteratee(value) : value;\n\n value = (comparator || value !== 0) ? value : 0;\n if (!(seen\n ? cacheHas(seen, computed)\n : includes(result, computed, comparator)\n )) {\n othIndex = othLength;\n while (--othIndex) {\n var cache = caches[othIndex];\n if (!(cache\n ? cacheHas(cache, computed)\n : includes(arrays[othIndex], computed, comparator))\n ) {\n continue outer;\n }\n }\n if (seen) {\n seen.push(computed);\n }\n result.push(value);\n }\n }\n return result;\n}\n\nexport default baseIntersection;\n","import isArrayLikeObject from './isArrayLikeObject.js';\n\n/**\n * Casts `value` to an empty array if it's not an array like object.\n *\n * @private\n * @param {*} value The value to inspect.\n * @returns {Array|Object} Returns the cast array-like object.\n */\nfunction castArrayLikeObject(value) {\n return isArrayLikeObject(value) ? value : [];\n}\n\nexport default castArrayLikeObject;\n","import arrayMap from './_arrayMap.js';\nimport baseIntersection from './_baseIntersection.js';\nimport baseRest from './_baseRest.js';\nimport castArrayLikeObject from './_castArrayLikeObject.js';\n\n/**\n * Creates an array of unique values that are included in all given arrays\n * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)\n * for equality comparisons. The order and references of result values are\n * determined by the first array.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Array\n * @param {...Array} [arrays] The arrays to inspect.\n * @returns {Array} Returns the new array of intersecting values.\n * @example\n *\n * _.intersection([2, 1], [2, 3]);\n * // => [2]\n */\nvar intersection = baseRest(function(arrays) {\n var mapped = arrayMap(arrays, castArrayLikeObject);\n return (mapped.length && mapped[0] === arrays[0])\n ? baseIntersection(mapped)\n : [];\n});\n\nexport default intersection;\n","import arrayMap from './_arrayMap.js';\nimport baseIntersection from './_baseIntersection.js';\nimport baseRest from './_baseRest.js';\nimport castArrayLikeObject from './_castArrayLikeObject.js';\nimport last from './last.js';\n\n/**\n * This method is like `_.intersection` except that it accepts `comparator`\n * which is invoked to compare elements of `arrays`. The order and references\n * of result values are determined by the first array. The comparator is\n * invoked with two arguments: (arrVal, othVal).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Array\n * @param {...Array} [arrays] The arrays to inspect.\n * @param {Function} [comparator] The comparator invoked per element.\n * @returns {Array} Returns the new array of intersecting values.\n * @example\n *\n * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];\n * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }];\n *\n * _.intersectionWith(objects, others, _.isEqual);\n * // => [{ 'x': 1, 'y': 2 }]\n */\nvar intersectionWith = baseRest(function(arrays) {\n var comparator = last(arrays),\n mapped = arrayMap(arrays, castArrayLikeObject);\n\n comparator = typeof comparator == 'function' ? comparator : undefined;\n if (comparator) {\n mapped.pop();\n }\n return (mapped.length && mapped[0] === arrays[0])\n ? baseIntersection(mapped, undefined, comparator)\n : [];\n});\n\nexport default intersectionWith;\n","import baseGetTag from './_baseGetTag.js';\nimport isObjectLike from './isObjectLike.js';\n\n/** `Object#toString` result references. */\nvar boolTag = '[object Boolean]';\n\n/**\n * Checks if `value` is classified as a boolean primitive or object.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a boolean, else `false`.\n * @example\n *\n * _.isBoolean(false);\n * // => true\n *\n * _.isBoolean(null);\n * // => false\n */\nfunction isBoolean(value) {\n return value === true || value === false ||\n (isObjectLike(value) && baseGetTag(value) == boolTag);\n}\n\nexport default isBoolean;\n","import baseIsEqual from './_baseIsEqual.js';\n\n/**\n * Performs a deep comparison between two values to determine if they are\n * equivalent.\n *\n * **Note:** This method supports comparing arrays, array buffers, booleans,\n * date objects, error objects, maps, numbers, `Object` objects, regexes,\n * sets, strings, symbols, and typed arrays. `Object` objects are compared\n * by their own, not inherited, enumerable properties. Functions and DOM\n * nodes are compared by strict equality, i.e. `===`.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to compare.\n * @param {*} other The other value to compare.\n * @returns {boolean} Returns `true` if the values are equivalent, else `false`.\n * @example\n *\n * var object = { 'a': 1 };\n * var other = { 'a': 1 };\n *\n * _.isEqual(object, other);\n * // => true\n *\n * object === other;\n * // => false\n */\nfunction isEqual(value, other) {\n return baseIsEqual(value, other);\n}\n\nexport default isEqual;\n","import assignValue from './_assignValue.js';\nimport castPath from './_castPath.js';\nimport isIndex from './_isIndex.js';\nimport isObject from './isObject.js';\nimport toKey from './_toKey.js';\n\n/**\n * The base implementation of `_.set`.\n *\n * @private\n * @param {Object} object The object to modify.\n * @param {Array|string} path The path of the property to set.\n * @param {*} value The value to set.\n * @param {Function} [customizer] The function to customize path creation.\n * @returns {Object} Returns `object`.\n */\nfunction baseSet(object, path, value, customizer) {\n if (!isObject(object)) {\n return object;\n }\n path = castPath(path, object);\n\n var index = -1,\n length = path.length,\n lastIndex = length - 1,\n nested = object;\n\n while (nested != null && ++index < length) {\n var key = toKey(path[index]),\n newValue = value;\n\n if (key === '__proto__' || key === 'constructor' || key === 'prototype') {\n return object;\n }\n\n if (index != lastIndex) {\n var objValue = nested[key];\n newValue = customizer ? customizer(objValue, key, nested) : undefined;\n if (newValue === undefined) {\n newValue = isObject(objValue)\n ? objValue\n : (isIndex(path[index + 1]) ? [] : {});\n }\n }\n assignValue(nested, key, newValue);\n nested = nested[key];\n }\n return object;\n}\n\nexport default baseSet;\n","import baseGet from './_baseGet.js';\nimport baseSet from './_baseSet.js';\nimport castPath from './_castPath.js';\n\n/**\n * The base implementation of `_.pickBy` without support for iteratee shorthands.\n *\n * @private\n * @param {Object} object The source object.\n * @param {string[]} paths The property paths to pick.\n * @param {Function} predicate The function invoked per property.\n * @returns {Object} Returns the new object.\n */\nfunction basePickBy(object, paths, predicate) {\n var index = -1,\n length = paths.length,\n result = {};\n\n while (++index < length) {\n var path = paths[index],\n value = baseGet(object, path);\n\n if (predicate(value, path)) {\n baseSet(result, castPath(path, object), value);\n }\n }\n return result;\n}\n\nexport default basePickBy;\n","/**\n * The base implementation of `_.sortBy` which uses `comparer` to define the\n * sort order of `array` and replaces criteria objects with their corresponding\n * values.\n *\n * @private\n * @param {Array} array The array to sort.\n * @param {Function} comparer The function to define sort order.\n * @returns {Array} Returns `array`.\n */\nfunction baseSortBy(array, comparer) {\n var length = array.length;\n\n array.sort(comparer);\n while (length--) {\n array[length] = array[length].value;\n }\n return array;\n}\n\nexport default baseSortBy;\n","import isSymbol from './isSymbol.js';\n\n/**\n * Compares values to sort them in ascending order.\n *\n * @private\n * @param {*} value The value to compare.\n * @param {*} other The other value to compare.\n * @returns {number} Returns the sort order indicator for `value`.\n */\nfunction compareAscending(value, other) {\n if (value !== other) {\n var valIsDefined = value !== undefined,\n valIsNull = value === null,\n valIsReflexive = value === value,\n valIsSymbol = isSymbol(value);\n\n var othIsDefined = other !== undefined,\n othIsNull = other === null,\n othIsReflexive = other === other,\n othIsSymbol = isSymbol(other);\n\n if ((!othIsNull && !othIsSymbol && !valIsSymbol && value > other) ||\n (valIsSymbol && othIsDefined && othIsReflexive && !othIsNull && !othIsSymbol) ||\n (valIsNull && othIsDefined && othIsReflexive) ||\n (!valIsDefined && othIsReflexive) ||\n !valIsReflexive) {\n return 1;\n }\n if ((!valIsNull && !valIsSymbol && !othIsSymbol && value < other) ||\n (othIsSymbol && valIsDefined && valIsReflexive && !valIsNull && !valIsSymbol) ||\n (othIsNull && valIsDefined && valIsReflexive) ||\n (!othIsDefined && valIsReflexive) ||\n !othIsReflexive) {\n return -1;\n }\n }\n return 0;\n}\n\nexport default compareAscending;\n","import compareAscending from './_compareAscending.js';\n\n/**\n * Used by `_.orderBy` to compare multiple properties of a value to another\n * and stable sort them.\n *\n * If `orders` is unspecified, all values are sorted in ascending order. Otherwise,\n * specify an order of \"desc\" for descending or \"asc\" for ascending sort order\n * of corresponding values.\n *\n * @private\n * @param {Object} object The object to compare.\n * @param {Object} other The other object to compare.\n * @param {boolean[]|string[]} orders The order to sort by for each property.\n * @returns {number} Returns the sort order indicator for `object`.\n */\nfunction compareMultiple(object, other, orders) {\n var index = -1,\n objCriteria = object.criteria,\n othCriteria = other.criteria,\n length = objCriteria.length,\n ordersLength = orders.length;\n\n while (++index < length) {\n var result = compareAscending(objCriteria[index], othCriteria[index]);\n if (result) {\n if (index >= ordersLength) {\n return result;\n }\n var order = orders[index];\n return result * (order == 'desc' ? -1 : 1);\n }\n }\n // Fixes an `Array#sort` bug in the JS engine embedded in Adobe applications\n // that causes it, under certain circumstances, to provide the same value for\n // `object` and `other`. See https://github.com/jashkenas/underscore/pull/1247\n // for more details.\n //\n // This also ensures a stable sort in V8 and other engines.\n // See https://bugs.chromium.org/p/v8/issues/detail?id=90 for more details.\n return object.index - other.index;\n}\n\nexport default compareMultiple;\n","import arrayMap from './_arrayMap.js';\nimport baseGet from './_baseGet.js';\nimport baseIteratee from './_baseIteratee.js';\nimport baseMap from './_baseMap.js';\nimport baseSortBy from './_baseSortBy.js';\nimport baseUnary from './_baseUnary.js';\nimport compareMultiple from './_compareMultiple.js';\nimport identity from './identity.js';\nimport isArray from './isArray.js';\n\n/**\n * The base implementation of `_.orderBy` without param guards.\n *\n * @private\n * @param {Array|Object} collection The collection to iterate over.\n * @param {Function[]|Object[]|string[]} iteratees The iteratees to sort by.\n * @param {string[]} orders The sort orders of `iteratees`.\n * @returns {Array} Returns the new sorted array.\n */\nfunction baseOrderBy(collection, iteratees, orders) {\n if (iteratees.length) {\n iteratees = arrayMap(iteratees, function(iteratee) {\n if (isArray(iteratee)) {\n return function(value) {\n return baseGet(value, iteratee.length === 1 ? iteratee[0] : iteratee);\n }\n }\n return iteratee;\n });\n } else {\n iteratees = [identity];\n }\n\n var index = -1;\n iteratees = arrayMap(iteratees, baseUnary(baseIteratee));\n\n var result = baseMap(collection, function(value, key, collection) {\n var criteria = arrayMap(iteratees, function(iteratee) {\n return iteratee(value);\n });\n return { 'criteria': criteria, 'index': ++index, 'value': value };\n });\n\n return baseSortBy(result, function(object, other) {\n return compareMultiple(object, other, orders);\n });\n}\n\nexport default baseOrderBy;\n","import basePickBy from './_basePickBy.js';\nimport hasIn from './hasIn.js';\n\n/**\n * The base implementation of `_.pick` without support for individual\n * property identifiers.\n *\n * @private\n * @param {Object} object The source object.\n * @param {string[]} paths The property paths to pick.\n * @returns {Object} Returns the new object.\n */\nfunction basePick(object, paths) {\n return basePickBy(object, paths, function(value, path) {\n return hasIn(object, path);\n });\n}\n\nexport default basePick;\n","import basePick from './_basePick.js';\nimport flatRest from './_flatRest.js';\n\n/**\n * Creates an object composed of the picked `object` properties.\n *\n * @static\n * @since 0.1.0\n * @memberOf _\n * @category Object\n * @param {Object} object The source object.\n * @param {...(string|string[])} [paths] The property paths to pick.\n * @returns {Object} Returns the new object.\n * @example\n *\n * var object = { 'a': 1, 'b': '2', 'c': 3 };\n *\n * _.pick(object, ['a', 'c']);\n * // => { 'a': 1, 'c': 3 }\n */\nvar pick = flatRest(function(object, paths) {\n return object == null ? {} : basePick(object, paths);\n});\n\nexport default pick;\n","/**\n * This function is like `baseIndexOf` except that it accepts a comparator.\n *\n * @private\n * @param {Array} array The array to inspect.\n * @param {*} value The value to search for.\n * @param {number} fromIndex The index to search from.\n * @param {Function} comparator The comparator invoked per element.\n * @returns {number} Returns the index of the matched value, else `-1`.\n */\nfunction baseIndexOfWith(array, value, fromIndex, comparator) {\n var index = fromIndex - 1,\n length = array.length;\n\n while (++index < length) {\n if (comparator(array[index], value)) {\n return index;\n }\n }\n return -1;\n}\n\nexport default baseIndexOfWith;\n","import arrayMap from './_arrayMap.js';\nimport baseIndexOf from './_baseIndexOf.js';\nimport baseIndexOfWith from './_baseIndexOfWith.js';\nimport baseUnary from './_baseUnary.js';\nimport copyArray from './_copyArray.js';\n\n/** Used for built-in method references. */\nvar arrayProto = Array.prototype;\n\n/** Built-in value references. */\nvar splice = arrayProto.splice;\n\n/**\n * The base implementation of `_.pullAllBy` without support for iteratee\n * shorthands.\n *\n * @private\n * @param {Array} array The array to modify.\n * @param {Array} values The values to remove.\n * @param {Function} [iteratee] The iteratee invoked per element.\n * @param {Function} [comparator] The comparator invoked per element.\n * @returns {Array} Returns `array`.\n */\nfunction basePullAll(array, values, iteratee, comparator) {\n var indexOf = comparator ? baseIndexOfWith : baseIndexOf,\n index = -1,\n length = values.length,\n seen = array;\n\n if (array === values) {\n values = copyArray(values);\n }\n if (iteratee) {\n seen = arrayMap(array, baseUnary(iteratee));\n }\n while (++index < length) {\n var fromIndex = 0,\n value = values[index],\n computed = iteratee ? iteratee(value) : value;\n\n while ((fromIndex = indexOf(seen, computed, fromIndex, comparator)) > -1) {\n if (seen !== array) {\n splice.call(seen, fromIndex, 1);\n }\n splice.call(array, fromIndex, 1);\n }\n }\n return array;\n}\n\nexport default basePullAll;\n","import basePullAll from './_basePullAll.js';\n\n/**\n * This method is like `_.pull` except that it accepts an array of values to remove.\n *\n * **Note:** Unlike `_.difference`, this method mutates `array`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Array\n * @param {Array} array The array to modify.\n * @param {Array} values The values to remove.\n * @returns {Array} Returns `array`.\n * @example\n *\n * var array = ['a', 'b', 'c', 'a', 'b', 'c'];\n *\n * _.pullAll(array, ['a', 'c']);\n * console.log(array);\n * // => ['b', 'b']\n */\nfunction pullAll(array, values) {\n return (array && array.length && values && values.length)\n ? basePullAll(array, values)\n : array;\n}\n\nexport default pullAll;\n","import baseFlatten from './_baseFlatten.js';\nimport baseOrderBy from './_baseOrderBy.js';\nimport baseRest from './_baseRest.js';\nimport isIterateeCall from './_isIterateeCall.js';\n\n/**\n * Creates an array of elements, sorted in ascending order by the results of\n * running each element in a collection thru each iteratee. This method\n * performs a stable sort, that is, it preserves the original sort order of\n * equal elements. The iteratees are invoked with one argument: (value).\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Collection\n * @param {Array|Object} collection The collection to iterate over.\n * @param {...(Function|Function[])} [iteratees=[_.identity]]\n * The iteratees to sort by.\n * @returns {Array} Returns the new sorted array.\n * @example\n *\n * var users = [\n * { 'user': 'fred', 'age': 48 },\n * { 'user': 'barney', 'age': 36 },\n * { 'user': 'fred', 'age': 30 },\n * { 'user': 'barney', 'age': 34 }\n * ];\n *\n * _.sortBy(users, [function(o) { return o.user; }]);\n * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 30]]\n *\n * _.sortBy(users, ['user', 'age']);\n * // => objects for [['barney', 34], ['barney', 36], ['fred', 30], ['fred', 48]]\n */\nvar sortBy = baseRest(function(collection, iteratees) {\n if (collection == null) {\n return [];\n }\n var length = iteratees.length;\n if (length > 1 && isIterateeCall(collection, iteratees[0], iteratees[1])) {\n iteratees = [];\n } else if (length > 2 && isIterateeCall(iteratees[0], iteratees[1], iteratees[2])) {\n iteratees = [iteratees[0]];\n }\n return baseOrderBy(collection, baseFlatten(iteratees, 1), []);\n});\n\nexport default sortBy;\n","import Set from './_Set.js';\nimport noop from './noop.js';\nimport setToArray from './_setToArray.js';\n\n/** Used as references for various `Number` constants. */\nvar INFINITY = 1 / 0;\n\n/**\n * Creates a set object of `values`.\n *\n * @private\n * @param {Array} values The values to add to the set.\n * @returns {Object} Returns the new set.\n */\nvar createSet = !(Set && (1 / setToArray(new Set([,-0]))[1]) == INFINITY) ? noop : function(values) {\n return new Set(values);\n};\n\nexport default createSet;\n","import SetCache from './_SetCache.js';\nimport arrayIncludes from './_arrayIncludes.js';\nimport arrayIncludesWith from './_arrayIncludesWith.js';\nimport cacheHas from './_cacheHas.js';\nimport createSet from './_createSet.js';\nimport setToArray from './_setToArray.js';\n\n/** Used as the size to enable large array optimizations. */\nvar LARGE_ARRAY_SIZE = 200;\n\n/**\n * The base implementation of `_.uniqBy` without support for iteratee shorthands.\n *\n * @private\n * @param {Array} array The array to inspect.\n * @param {Function} [iteratee] The iteratee invoked per element.\n * @param {Function} [comparator] The comparator invoked per element.\n * @returns {Array} Returns the new duplicate free array.\n */\nfunction baseUniq(array, iteratee, comparator) {\n var index = -1,\n includes = arrayIncludes,\n length = array.length,\n isCommon = true,\n result = [],\n seen = result;\n\n if (comparator) {\n isCommon = false;\n includes = arrayIncludesWith;\n }\n else if (length >= LARGE_ARRAY_SIZE) {\n var set = iteratee ? null : createSet(array);\n if (set) {\n return setToArray(set);\n }\n isCommon = false;\n includes = cacheHas;\n seen = new SetCache;\n }\n else {\n seen = iteratee ? [] : result;\n }\n outer:\n while (++index < length) {\n var value = array[index],\n computed = iteratee ? iteratee(value) : value;\n\n value = (comparator || value !== 0) ? value : 0;\n if (isCommon && computed === computed) {\n var seenIndex = seen.length;\n while (seenIndex--) {\n if (seen[seenIndex] === computed) {\n continue outer;\n }\n }\n if (iteratee) {\n seen.push(computed);\n }\n result.push(value);\n }\n else if (!includes(seen, computed, comparator)) {\n if (seen !== result) {\n seen.push(computed);\n }\n result.push(value);\n }\n }\n return result;\n}\n\nexport default baseUniq;\n","import baseUniq from './_baseUniq.js';\n\n/**\n * Creates a duplicate-free version of an array, using\n * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)\n * for equality comparisons, in which only the first occurrence of each element\n * is kept. The order of result values is determined by the order they occur\n * in the array.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Array\n * @param {Array} array The array to inspect.\n * @returns {Array} Returns the new duplicate free array.\n * @example\n *\n * _.uniq([2, 1, 2]);\n * // => [2, 1]\n */\nfunction uniq(array) {\n return (array && array.length) ? baseUniq(array) : [];\n}\n\nexport default uniq;\n","import baseUniq from './_baseUniq.js';\n\n/**\n * This method is like `_.uniq` except that it accepts `comparator` which\n * is invoked to compare elements of `array`. The order of result values is\n * determined by the order they occur in the array.The comparator is invoked\n * with two arguments: (arrVal, othVal).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Array\n * @param {Array} array The array to inspect.\n * @param {Function} [comparator] The comparator invoked per element.\n * @returns {Array} Returns the new duplicate free array.\n * @example\n *\n * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 2 }];\n *\n * _.uniqWith(objects, _.isEqual);\n * // => [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }]\n */\nfunction uniqWith(array, comparator) {\n comparator = typeof comparator == 'function' ? comparator : undefined;\n return (array && array.length) ? baseUniq(array, undefined, comparator) : [];\n}\n\nexport default uniqWith;\n","import baseDifference from './_baseDifference.js';\nimport baseRest from './_baseRest.js';\nimport isArrayLikeObject from './isArrayLikeObject.js';\n\n/**\n * Creates an array excluding all given values using\n * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)\n * for equality comparisons.\n *\n * **Note:** Unlike `_.pull`, this method returns a new array.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Array\n * @param {Array} array The array to inspect.\n * @param {...*} [values] The values to exclude.\n * @returns {Array} Returns the new array of filtered values.\n * @see _.difference, _.xor\n * @example\n *\n * _.without([2, 1, 2, 3], 1, 2);\n * // => [3]\n */\nvar without = baseRest(function(array, values) {\n return isArrayLikeObject(array)\n ? baseDifference(array, values)\n : [];\n});\n\nexport default without;\n","'use strict'\n\nmodule.exports = stringify\n\nvar indentation = ''\n// eslint-disable-next-line\nconst strEscapeSequencesRegExp = /[\\x00-\\x1f\\x22\\x5c]/\n// eslint-disable-next-line\nconst strEscapeSequencesReplacer = /[\\x00-\\x1f\\x22\\x5c]/g\n\n// Escaped special characters. Use empty strings to fill up unused entries.\nconst meta = [\n '\\\\u0000', '\\\\u0001', '\\\\u0002', '\\\\u0003', '\\\\u0004',\n '\\\\u0005', '\\\\u0006', '\\\\u0007', '\\\\b', '\\\\t',\n '\\\\n', '\\\\u000b', '\\\\f', '\\\\r', '\\\\u000e',\n '\\\\u000f', '\\\\u0010', '\\\\u0011', '\\\\u0012', '\\\\u0013',\n '\\\\u0014', '\\\\u0015', '\\\\u0016', '\\\\u0017', '\\\\u0018',\n '\\\\u0019', '\\\\u001a', '\\\\u001b', '\\\\u001c', '\\\\u001d',\n '\\\\u001e', '\\\\u001f', '', '', '\\\\\"',\n '', '', '', '', '', '', '', '', '', '',\n '', '', '', '', '', '', '', '', '', '',\n '', '', '', '', '', '', '', '', '', '',\n '', '', '', '', '', '', '', '', '', '',\n '', '', '', '', '', '', '', '', '', '',\n '', '', '', '', '', '', '', '\\\\\\\\'\n]\n\nfunction escapeFn (str) {\n return meta[str.charCodeAt(0)]\n}\n\n// Escape control characters, double quotes and the backslash.\n// Note: it is faster to run this only once for a big string instead of only for\n// the parts that it is necessary for. But this is only true if we do not add\n// extra indentation to the string before.\nfunction strEscape (str) {\n // Some magic numbers that worked out fine while benchmarking with v8 6.0\n if (str.length < 5000 && !strEscapeSequencesRegExp.test(str)) {\n return str\n }\n if (str.length > 100) {\n return str.replace(strEscapeSequencesReplacer, escapeFn)\n }\n var result = ''\n var last = 0\n for (var i = 0; i < str.length; i++) {\n const point = str.charCodeAt(i)\n if (point === 34 || point === 92 || point < 32) {\n if (last === i) {\n result += meta[point]\n } else {\n result += `${str.slice(last, i)}${meta[point]}`\n }\n last = i + 1\n }\n }\n if (last === 0) {\n result = str\n } else if (last !== i) {\n result += str.slice(last)\n }\n return result\n}\n\n// Full version: supports all options\nfunction stringifyFullFn (key, parent, stack, replacer, indent) {\n var i, res, join\n const originalIndentation = indentation\n var value = parent[key]\n\n if (typeof value === 'object' && value !== null && typeof value.toJSON === 'function') {\n value = value.toJSON(key)\n }\n value = replacer.call(parent, key, value)\n\n switch (typeof value) {\n case 'object':\n if (value === null) {\n return 'null'\n }\n for (i = 0; i < stack.length; i++) {\n if (stack[i] === value) {\n return '\"[Circular]\"'\n }\n }\n if (Array.isArray(value)) {\n if (value.length === 0) {\n return '[]'\n }\n stack.push(value)\n res = '['\n indentation += indent\n res += `\\n${indentation}`\n join = `,\\n${indentation}`\n // Use null as placeholder for non-JSON values.\n for (i = 0; i < value.length - 1; i++) {\n const tmp = stringifyFullFn(i, value, stack, replacer, indent)\n res += tmp !== undefined ? tmp : 'null'\n res += join\n }\n const tmp = stringifyFullFn(i, value, stack, replacer, indent)\n res += tmp !== undefined ? tmp : 'null'\n if (indentation !== '') {\n res += `\\n${originalIndentation}`\n }\n res += ']'\n stack.pop()\n indentation = originalIndentation\n return res\n }\n\n var keys = insertSort(Object.keys(value))\n if (keys.length === 0) {\n return '{}'\n }\n stack.push(value)\n res = '{'\n indentation += indent\n res += `\\n${indentation}`\n join = `,\\n${indentation}`\n var separator = ''\n for (i = 0; i < keys.length; i++) {\n key = keys[i]\n const tmp = stringifyFullFn(key, value, stack, replacer, indent)\n if (tmp !== undefined) {\n res += `${separator}\"${strEscape(key)}\": ${tmp}`\n separator = join\n }\n }\n if (separator !== '') {\n res += `\\n${originalIndentation}`\n } else {\n res = '{'\n }\n res += '}'\n stack.pop()\n indentation = originalIndentation\n return res\n case 'string':\n return `\"${strEscape(value)}\"`\n case 'number':\n // JSON numbers must be finite. Encode non-finite numbers as null.\n return isFinite(value) ? String(value) : 'null'\n case 'boolean':\n return value === true ? 'true' : 'false'\n }\n}\n\nfunction stringifyFullArr (key, value, stack, replacer, indent) {\n var i, res, join\n const originalIndentation = indentation\n\n if (typeof value === 'object' && value !== null && typeof value.toJSON === 'function') {\n value = value.toJSON(key)\n }\n\n switch (typeof value) {\n case 'object':\n if (value === null) {\n return 'null'\n }\n for (i = 0; i < stack.length; i++) {\n if (stack[i] === value) {\n return '\"[Circular]\"'\n }\n }\n if (Array.isArray(value)) {\n if (value.length === 0) {\n return '[]'\n }\n stack.push(value)\n res = '['\n indentation += indent\n res += `\\n${indentation}`\n join = `,\\n${indentation}`\n // Use null as placeholder for non-JSON values.\n for (i = 0; i < value.length - 1; i++) {\n const tmp = stringifyFullArr(i, value[i], stack, replacer, indent)\n res += tmp !== undefined ? tmp : 'null'\n res += join\n }\n const tmp = stringifyFullArr(i, value[i], stack, replacer, indent)\n res += tmp !== undefined ? tmp : 'null'\n if (indentation !== '') {\n res += `\\n${originalIndentation}`\n }\n res += ']'\n stack.pop()\n indentation = originalIndentation\n return res\n }\n\n if (replacer.length === 0) {\n return '{}'\n }\n stack.push(value)\n res = '{'\n indentation += indent\n res += `\\n${indentation}`\n join = `,\\n${indentation}`\n var separator = ''\n for (i = 0; i < replacer.length; i++) {\n if (typeof replacer[i] === 'string' || typeof replacer[i] === 'number') {\n key = replacer[i]\n const tmp = stringifyFullArr(key, value[key], stack, replacer, indent)\n if (tmp !== undefined) {\n res += `${separator}\"${strEscape(key)}\": ${tmp}`\n separator = join\n }\n }\n }\n if (separator !== '') {\n res += `\\n${originalIndentation}`\n } else {\n res = '{'\n }\n res += '}'\n stack.pop()\n indentation = originalIndentation\n return res\n case 'string':\n return `\"${strEscape(value)}\"`\n case 'number':\n // JSON numbers must be finite. Encode non-finite numbers as null.\n return isFinite(value) ? String(value) : 'null'\n case 'boolean':\n return value === true ? 'true' : 'false'\n }\n}\n\n// Supports only the spacer option\nfunction stringifyIndent (key, value, stack, indent) {\n var i, res, join\n const originalIndentation = indentation\n\n switch (typeof value) {\n case 'object':\n if (value === null) {\n return 'null'\n }\n if (typeof value.toJSON === 'function') {\n value = value.toJSON(key)\n // Prevent calling `toJSON` again.\n if (typeof value !== 'object') {\n return stringifyIndent(key, value, stack, indent)\n }\n if (value === null) {\n return 'null'\n }\n }\n for (i = 0; i < stack.length; i++) {\n if (stack[i] === value) {\n return '\"[Circular]\"'\n }\n }\n\n if (Array.isArray(value)) {\n if (value.length === 0) {\n return '[]'\n }\n stack.push(value)\n res = '['\n indentation += indent\n res += `\\n${indentation}`\n join = `,\\n${indentation}`\n // Use null as placeholder for non-JSON values.\n for (i = 0; i < value.length - 1; i++) {\n const tmp = stringifyIndent(i, value[i], stack, indent)\n res += tmp !== undefined ? tmp : 'null'\n res += join\n }\n const tmp = stringifyIndent(i, value[i], stack, indent)\n res += tmp !== undefined ? tmp : 'null'\n if (indentation !== '') {\n res += `\\n${originalIndentation}`\n }\n res += ']'\n stack.pop()\n indentation = originalIndentation\n return res\n }\n\n var keys = insertSort(Object.keys(value))\n if (keys.length === 0) {\n return '{}'\n }\n stack.push(value)\n res = '{'\n indentation += indent\n res += `\\n${indentation}`\n join = `,\\n${indentation}`\n var separator = ''\n for (i = 0; i < keys.length; i++) {\n key = keys[i]\n const tmp = stringifyIndent(key, value[key], stack, indent)\n if (tmp !== undefined) {\n res += `${separator}\"${strEscape(key)}\": ${tmp}`\n separator = join\n }\n }\n if (separator !== '') {\n res += `\\n${originalIndentation}`\n } else {\n res = '{'\n }\n res += '}'\n stack.pop()\n indentation = originalIndentation\n return res\n case 'string':\n return `\"${strEscape(value)}\"`\n case 'number':\n // JSON numbers must be finite. Encode non-finite numbers as null.\n return isFinite(value) ? String(value) : 'null'\n case 'boolean':\n return value === true ? 'true' : 'false'\n }\n}\n\n// Supports only the replacer option\nfunction stringifyReplacerArr (key, value, stack, replacer) {\n var i, res\n // If the value has a toJSON method, call it to obtain a replacement value.\n if (typeof value === 'object' && value !== null && typeof value.toJSON === 'function') {\n value = value.toJSON(key)\n }\n\n switch (typeof value) {\n case 'object':\n if (value === null) {\n return 'null'\n }\n for (i = 0; i < stack.length; i++) {\n if (stack[i] === value) {\n return '\"[Circular]\"'\n }\n }\n if (Array.isArray(value)) {\n if (value.length === 0) {\n return '[]'\n }\n stack.push(value)\n res = '['\n // Use null as placeholder for non-JSON values.\n for (i = 0; i < value.length - 1; i++) {\n const tmp = stringifyReplacerArr(i, value[i], stack, replacer)\n res += tmp !== undefined ? tmp : 'null'\n res += ','\n }\n const tmp = stringifyReplacerArr(i, value[i], stack, replacer)\n res += tmp !== undefined ? tmp : 'null'\n res += ']'\n stack.pop()\n return res\n }\n\n if (replacer.length === 0) {\n return '{}'\n }\n stack.push(value)\n res = '{'\n var separator = ''\n for (i = 0; i < replacer.length; i++) {\n if (typeof replacer[i] === 'string' || typeof replacer[i] === 'number') {\n key = replacer[i]\n const tmp = stringifyReplacerArr(key, value[key], stack, replacer)\n if (tmp !== undefined) {\n res += `${separator}\"${strEscape(key)}\":${tmp}`\n separator = ','\n }\n }\n }\n res += '}'\n stack.pop()\n return res\n case 'string':\n return `\"${strEscape(value)}\"`\n case 'number':\n // JSON numbers must be finite. Encode non-finite numbers as null.\n return isFinite(value) ? String(value) : 'null'\n case 'boolean':\n return value === true ? 'true' : 'false'\n }\n}\n\nfunction stringifyReplacerFn (key, parent, stack, replacer) {\n var i, res\n var value = parent[key]\n // If the value has a toJSON method, call it to obtain a replacement value.\n if (typeof value === 'object' && value !== null && typeof value.toJSON === 'function') {\n value = value.toJSON(key)\n }\n value = replacer.call(parent, key, value)\n\n switch (typeof value) {\n case 'object':\n if (value === null) {\n return 'null'\n }\n for (i = 0; i < stack.length; i++) {\n if (stack[i] === value) {\n return '\"[Circular]\"'\n }\n }\n if (Array.isArray(value)) {\n if (value.length === 0) {\n return '[]'\n }\n stack.push(value)\n res = '['\n // Use null as placeholder for non-JSON values.\n for (i = 0; i < value.length - 1; i++) {\n const tmp = stringifyReplacerFn(i, value, stack, replacer)\n res += tmp !== undefined ? tmp : 'null'\n res += ','\n }\n const tmp = stringifyReplacerFn(i, value, stack, replacer)\n res += tmp !== undefined ? tmp : 'null'\n res += ']'\n stack.pop()\n return res\n }\n\n var keys = insertSort(Object.keys(value))\n if (keys.length === 0) {\n return '{}'\n }\n stack.push(value)\n res = '{'\n var separator = ''\n for (i = 0; i < keys.length; i++) {\n key = keys[i]\n const tmp = stringifyReplacerFn(key, value, stack, replacer)\n if (tmp !== undefined) {\n res += `${separator}\"${strEscape(key)}\":${tmp}`\n separator = ','\n }\n }\n res += '}'\n stack.pop()\n return res\n case 'string':\n return `\"${strEscape(value)}\"`\n case 'number':\n // JSON numbers must be finite. Encode non-finite numbers as null.\n return isFinite(value) ? String(value) : 'null'\n case 'boolean':\n return value === true ? 'true' : 'false'\n }\n}\n\n// Simple without any options\nfunction stringifySimple (key, value, stack) {\n var i, res\n switch (typeof value) {\n case 'object':\n if (value === null) {\n return 'null'\n }\n if (typeof value.toJSON === 'function') {\n value = value.toJSON(key)\n // Prevent calling `toJSON` again\n if (typeof value !== 'object') {\n return stringifySimple(key, value, stack)\n }\n if (value === null) {\n return 'null'\n }\n }\n for (i = 0; i < stack.length; i++) {\n if (stack[i] === value) {\n return '\"[Circular]\"'\n }\n }\n\n if (Array.isArray(value)) {\n if (value.length === 0) {\n return '[]'\n }\n stack.push(value)\n res = '['\n // Use null as placeholder for non-JSON values.\n for (i = 0; i < value.length - 1; i++) {\n const tmp = stringifySimple(i, value[i], stack)\n res += tmp !== undefined ? tmp : 'null'\n res += ','\n }\n const tmp = stringifySimple(i, value[i], stack)\n res += tmp !== undefined ? tmp : 'null'\n res += ']'\n stack.pop()\n return res\n }\n\n var keys = insertSort(Object.keys(value))\n if (keys.length === 0) {\n return '{}'\n }\n stack.push(value)\n var separator = ''\n res = '{'\n for (i = 0; i < keys.length; i++) {\n key = keys[i]\n const tmp = stringifySimple(key, value[key], stack)\n if (tmp !== undefined) {\n res += `${separator}\"${strEscape(key)}\":${tmp}`\n separator = ','\n }\n }\n res += '}'\n stack.pop()\n return res\n case 'string':\n return `\"${strEscape(value)}\"`\n case 'number':\n // JSON numbers must be finite. Encode non-finite numbers as null.\n // Convert the numbers implicit to a string instead of explicit.\n return isFinite(value) ? String(value) : 'null'\n case 'boolean':\n return value === true ? 'true' : 'false'\n }\n}\n\nfunction insertSort (arr) {\n for (var i = 1; i < arr.length; i++) {\n const tmp = arr[i]\n var j = i\n while (j !== 0 && arr[j - 1] > tmp) {\n arr[j] = arr[j - 1]\n j--\n }\n arr[j] = tmp\n }\n\n return arr\n}\n\nfunction stringify (value, replacer, spacer) {\n var i\n var indent = ''\n indentation = ''\n\n if (arguments.length > 1) {\n // If the spacer parameter is a number, make an indent string containing that\n // many spaces.\n if (typeof spacer === 'number') {\n for (i = 0; i < spacer; i += 1) {\n indent += ' '\n }\n // If the spacer parameter is a string, it will be used as the indent string.\n } else if (typeof spacer === 'string') {\n indent = spacer\n }\n if (indent !== '') {\n if (replacer !== undefined && replacer !== null) {\n if (typeof replacer === 'function') {\n return stringifyFullFn('', { '': value }, [], replacer, indent)\n }\n if (Array.isArray(replacer)) {\n return stringifyFullArr('', value, [], replacer, indent)\n }\n }\n return stringifyIndent('', value, [], indent)\n }\n if (typeof replacer === 'function') {\n return stringifyReplacerFn('', { '': value }, [], replacer)\n }\n if (Array.isArray(replacer)) {\n return stringifyReplacerArr('', value, [], replacer)\n }\n }\n return stringifySimple('', value, [])\n}\n","'use strict'\n\nconst stringify = require('./stable')\n\nmodule.exports = stringify\nstringify.default = stringify\n","/******************************************************************************\nCopyright (c) Microsoft Corporation.\n\nPermission to use, copy, modify, and/or distribute this software for any\npurpose with or without fee is hereby granted.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH\nREGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY\nAND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,\nINDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM\nLOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR\nOTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR\nPERFORMANCE OF THIS SOFTWARE.\n***************************************************************************** */\n/* global Reflect, Promise, SuppressedError, Symbol, Iterator */\n\nvar extendStatics = function(d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };\n return extendStatics(d, b);\n};\n\nexport function __extends(d, b) {\n if (typeof b !== \"function\" && b !== null)\n throw new TypeError(\"Class extends value \" + String(b) + \" is not a constructor or null\");\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n}\n\nexport var __assign = function() {\n __assign = Object.assign || function __assign(t) {\n for (var s, i = 1, n = arguments.length; i < n; i++) {\n s = arguments[i];\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];\n }\n return t;\n }\n return __assign.apply(this, arguments);\n}\n\nexport function __rest(s, e) {\n var t = {};\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)\n t[p] = s[p];\n if (s != null && typeof Object.getOwnPropertySymbols === \"function\")\n for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {\n if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))\n t[p[i]] = s[p[i]];\n }\n return t;\n}\n\nexport function __decorate(decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n}\n\nexport function __param(paramIndex, decorator) {\n return function (target, key) { decorator(target, key, paramIndex); }\n}\n\nexport function __esDecorate(ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {\n function accept(f) { if (f !== void 0 && typeof f !== \"function\") throw new TypeError(\"Function expected\"); return f; }\n var kind = contextIn.kind, key = kind === \"getter\" ? \"get\" : kind === \"setter\" ? \"set\" : \"value\";\n var target = !descriptorIn && ctor ? contextIn[\"static\"] ? ctor : ctor.prototype : null;\n var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});\n var _, done = false;\n for (var i = decorators.length - 1; i >= 0; i--) {\n var context = {};\n for (var p in contextIn) context[p] = p === \"access\" ? {} : contextIn[p];\n for (var p in contextIn.access) context.access[p] = contextIn.access[p];\n context.addInitializer = function (f) { if (done) throw new TypeError(\"Cannot add initializers after decoration has completed\"); extraInitializers.push(accept(f || null)); };\n var result = (0, decorators[i])(kind === \"accessor\" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);\n if (kind === \"accessor\") {\n if (result === void 0) continue;\n if (result === null || typeof result !== \"object\") throw new TypeError(\"Object expected\");\n if (_ = accept(result.get)) descriptor.get = _;\n if (_ = accept(result.set)) descriptor.set = _;\n if (_ = accept(result.init)) initializers.unshift(_);\n }\n else if (_ = accept(result)) {\n if (kind === \"field\") initializers.unshift(_);\n else descriptor[key] = _;\n }\n }\n if (target) Object.defineProperty(target, contextIn.name, descriptor);\n done = true;\n};\n\nexport function __runInitializers(thisArg, initializers, value) {\n var useValue = arguments.length > 2;\n for (var i = 0; i < initializers.length; i++) {\n value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);\n }\n return useValue ? value : void 0;\n};\n\nexport function __propKey(x) {\n return typeof x === \"symbol\" ? x : \"\".concat(x);\n};\n\nexport function __setFunctionName(f, name, prefix) {\n if (typeof name === \"symbol\") name = name.description ? \"[\".concat(name.description, \"]\") : \"\";\n return Object.defineProperty(f, \"name\", { configurable: true, value: prefix ? \"\".concat(prefix, \" \", name) : name });\n};\n\nexport function __metadata(metadataKey, metadataValue) {\n if (typeof Reflect === \"object\" && typeof Reflect.metadata === \"function\") return Reflect.metadata(metadataKey, metadataValue);\n}\n\nexport function __awaiter(thisArg, _arguments, P, generator) {\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n step((generator = generator.apply(thisArg, _arguments || [])).next());\n });\n}\n\nexport function __generator(thisArg, body) {\n var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === \"function\" ? Iterator : Object).prototype);\n return g.next = verb(0), g[\"throw\"] = verb(1), g[\"return\"] = verb(2), typeof Symbol === \"function\" && (g[Symbol.iterator] = function() { return this; }), g;\n function verb(n) { return function (v) { return step([n, v]); }; }\n function step(op) {\n if (f) throw new TypeError(\"Generator is already executing.\");\n while (g && (g = 0, op[0] && (_ = 0)), _) try {\n if (f = 1, y && (t = op[0] & 2 ? y[\"return\"] : op[0] ? y[\"throw\"] || ((t = y[\"return\"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;\n if (y = 0, t) op = [op[0] & 2, t.value];\n switch (op[0]) {\n case 0: case 1: t = op; break;\n case 4: _.label++; return { value: op[1], done: false };\n case 5: _.label++; y = op[1]; op = [0]; continue;\n case 7: op = _.ops.pop(); _.trys.pop(); continue;\n default:\n if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }\n if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }\n if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }\n if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }\n if (t[2]) _.ops.pop();\n _.trys.pop(); continue;\n }\n op = body.call(thisArg, _);\n } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }\n if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };\n }\n}\n\nexport var __createBinding = Object.create ? (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n var desc = Object.getOwnPropertyDescriptor(m, k);\n if (!desc || (\"get\" in desc ? !m.__esModule : desc.writable || desc.configurable)) {\n desc = { enumerable: true, get: function() { return m[k]; } };\n }\n Object.defineProperty(o, k2, desc);\n}) : (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n o[k2] = m[k];\n});\n\nexport function __exportStar(m, o) {\n for (var p in m) if (p !== \"default\" && !Object.prototype.hasOwnProperty.call(o, p)) __createBinding(o, m, p);\n}\n\nexport function __values(o) {\n var s = typeof Symbol === \"function\" && Symbol.iterator, m = s && o[s], i = 0;\n if (m) return m.call(o);\n if (o && typeof o.length === \"number\") return {\n next: function () {\n if (o && i >= o.length) o = void 0;\n return { value: o && o[i++], done: !o };\n }\n };\n throw new TypeError(s ? \"Object is not iterable.\" : \"Symbol.iterator is not defined.\");\n}\n\nexport function __read(o, n) {\n var m = typeof Symbol === \"function\" && o[Symbol.iterator];\n if (!m) return o;\n var i = m.call(o), r, ar = [], e;\n try {\n while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);\n }\n catch (error) { e = { error: error }; }\n finally {\n try {\n if (r && !r.done && (m = i[\"return\"])) m.call(i);\n }\n finally { if (e) throw e.error; }\n }\n return ar;\n}\n\n/** @deprecated */\nexport function __spread() {\n for (var ar = [], i = 0; i < arguments.length; i++)\n ar = ar.concat(__read(arguments[i]));\n return ar;\n}\n\n/** @deprecated */\nexport function __spreadArrays() {\n for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;\n for (var r = Array(s), k = 0, i = 0; i < il; i++)\n for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)\n r[k] = a[j];\n return r;\n}\n\nexport function __spreadArray(to, from, pack) {\n if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {\n if (ar || !(i in from)) {\n if (!ar) ar = Array.prototype.slice.call(from, 0, i);\n ar[i] = from[i];\n }\n }\n return to.concat(ar || Array.prototype.slice.call(from));\n}\n\nexport function __await(v) {\n return this instanceof __await ? (this.v = v, this) : new __await(v);\n}\n\nexport function __asyncGenerator(thisArg, _arguments, generator) {\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\n var g = generator.apply(thisArg, _arguments || []), i, q = [];\n return i = Object.create((typeof AsyncIterator === \"function\" ? AsyncIterator : Object).prototype), verb(\"next\"), verb(\"throw\"), verb(\"return\", awaitReturn), i[Symbol.asyncIterator] = function () { return this; }, i;\n function awaitReturn(f) { return function (v) { return Promise.resolve(v).then(f, reject); }; }\n function verb(n, f) { if (g[n]) { i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; if (f) i[n] = f(i[n]); } }\n function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }\n function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }\n function fulfill(value) { resume(\"next\", value); }\n function reject(value) { resume(\"throw\", value); }\n function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }\n}\n\nexport function __asyncDelegator(o) {\n var i, p;\n return i = {}, verb(\"next\"), verb(\"throw\", function (e) { throw e; }), verb(\"return\"), i[Symbol.iterator] = function () { return this; }, i;\n function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: false } : f ? f(v) : v; } : f; }\n}\n\nexport function __asyncValues(o) {\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\n var m = o[Symbol.asyncIterator], i;\n return m ? m.call(o) : (o = typeof __values === \"function\" ? __values(o) : o[Symbol.iterator](), i = {}, verb(\"next\"), verb(\"throw\"), verb(\"return\"), i[Symbol.asyncIterator] = function () { return this; }, i);\n function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }\n function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }\n}\n\nexport function __makeTemplateObject(cooked, raw) {\n if (Object.defineProperty) { Object.defineProperty(cooked, \"raw\", { value: raw }); } else { cooked.raw = raw; }\n return cooked;\n};\n\nvar __setModuleDefault = Object.create ? (function(o, v) {\n Object.defineProperty(o, \"default\", { enumerable: true, value: v });\n}) : function(o, v) {\n o[\"default\"] = v;\n};\n\nvar ownKeys = function(o) {\n ownKeys = Object.getOwnPropertyNames || function (o) {\n var ar = [];\n for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;\n return ar;\n };\n return ownKeys(o);\n};\n\nexport function __importStar(mod) {\n if (mod && mod.__esModule) return mod;\n var result = {};\n if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== \"default\") __createBinding(result, mod, k[i]);\n __setModuleDefault(result, mod);\n return result;\n}\n\nexport function __importDefault(mod) {\n return (mod && mod.__esModule) ? mod : { default: mod };\n}\n\nexport function __classPrivateFieldGet(receiver, state, kind, f) {\n if (kind === \"a\" && !f) throw new TypeError(\"Private accessor was defined without a getter\");\n if (typeof state === \"function\" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError(\"Cannot read private member from an object whose class did not declare it\");\n return kind === \"m\" ? f : kind === \"a\" ? f.call(receiver) : f ? f.value : state.get(receiver);\n}\n\nexport function __classPrivateFieldSet(receiver, state, value, kind, f) {\n if (kind === \"m\") throw new TypeError(\"Private method is not writable\");\n if (kind === \"a\" && !f) throw new TypeError(\"Private accessor was defined without a setter\");\n if (typeof state === \"function\" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError(\"Cannot write private member to an object whose class did not declare it\");\n return (kind === \"a\" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;\n}\n\nexport function __classPrivateFieldIn(state, receiver) {\n if (receiver === null || (typeof receiver !== \"object\" && typeof receiver !== \"function\")) throw new TypeError(\"Cannot use 'in' operator on non-object\");\n return typeof state === \"function\" ? receiver === state : state.has(receiver);\n}\n\nexport function __addDisposableResource(env, value, async) {\n if (value !== null && value !== void 0) {\n if (typeof value !== \"object\" && typeof value !== \"function\") throw new TypeError(\"Object expected.\");\n var dispose, inner;\n if (async) {\n if (!Symbol.asyncDispose) throw new TypeError(\"Symbol.asyncDispose is not defined.\");\n dispose = value[Symbol.asyncDispose];\n }\n if (dispose === void 0) {\n if (!Symbol.dispose) throw new TypeError(\"Symbol.dispose is not defined.\");\n dispose = value[Symbol.dispose];\n if (async) inner = dispose;\n }\n if (typeof dispose !== \"function\") throw new TypeError(\"Object not disposable.\");\n if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };\n env.stack.push({ value: value, dispose: dispose, async: async });\n }\n else if (async) {\n env.stack.push({ async: true });\n }\n return value;\n}\n\nvar _SuppressedError = typeof SuppressedError === \"function\" ? SuppressedError : function (error, suppressed, message) {\n var e = new Error(message);\n return e.name = \"SuppressedError\", e.error = error, e.suppressed = suppressed, e;\n};\n\nexport function __disposeResources(env) {\n function fail(e) {\n env.error = env.hasError ? new _SuppressedError(e, env.error, \"An error was suppressed during disposal.\") : e;\n env.hasError = true;\n }\n var r, s = 0;\n function next() {\n while (r = env.stack.pop()) {\n try {\n if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next);\n if (r.dispose) {\n var result = r.dispose.call(r.value);\n if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) { fail(e); return next(); });\n }\n else s |= 1;\n }\n catch (e) {\n fail(e);\n }\n }\n if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve();\n if (env.hasError) throw env.error;\n }\n return next();\n}\n\nexport function __rewriteRelativeImportExtension(path, preserveJsx) {\n if (typeof path === \"string\" && /^\\.\\.?\\//.test(path)) {\n return path.replace(/\\.(tsx)$|((?:\\.d)?)((?:\\.[^./]+?)?)\\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {\n return tsx ? preserveJsx ? \".jsx\" : \".js\" : d && (!ext || !cm) ? m : (d + ext + \".\" + cm.toLowerCase() + \"js\");\n });\n }\n return path;\n}\n\nexport default {\n __extends,\n __assign,\n __rest,\n __decorate,\n __param,\n __esDecorate,\n __runInitializers,\n __propKey,\n __setFunctionName,\n __metadata,\n __awaiter,\n __generator,\n __createBinding,\n __exportStar,\n __values,\n __read,\n __spread,\n __spreadArrays,\n __spreadArray,\n __await,\n __asyncGenerator,\n __asyncDelegator,\n __asyncValues,\n __makeTemplateObject,\n __importStar,\n __importDefault,\n __classPrivateFieldGet,\n __classPrivateFieldSet,\n __classPrivateFieldIn,\n __addDisposableResource,\n __disposeResources,\n __rewriteRelativeImportExtension,\n};\n",null,null,null,null,null,null,null,null,null,"/*!\n * EventEmitter v5.2.9 - git.io/ee\n * Unlicense - http://unlicense.org/\n * Oliver Caldwell - https://oli.me.uk/\n * @preserve\n */\n\n;(function (exports) {\n 'use strict';\n\n /**\n * Class for managing events.\n * Can be extended to provide event functionality in other classes.\n *\n * @class EventEmitter Manages event registering and emitting.\n */\n function EventEmitter() {}\n\n // Shortcuts to improve speed and size\n var proto = EventEmitter.prototype;\n var originalGlobalValue = exports.EventEmitter;\n\n /**\n * Finds the index of the listener for the event in its storage array.\n *\n * @param {Function[]} listeners Array of listeners to search through.\n * @param {Function} listener Method to look for.\n * @return {Number} Index of the specified listener, -1 if not found\n * @api private\n */\n function indexOfListener(listeners, listener) {\n var i = listeners.length;\n while (i--) {\n if (listeners[i].listener === listener) {\n return i;\n }\n }\n\n return -1;\n }\n\n /**\n * Alias a method while keeping the context correct, to allow for overwriting of target method.\n *\n * @param {String} name The name of the target method.\n * @return {Function} The aliased method\n * @api private\n */\n function alias(name) {\n return function aliasClosure() {\n return this[name].apply(this, arguments);\n };\n }\n\n /**\n * Returns the listener array for the specified event.\n * Will initialise the event object and listener arrays if required.\n * Will return an object if you use a regex search. The object contains keys for each matched event. So /ba[rz]/ might return an object containing bar and baz. But only if you have either defined them with defineEvent or added some listeners to them.\n * Each property in the object response is an array of listener functions.\n *\n * @param {String|RegExp} evt Name of the event to return the listeners from.\n * @return {Function[]|Object} All listener functions for the event.\n */\n proto.getListeners = function getListeners(evt) {\n var events = this._getEvents();\n var response;\n var key;\n\n // Return a concatenated array of all matching events if\n // the selector is a regular expression.\n if (evt instanceof RegExp) {\n response = {};\n for (key in events) {\n if (events.hasOwnProperty(key) && evt.test(key)) {\n response[key] = events[key];\n }\n }\n }\n else {\n response = events[evt] || (events[evt] = []);\n }\n\n return response;\n };\n\n /**\n * Takes a list of listener objects and flattens it into a list of listener functions.\n *\n * @param {Object[]} listeners Raw listener objects.\n * @return {Function[]} Just the listener functions.\n */\n proto.flattenListeners = function flattenListeners(listeners) {\n var flatListeners = [];\n var i;\n\n for (i = 0; i < listeners.length; i += 1) {\n flatListeners.push(listeners[i].listener);\n }\n\n return flatListeners;\n };\n\n /**\n * Fetches the requested listeners via getListeners but will always return the results inside an object. This is mainly for internal use but others may find it useful.\n *\n * @param {String|RegExp} evt Name of the event to return the listeners from.\n * @return {Object} All listener functions for an event in an object.\n */\n proto.getListenersAsObject = function getListenersAsObject(evt) {\n var listeners = this.getListeners(evt);\n var response;\n\n if (listeners instanceof Array) {\n response = {};\n response[evt] = listeners;\n }\n\n return response || listeners;\n };\n\n function isValidListener (listener) {\n if (typeof listener === 'function' || listener instanceof RegExp) {\n return true\n } else if (listener && typeof listener === 'object') {\n return isValidListener(listener.listener)\n } else {\n return false\n }\n }\n\n /**\n * Adds a listener function to the specified event.\n * The listener will not be added if it is a duplicate.\n * If the listener returns true then it will be removed after it is called.\n * If you pass a regular expression as the event name then the listener will be added to all events that match it.\n *\n * @param {String|RegExp} evt Name of the event to attach the listener to.\n * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling.\n * @return {Object} Current instance of EventEmitter for chaining.\n */\n proto.addListener = function addListener(evt, listener) {\n if (!isValidListener(listener)) {\n throw new TypeError('listener must be a function');\n }\n\n var listeners = this.getListenersAsObject(evt);\n var listenerIsWrapped = typeof listener === 'object';\n var key;\n\n for (key in listeners) {\n if (listeners.hasOwnProperty(key) && indexOfListener(listeners[key], listener) === -1) {\n listeners[key].push(listenerIsWrapped ? listener : {\n listener: listener,\n once: false\n });\n }\n }\n\n return this;\n };\n\n /**\n * Alias of addListener\n */\n proto.on = alias('addListener');\n\n /**\n * Semi-alias of addListener. It will add a listener that will be\n * automatically removed after its first execution.\n *\n * @param {String|RegExp} evt Name of the event to attach the listener to.\n * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling.\n * @return {Object} Current instance of EventEmitter for chaining.\n */\n proto.addOnceListener = function addOnceListener(evt, listener) {\n return this.addListener(evt, {\n listener: listener,\n once: true\n });\n };\n\n /**\n * Alias of addOnceListener.\n */\n proto.once = alias('addOnceListener');\n\n /**\n * Defines an event name. This is required if you want to use a regex to add a listener to multiple events at once. If you don't do this then how do you expect it to know what event to add to? Should it just add to every possible match for a regex? No. That is scary and bad.\n * You need to tell it what event names should be matched by a regex.\n *\n * @param {String} evt Name of the event to create.\n * @return {Object} Current instance of EventEmitter for chaining.\n */\n proto.defineEvent = function defineEvent(evt) {\n this.getListeners(evt);\n return this;\n };\n\n /**\n * Uses defineEvent to define multiple events.\n *\n * @param {String[]} evts An array of event names to define.\n * @return {Object} Current instance of EventEmitter for chaining.\n */\n proto.defineEvents = function defineEvents(evts) {\n for (var i = 0; i < evts.length; i += 1) {\n this.defineEvent(evts[i]);\n }\n return this;\n };\n\n /**\n * Removes a listener function from the specified event.\n * When passed a regular expression as the event name, it will remove the listener from all events that match it.\n *\n * @param {String|RegExp} evt Name of the event to remove the listener from.\n * @param {Function} listener Method to remove from the event.\n * @return {Object} Current instance of EventEmitter for chaining.\n */\n proto.removeListener = function removeListener(evt, listener) {\n var listeners = this.getListenersAsObject(evt);\n var index;\n var key;\n\n for (key in listeners) {\n if (listeners.hasOwnProperty(key)) {\n index = indexOfListener(listeners[key], listener);\n\n if (index !== -1) {\n listeners[key].splice(index, 1);\n }\n }\n }\n\n return this;\n };\n\n /**\n * Alias of removeListener\n */\n proto.off = alias('removeListener');\n\n /**\n * Adds listeners in bulk using the manipulateListeners method.\n * If you pass an object as the first argument you can add to multiple events at once. The object should contain key value pairs of events and listeners or listener arrays. You can also pass it an event name and an array of listeners to be added.\n * You can also pass it a regular expression to add the array of listeners to all events that match it.\n * Yeah, this function does quite a bit. That's probably a bad thing.\n *\n * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to add to multiple events at once.\n * @param {Function[]} [listeners] An optional array of listener functions to add.\n * @return {Object} Current instance of EventEmitter for chaining.\n */\n proto.addListeners = function addListeners(evt, listeners) {\n // Pass through to manipulateListeners\n return this.manipulateListeners(false, evt, listeners);\n };\n\n /**\n * Removes listeners in bulk using the manipulateListeners method.\n * If you pass an object as the first argument you can remove from multiple events at once. The object should contain key value pairs of events and listeners or listener arrays.\n * You can also pass it an event name and an array of listeners to be removed.\n * You can also pass it a regular expression to remove the listeners from all events that match it.\n *\n * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to remove from multiple events at once.\n * @param {Function[]} [listeners] An optional array of listener functions to remove.\n * @return {Object} Current instance of EventEmitter for chaining.\n */\n proto.removeListeners = function removeListeners(evt, listeners) {\n // Pass through to manipulateListeners\n return this.manipulateListeners(true, evt, listeners);\n };\n\n /**\n * Edits listeners in bulk. The addListeners and removeListeners methods both use this to do their job. You should really use those instead, this is a little lower level.\n * The first argument will determine if the listeners are removed (true) or added (false).\n * If you pass an object as the second argument you can add/remove from multiple events at once. The object should contain key value pairs of events and listeners or listener arrays.\n * You can also pass it an event name and an array of listeners to be added/removed.\n * You can also pass it a regular expression to manipulate the listeners of all events that match it.\n *\n * @param {Boolean} remove True if you want to remove listeners, false if you want to add.\n * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to add/remove from multiple events at once.\n * @param {Function[]} [listeners] An optional array of listener functions to add/remove.\n * @return {Object} Current instance of EventEmitter for chaining.\n */\n proto.manipulateListeners = function manipulateListeners(remove, evt, listeners) {\n var i;\n var value;\n var single = remove ? this.removeListener : this.addListener;\n var multiple = remove ? this.removeListeners : this.addListeners;\n\n // If evt is an object then pass each of its properties to this method\n if (typeof evt === 'object' && !(evt instanceof RegExp)) {\n for (i in evt) {\n if (evt.hasOwnProperty(i) && (value = evt[i])) {\n // Pass the single listener straight through to the singular method\n if (typeof value === 'function') {\n single.call(this, i, value);\n }\n else {\n // Otherwise pass back to the multiple function\n multiple.call(this, i, value);\n }\n }\n }\n }\n else {\n // So evt must be a string\n // And listeners must be an array of listeners\n // Loop over it and pass each one to the multiple method\n i = listeners.length;\n while (i--) {\n single.call(this, evt, listeners[i]);\n }\n }\n\n return this;\n };\n\n /**\n * Removes all listeners from a specified event.\n * If you do not specify an event then all listeners will be removed.\n * That means every event will be emptied.\n * You can also pass a regex to remove all events that match it.\n *\n * @param {String|RegExp} [evt] Optional name of the event to remove all listeners for. Will remove from every event if not passed.\n * @return {Object} Current instance of EventEmitter for chaining.\n */\n proto.removeEvent = function removeEvent(evt) {\n var type = typeof evt;\n var events = this._getEvents();\n var key;\n\n // Remove different things depending on the state of evt\n if (type === 'string') {\n // Remove all listeners for the specified event\n delete events[evt];\n }\n else if (evt instanceof RegExp) {\n // Remove all events matching the regex.\n for (key in events) {\n if (events.hasOwnProperty(key) && evt.test(key)) {\n delete events[key];\n }\n }\n }\n else {\n // Remove all listeners in all events\n delete this._events;\n }\n\n return this;\n };\n\n /**\n * Alias of removeEvent.\n *\n * Added to mirror the node API.\n */\n proto.removeAllListeners = alias('removeEvent');\n\n /**\n * Emits an event of your choice.\n * When emitted, every listener attached to that event will be executed.\n * If you pass the optional argument array then those arguments will be passed to every listener upon execution.\n * Because it uses `apply`, your array of arguments will be passed as if you wrote them out separately.\n * So they will not arrive within the array on the other side, they will be separate.\n * You can also pass a regular expression to emit to all events that match it.\n *\n * @param {String|RegExp} evt Name of the event to emit and execute listeners for.\n * @param {Array} [args] Optional array of arguments to be passed to each listener.\n * @return {Object} Current instance of EventEmitter for chaining.\n */\n proto.emitEvent = function emitEvent(evt, args) {\n var listenersMap = this.getListenersAsObject(evt);\n var listeners;\n var listener;\n var i;\n var key;\n var response;\n\n for (key in listenersMap) {\n if (listenersMap.hasOwnProperty(key)) {\n listeners = listenersMap[key].slice(0);\n\n for (i = 0; i < listeners.length; i++) {\n // If the listener returns true then it shall be removed from the event\n // The function is executed either with a basic call or an apply if there is an args array\n listener = listeners[i];\n\n if (listener.once === true) {\n this.removeListener(evt, listener.listener);\n }\n\n response = listener.listener.apply(this, args || []);\n\n if (response === this._getOnceReturnValue()) {\n this.removeListener(evt, listener.listener);\n }\n }\n }\n }\n\n return this;\n };\n\n /**\n * Alias of emitEvent\n */\n proto.trigger = alias('emitEvent');\n\n /**\n * Subtly different from emitEvent in that it will pass its arguments on to the listeners, as opposed to taking a single array of arguments to pass on.\n * As with emitEvent, you can pass a regex in place of the event name to emit to all events that match it.\n *\n * @param {String|RegExp} evt Name of the event to emit and execute listeners for.\n * @param {...*} Optional additional arguments to be passed to each listener.\n * @return {Object} Current instance of EventEmitter for chaining.\n */\n proto.emit = function emit(evt) {\n var args = Array.prototype.slice.call(arguments, 1);\n return this.emitEvent(evt, args);\n };\n\n /**\n * Sets the current value to check against when executing listeners. If a\n * listeners return value matches the one set here then it will be removed\n * after execution. This value defaults to true.\n *\n * @param {*} value The new value to check for when executing listeners.\n * @return {Object} Current instance of EventEmitter for chaining.\n */\n proto.setOnceReturnValue = function setOnceReturnValue(value) {\n this._onceReturnValue = value;\n return this;\n };\n\n /**\n * Fetches the current value to check against when executing listeners. If\n * the listeners return value matches this one then it should be removed\n * automatically. It will return true by default.\n *\n * @return {*|Boolean} The current value to check for or the default, true.\n * @api private\n */\n proto._getOnceReturnValue = function _getOnceReturnValue() {\n if (this.hasOwnProperty('_onceReturnValue')) {\n return this._onceReturnValue;\n }\n else {\n return true;\n }\n };\n\n /**\n * Fetches the events object and creates one if required.\n *\n * @return {Object} The events storage object.\n * @api private\n */\n proto._getEvents = function _getEvents() {\n return this._events || (this._events = {});\n };\n\n /**\n * Reverts the global {@link EventEmitter} to its previous value and returns a reference to this version.\n *\n * @return {Function} Non conflicting EventEmitter class.\n */\n EventEmitter.noConflict = function noConflict() {\n exports.EventEmitter = originalGlobalValue;\n return EventEmitter;\n };\n\n // Expose the class either via AMD, CommonJS or the global object\n if (typeof define === 'function' && define.amd) {\n define(function () {\n return EventEmitter;\n });\n }\n else if (typeof module === 'object' && module.exports){\n module.exports = EventEmitter;\n }\n else {\n exports.EventEmitter = EventEmitter;\n }\n}(typeof window !== 'undefined' ? window : this || {}));\n",null,null,null,"var isEqual = require('lodash/isEqual')\nvar sortBy = require('lodash/sortBy')\nvar uniq = require('lodash/uniq')\nvar uniqWith = require('lodash/uniqWith')\nvar defaults = require('lodash/defaults')\nvar intersectionWith = require('lodash/intersectionWith')\nvar isPlainObject = require('lodash/isPlainObject')\nvar isBoolean = require('lodash/isBoolean')\n\nvar normalizeArray = val => Array.isArray(val)\n ? val : [val]\nvar undef = val => val === undefined\nvar keys = obj => isPlainObject(obj) || Array.isArray(obj) ? Object.keys(obj) : []\nvar has = (obj, key) => obj.hasOwnProperty(key)\nvar stringArray = arr => sortBy(uniq(arr))\nvar undefEmpty = val => undef(val) || (Array.isArray(val) && val.length === 0)\nvar keyValEqual = (a, b, key, compare) => b && has(b, key) && a && has(a, key) && compare(a[key], b[key])\nvar undefAndZero = (a, b) => (undef(a) && b === 0) || (undef(b) && a === 0) || isEqual(a, b)\nvar falseUndefined = (a, b) => (undef(a) && b === false) || (undef(b) && a === false) || isEqual(a, b)\nvar emptySchema = schema => undef(schema) || isEqual(schema, {}) || schema === true\nvar emptyObjUndef = schema => undef(schema) || isEqual(schema, {})\nvar isSchema = val => undef(val) || isPlainObject(val) || val === true || val === false\n\nfunction undefArrayEqual(a, b) {\n if (undefEmpty(a) && undefEmpty(b)) {\n return true\n } else {\n return isEqual(stringArray(a), stringArray(b))\n }\n}\n\nfunction unsortedNormalizedArray(a, b) {\n a = normalizeArray(a)\n b = normalizeArray(b)\n return isEqual(stringArray(a), stringArray(b))\n}\n\nfunction schemaGroup(a, b, key, compare) {\n var allProps = uniq(keys(a).concat(keys(b)))\n if (emptyObjUndef(a) && emptyObjUndef(b)) {\n return true\n } else if (emptyObjUndef(a) && keys(b).length) {\n return false\n } else if (emptyObjUndef(b) && keys(a).length) {\n return false\n }\n\n return allProps.every(function(key) {\n var aVal = a[key]\n var bVal = b[key]\n if (Array.isArray(aVal) && Array.isArray(bVal)) {\n return isEqual(stringArray(a), stringArray(b))\n } else if (Array.isArray(aVal) && !Array.isArray(bVal)) {\n return false\n } else if (Array.isArray(bVal) && !Array.isArray(aVal)) {\n return false\n }\n return keyValEqual(a, b, key, compare)\n })\n}\n\nfunction items(a, b, key, compare) {\n if (isPlainObject(a) && isPlainObject(b)) {\n return compare(a, b)\n } else if (Array.isArray(a) && Array.isArray(b)) {\n return schemaGroup(a, b, key, compare)\n } else {\n return isEqual(a, b)\n }\n}\n\nfunction unsortedArray(a, b, key, compare) {\n var uniqueA = uniqWith(a, compare)\n var uniqueB = uniqWith(b, compare)\n var inter = intersectionWith(uniqueA, uniqueB, compare)\n return inter.length === Math.max(uniqueA.length, uniqueB.length)\n}\n\nvar comparers = {\n title: isEqual,\n uniqueItems: falseUndefined,\n minLength: undefAndZero,\n minItems: undefAndZero,\n minProperties: undefAndZero,\n required: undefArrayEqual,\n enum: undefArrayEqual,\n type: unsortedNormalizedArray,\n items: items,\n anyOf: unsortedArray,\n allOf: unsortedArray,\n oneOf: unsortedArray,\n properties: schemaGroup,\n patternProperties: schemaGroup,\n dependencies: schemaGroup\n}\n\nvar acceptsUndefined = [\n 'properties',\n 'patternProperties',\n 'dependencies',\n 'uniqueItems',\n 'minLength',\n 'minItems',\n 'minProperties',\n 'required'\n]\n\nvar schemaProps = ['additionalProperties', 'additionalItems', 'contains', 'propertyNames', 'not']\n\nfunction compare(a, b, options) {\n options = defaults(options, {\n ignore: []\n })\n\n if (emptySchema(a) && emptySchema(b)) {\n return true\n }\n\n if (!isSchema(a) || !isSchema(b)) {\n throw new Error('Either of the values are not a JSON schema.')\n }\n if (a === b) {\n return true\n }\n\n if (isBoolean(a) && isBoolean(b)) {\n return a === b\n }\n\n if ((a === undefined && b === false) || (b === undefined && a === false)) {\n return false\n }\n\n if ((undef(a) && !undef(b)) || (!undef(a) && undef(b))) {\n return false\n }\n\n var allKeys = uniq(Object.keys(a).concat(Object.keys(b)))\n\n if (options.ignore.length) {\n allKeys = allKeys.filter(k => options.ignore.indexOf(k) === -1)\n }\n\n if (!allKeys.length) {\n return true\n }\n\n function innerCompare(a, b) {\n return compare(a, b, options)\n }\n\n return allKeys.every(function(key) {\n var aValue = a[key]\n var bValue = b[key]\n\n if (schemaProps.indexOf(key) !== -1) {\n return compare(aValue, bValue, options)\n }\n\n var comparer = comparers[key]\n if (!comparer) {\n comparer = isEqual\n }\n\n // do simple lodash check first\n if (isEqual(aValue, bValue)) {\n return true\n }\n\n if (acceptsUndefined.indexOf(key) === -1) {\n if ((!has(a, key) && has(b, key)) || (has(a, key) && !has(b, key))) {\n return aValue === bValue\n }\n }\n\n var result = comparer(aValue, bValue, key, innerCompare)\n if (!isBoolean(result)) {\n throw new Error('Comparer must return true or false')\n }\n return result\n })\n}\n\nmodule.exports = compare\n","'use strict';\n\n/**\n* FUNCTION: isArray( value )\n*\tValidates if a value is an array.\n*\n* @param {*} value - value to be validated\n* @returns {Boolean} boolean indicating whether value is an array\n*/\nfunction isArray( value ) {\n\treturn Object.prototype.toString.call( value ) === '[object Array]';\n} // end FUNCTION isArray()\n\n// EXPORTS //\n\nmodule.exports = Array.isArray || isArray;\n","/**\n*\n*\tVALIDATE: number\n*\n*\n*\tDESCRIPTION:\n*\t\t- Validates if a value is a number.\n*\n*\n*\tNOTES:\n*\t\t[1]\n*\n*\n*\tTODO:\n*\t\t[1]\n*\n*\n*\tLICENSE:\n*\t\tMIT\n*\n*\tCopyright (c) 2014. Athan Reines.\n*\n*\n*\tAUTHOR:\n*\t\tAthan Reines. kgryte@gmail.com. 2014.\n*\n*/\n\n'use strict';\n\n/**\n* FUNCTION: isNumber( value )\n*\tValidates if a value is a number.\n*\n* @param {*} value - value to be validated\n* @returns {Boolean} boolean indicating whether value is a number\n*/\nfunction isNumber( value ) {\n\treturn ( typeof value === 'number' || Object.prototype.toString.call( value ) === '[object Number]' ) && value.valueOf() === value.valueOf();\n} // end FUNCTION isNumber()\n\n\n// EXPORTS //\n\nmodule.exports = isNumber;\n","/**\n*\n*\tVALIDATE: integer\n*\n*\n*\tDESCRIPTION:\n*\t\t- Validates if a value is an integer.\n*\n*\n*\tNOTES:\n*\t\t[1]\n*\n*\n*\tTODO:\n*\t\t[1]\n*\n*\n*\tLICENSE:\n*\t\tMIT\n*\n*\tCopyright (c) 2014. Athan Reines.\n*\n*\n*\tAUTHOR:\n*\t\tAthan Reines. kgryte@gmail.com. 2014.\n*\n*/\n\n'use strict';\n\n// MODULES //\n\nvar isNumber = require( 'validate.io-number' );\n\n\n// ISINTEGER //\n\n/**\n* FUNCTION: isInteger( value )\n*\tValidates if a value is an integer.\n*\n* @param {Number} value - value to be validated\n* @returns {Boolean} boolean indicating whether value is an integer\n*/\nfunction isInteger( value ) {\n\treturn isNumber( value ) && value%1 === 0;\n} // end FUNCTION isInteger()\n\n\n// EXPORTS //\n\nmodule.exports = isInteger;\n","/**\n*\n*\tVALIDATE: integer-array\n*\n*\n*\tDESCRIPTION:\n*\t\t- Validates if a value is an integer array.\n*\n*\n*\tNOTES:\n*\t\t[1]\n*\n*\n*\tTODO:\n*\t\t[1]\n*\n*\n*\tLICENSE:\n*\t\tMIT\n*\n*\tCopyright (c) 2015. Athan Reines.\n*\n*\n*\tAUTHOR:\n*\t\tAthan Reines. kgryte@gmail.com. 2015.\n*\n*/\n\n'use strict';\n\n// MODULES //\n\nvar isArray = require( 'validate.io-array' ),\n\tisInteger = require( 'validate.io-integer' );\n\n\n// IS INTEGER ARRAY //\n\n/**\n* FUNCTION: isIntegerArray( value )\n*\tValidates if a value is an integer array.\n*\n* @param {*} value - value to be validated\n* @returns {Boolean} boolean indicating if a value is an integer array\n*/\nfunction isIntegerArray( value ) {\n\tvar len;\n\tif ( !isArray( value ) ) {\n\t\treturn false;\n\t}\n\tlen = value.length;\n\tif ( !len ) {\n\t\treturn false;\n\t}\n\tfor ( var i = 0; i < len; i++ ) {\n\t\tif ( !isInteger( value[i] ) ) {\n\t\t\treturn false;\n\t\t}\n\t}\n\treturn true;\n} // end FUNCTION isIntegerArray()\n\n\n// EXPORTS //\n\nmodule.exports = isIntegerArray;\n","/**\n*\n*\tVALIDATE: function\n*\n*\n*\tDESCRIPTION:\n*\t\t- Validates if a value is a function.\n*\n*\n*\tNOTES:\n*\t\t[1]\n*\n*\n*\tTODO:\n*\t\t[1]\n*\n*\n*\tLICENSE:\n*\t\tMIT\n*\n*\tCopyright (c) 2014. Athan Reines.\n*\n*\n*\tAUTHOR:\n*\t\tAthan Reines. kgryte@gmail.com. 2014.\n*\n*/\n\n'use strict';\n\n/**\n* FUNCTION: isFunction( value )\n*\tValidates if a value is a function.\n*\n* @param {*} value - value to be validated\n* @returns {Boolean} boolean indicating whether value is a function\n*/\nfunction isFunction( value ) {\n\treturn ( typeof value === 'function' );\n} // end FUNCTION isFunction()\n\n\n// EXPORTS //\n\nmodule.exports = isFunction;\n","'use strict';\n\n// MODULES //\n\nvar isArray = require( 'validate.io-array' ),\n\tisIntegerArray = require( 'validate.io-integer-array' ),\n\tisFunction = require( 'validate.io-function' );\n\n\n// VARIABLES //\n\nvar MAXINT = Math.pow( 2, 31 ) - 1;\n\n\n// FUNCTIONS //\n\n/**\n* FUNCTION: gcd( a, b )\n*\tComputes the greatest common divisor of two integers `a` and `b`, using the binary GCD algorithm.\n*\n* @param {Number} a - integer\n* @param {Number} b - integer\n* @returns {Number} greatest common divisor\n*/\nfunction gcd( a, b ) {\n\tvar k = 1,\n\t\tt;\n\t// Simple cases:\n\tif ( a === 0 ) {\n\t\treturn b;\n\t}\n\tif ( b === 0 ) {\n\t\treturn a;\n\t}\n\t// Reduce `a` and/or `b` to odd numbers and keep track of the greatest power of 2 dividing both `a` and `b`...\n\twhile ( a%2 === 0 && b%2 === 0 ) {\n\t\ta = a / 2; // right shift\n\t\tb = b / 2; // right shift\n\t\tk = k * 2; // left shift\n\t}\n\t// Reduce `a` to an odd number...\n\twhile ( a%2 === 0 ) {\n\t\ta = a / 2; // right shift\n\t}\n\t// Henceforth, `a` is always odd...\n\twhile ( b ) {\n\t\t// Remove all factors of 2 in `b`, as they are not common...\n\t\twhile ( b%2 === 0 ) {\n\t\t\tb = b / 2; // right shift\n\t\t}\n\t\t// `a` and `b` are both odd. Swap values such that `b` is the larger of the two values, and then set `b` to the difference (which is even)...\n\t\tif ( a > b ) {\n\t\t\tt = b;\n\t\t\tb = a;\n\t\t\ta = t;\n\t\t}\n\t\tb = b - a; // b=0 iff b=a\n\t}\n\t// Restore common factors of 2...\n\treturn k * a;\n} // end FUNCTION gcd()\n\n/**\n* FUNCTION: bitwise( a, b )\n*\tComputes the greatest common divisor of two integers `a` and `b`, using the binary GCD algorithm and bitwise operations.\n*\n* @param {Number} a - safe integer\n* @param {Number} b - safe integer\n* @returns {Number} greatest common divisor\n*/\nfunction bitwise( a, b ) {\n\tvar k = 0,\n\t\tt;\n\t// Simple cases:\n\tif ( a === 0 ) {\n\t\treturn b;\n\t}\n\tif ( b === 0 ) {\n\t\treturn a;\n\t}\n\t// Reduce `a` and/or `b` to odd numbers and keep track of the greatest power of 2 dividing both `a` and `b`...\n\twhile ( (a & 1) === 0 && (b & 1) === 0 ) {\n\t\ta >>>= 1; // right shift\n\t\tb >>>= 1; // right shift\n\t\tk++;\n\t}\n\t// Reduce `a` to an odd number...\n\twhile ( (a & 1) === 0 ) {\n\t\ta >>>= 1; // right shift\n\t}\n\t// Henceforth, `a` is always odd...\n\twhile ( b ) {\n\t\t// Remove all factors of 2 in `b`, as they are not common...\n\t\twhile ( (b & 1) === 0 ) {\n\t\t\tb >>>= 1; // right shift\n\t\t}\n\t\t// `a` and `b` are both odd. Swap values such that `b` is the larger of the two values, and then set `b` to the difference (which is even)...\n\t\tif ( a > b ) {\n\t\t\tt = b;\n\t\t\tb = a;\n\t\t\ta = t;\n\t\t}\n\t\tb = b - a; // b=0 iff b=a\n\t}\n\t// Restore common factors of 2...\n\treturn a << k;\n} // end FUNCTION bitwise()\n\n\n// GREATEST COMMON DIVISOR //\n\n/**\n* FUNCTION: compute( arr[, clbk] )\n*\tComputes the greatest common divisor.\n*\n* @param {Number[]|Number} arr - input array of integers\n* @param {Function|Number} [clbk] - accessor function for accessing array values\n* @returns {Number|Null} greatest common divisor or null\n*/\nfunction compute() {\n\tvar nargs = arguments.length,\n\t\targs,\n\t\tclbk,\n\t\tarr,\n\t\tlen,\n\t\ta, b,\n\t\ti;\n\n\t// Copy the input arguments to an array...\n\targs = new Array( nargs );\n\tfor ( i = 0; i < nargs; i++ ) {\n\t\targs[ i ] = arguments[ i ];\n\t}\n\t// Have we been provided with integer arguments?\n\tif ( isIntegerArray( args ) ) {\n\t\tif ( nargs === 2 ) {\n\t\t\ta = args[ 0 ];\n\t\t\tb = args[ 1 ];\n\t\t\tif ( a < 0 ) {\n\t\t\t\ta = -a;\n\t\t\t}\n\t\t\tif ( b < 0 ) {\n\t\t\t\tb = -b;\n\t\t\t}\n\t\t\tif ( a <= MAXINT && b <= MAXINT ) {\n\t\t\t\treturn bitwise( a, b );\n\t\t\t} else {\n\t\t\t\treturn gcd( a, b );\n\t\t\t}\n\t\t}\n\t\tarr = args;\n\t}\n\t// If not integers, ensure the first argument is an array...\n\telse if ( !isArray( args[ 0 ] ) ) {\n\t\tthrow new TypeError( 'gcd()::invalid input argument. Must provide an array of integers. Value: `' + args[ 0 ] + '`.' );\n\t}\n\t// Have we been provided with more than one argument? If so, ensure that the accessor argument is a function...\n\telse if ( nargs > 1 ) {\n\t\tarr = args[ 0 ];\n\t\tclbk = args[ 1 ];\n\t\tif ( !isFunction( clbk ) ) {\n\t\t\tthrow new TypeError( 'gcd()::invalid input argument. Accessor must be a function. Value: `' + clbk + '`.' );\n\t\t}\n\t}\n\t// We have been provided an array...\n\telse {\n\t\tarr = args[ 0 ];\n\t}\n\tlen = arr.length;\n\n\t// Check if a sufficient number of values have been provided...\n\tif ( len < 2 ) {\n\t\treturn null;\n\t}\n\t// If an accessor is provided, extract the array values...\n\tif ( clbk ) {\n\t\ta = new Array( len );\n\t\tfor ( i = 0; i < len; i++ ) {\n\t\t\ta[ i ] = clbk( arr[ i ], i );\n\t\t}\n\t\tarr = a;\n\t}\n\t// Given an input array, ensure all array values are integers...\n\tif ( nargs < 3 ) {\n\t\tif ( !isIntegerArray( arr ) ) {\n\t\t\tthrow new TypeError( 'gcd()::invalid input argument. Accessed array values must be integers. Value: `' + arr + '`.' );\n\t\t}\n\t}\n\t// Convert any negative integers to positive integers...\n\tfor ( i = 0; i < len; i++ ) {\n\t\ta = arr[ i ];\n\t\tif ( a < 0 ) {\n\t\t\tarr[ i ] = -a;\n\t\t}\n\t}\n\t// Exploit the fact that the gcd is an associative function...\n\ta = arr[ 0 ];\n\tfor ( i = 1; i < len; i++ ) {\n\t\tb = arr[ i ];\n\t\tif ( b <= MAXINT && a <= MAXINT ) {\n\t\t\ta = bitwise( a, b );\n\t\t} else {\n\t\t\ta = gcd( a, b );\n\t\t}\n\t}\n\treturn a;\n} // end FUNCTION compute()\n\n\n// EXPORTS //\n\nmodule.exports = compute;\n","'use strict';\n\n// MODULES //\n\nvar gcd = require( 'compute-gcd' ),\n\tisArray = require( 'validate.io-array' ),\n\tisIntegerArray = require( 'validate.io-integer-array' ),\n\tisFunction = require( 'validate.io-function' );\n\n\n// LEAST COMMON MULTIPLE //\n\n/**\n* FUNCTION: lcm( arr[, clbk] )\n*\tComputes the least common multiple (lcm).\n*\n* @param {Number[]|Number} arr - input array of integers\n* @param {Function|Number} [accessor] - accessor function for accessing array values\n* @returns {Number|Null} least common multiple or null\n*/\nfunction lcm() {\n\tvar nargs = arguments.length,\n\t\targs,\n\t\tclbk,\n\t\tarr,\n\t\tlen,\n\t\ta, b,\n\t\ti;\n\n\t// Copy the input arguments to an array...\n\targs = new Array( nargs );\n\tfor ( i = 0; i < nargs; i++ ) {\n\t\targs[ i ] = arguments[ i ];\n\t}\n\t// Have we been provided with integer arguments?\n\tif ( isIntegerArray( args ) ) {\n\t\tif ( nargs === 2 ) {\n\t\t\ta = args[ 0 ];\n\t\t\tb = args[ 1 ];\n\t\t\tif ( a < 0 ) {\n\t\t\t\ta = -a;\n\t\t\t}\n\t\t\tif ( b < 0 ) {\n\t\t\t\tb = -b;\n\t\t\t}\n\t\t\tif ( a === 0 || b === 0 ) {\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t\treturn ( a/gcd(a,b) ) * b;\n\t\t}\n\t\tarr = args;\n\t}\n\t// If not integers, ensure that the first argument is an array...\n\telse if ( !isArray( args[ 0 ] ) ) {\n\t\tthrow new TypeError( 'lcm()::invalid input argument. Must provide an array of integers. Value: `' + args[ 0 ] + '`.' );\n\t}\n\t// Have we been provided with more than one argument? If so, ensure that the accessor argument is a function...\n\telse if ( nargs > 1 ) {\n\t\tarr = args[ 0 ];\n\t\tclbk = args[ 1 ];\n\t\tif ( !isFunction( clbk ) ) {\n\t\t\tthrow new TypeError( 'lcm()::invalid input argument. Accessor must be a function. Value: `' + clbk + '`.' );\n\t\t}\n\t}\n\t// We have been provided an array...\n\telse {\n\t\tarr = args[ 0 ];\n\t}\n\tlen = arr.length;\n\n\t// Check if a sufficient number of values have been provided...\n\tif ( len < 2 ) {\n\t\treturn null;\n\t}\n\t// If an accessor is provided, extract the array values...\n\tif ( clbk ) {\n\t\ta = new Array( len );\n\t\tfor ( i = 0; i < len; i++ ) {\n\t\t\ta[ i ] = clbk( arr[ i ], i );\n\t\t}\n\t\tarr = a;\n\t}\n\t// Given an input array, ensure all array values are integers...\n\tif ( nargs < 3 ) {\n\t\tif ( !isIntegerArray( arr ) ) {\n\t\t\tthrow new TypeError( 'lcm()::invalid input argument. Accessed array values must be integers. Value: `' + arr + '`.' );\n\t\t}\n\t}\n\t// Convert any negative integers to positive integers...\n\tfor ( i = 0; i < len; i++ ) {\n\t\ta = arr[ i ];\n\t\tif ( a < 0 ) {\n\t\t\tarr[ i ] = -a;\n\t\t}\n\t}\n\t// Exploit the fact that the lcm is an associative function...\n\ta = arr[ 0 ];\n\tfor ( i = 1; i < len; i++ ) {\n\t\tb = arr[ i ];\n\t\tif ( a === 0 || b === 0 ) {\n\t\t\treturn 0;\n\t\t}\n\t\ta = ( a/gcd(a,b) ) * b;\n\t}\n\treturn a;\n} // end FUNCTION lcm()\n\n\n// EXPORTS //\n\nmodule.exports = lcm;\n","'use strict'\nvar compact = require('lodash/compact')\nvar compare = require('json-schema-compare')\nvar computeLcm = require('compute-lcm')\nvar defaultsDeep = require('lodash/defaultsDeep')\nvar flatten = require('lodash/flatten')\nvar flattenDeep = require('lodash/flattenDeep')\nvar intersection = require('lodash/intersection')\nvar intersectionWith = require('lodash/intersectionWith')\nvar isEqual = require('lodash/isEqual')\nvar isPlainObject = require('lodash/isPlainObject')\nvar pullAll = require('lodash/pullAll')\nvar pick = require('lodash/pick')\nvar sortBy = require('lodash/sortBy')\nvar forEach = require('lodash/forEach')\nvar uniq = require('lodash/uniq')\nvar uniqWith = require('lodash/uniqWith')\nvar without = require('lodash/without')\n\nvar withoutArr = (arr, ...rest) => without.apply(null, [arr].concat(flatten(rest)))\nvar isPropertyRelated = (key) => contains(propertyRelated, key)\nvar isItemsRelated = (key) => contains(itemsRelated, key)\nvar contains = (arr, val) => arr.indexOf(val) !== -1\nvar isEmptySchema = (obj) => (!keys(obj).length) && obj !== false && obj !== true\nvar isSchema = (val) => isPlainObject(val) || val === true || val === false\nvar isFalse = (val) => val === false\nvar isTrue = (val) => val === true\nvar isNotNull = (val) => val !== null\nvar schemaResolver = (compacted, key, mergeSchemas) => mergeSchemas(compacted)\nvar stringArray = (values) => sortBy(uniq(flattenDeep(values)))\nvar notUndefined = (val) => val !== undefined\nvar allUniqueKeys = (arr) => uniq(flattenDeep(arr.map(keys)))\nvar hasInThis = function (annotation) {\n return annotation in this\n}\n\n// resolvers\nvar first = compacted => compacted[0]\nvar last = compacted => compacted[compacted.length - 1]\nvar required = compacted => stringArray(compacted)\nvar maximumValue = compacted => Math.max.apply(Math, compacted)\nvar minimumValue = compacted => Math.min.apply(Math, compacted)\nvar uniqueItems = compacted => compacted.some(isTrue)\nvar examples = compacted => uniqWith(flatten(compacted), isEqual)\n\nfunction compareProp(key) {\n return function(a, b) {\n return compare({\n [key]: a\n }, {[key]: b})\n }\n}\n\nfunction getAllOf(schema) {\n let { allOf, ...copy } = schema\n copy = isPlainObject(schema) ? copy : schema // if schema is boolean\n if (Array.isArray(allOf)) {\n if (annotationProps.some(hasInThis, copy)) {\n return [copy, ...allOf.filter(isNotNull).map(getAllOf), pick(copy, annotationProps)]\n }\n\n return [copy, ...allOf.filter(isNotNull).map(getAllOf)]\n }\n\n return [copy]\n}\n\nfunction getValues(schemas, key) {\n return schemas.map(schema => schema && schema[key])\n}\n\nfunction getItemSchemas(subSchemas, key) {\n return subSchemas.map(function(sub) {\n if (!sub) {\n return\n }\n\n if (Array.isArray(sub.items)) {\n var schemaAtPos = sub.items[key]\n if (isSchema(schemaAtPos)) {\n return schemaAtPos\n } else if (sub.hasOwnProperty('additionalItems')) {\n return sub.additionalItems\n }\n } else {\n return sub.items\n }\n })\n}\n\nfunction tryMergeSchemaGroups(schemaGroups, mergeSchemas) {\n return schemaGroups.map(function(schemas, index) {\n try {\n return mergeSchemas(schemas, index)\n } catch (e) {\n return undefined\n }\n }).filter(notUndefined)\n}\n\nfunction getAdditionalSchemas(subSchemas) {\n return subSchemas.map(function(sub) {\n if (!sub) {\n return\n }\n if (Array.isArray(sub.items)) {\n return sub.additionalItems\n }\n return sub.items\n })\n}\n\nfunction keys(obj) {\n if (isPlainObject(obj) || Array.isArray(obj)) {\n return Object.keys(obj)\n } else {\n return []\n }\n}\n\nfunction getAnyOfCombinations(arrOfArrays, combinations) {\n combinations = combinations || []\n if (!arrOfArrays.length) {\n return combinations\n }\n\n var values = arrOfArrays.slice(0).shift()\n var rest = arrOfArrays.slice(1)\n if (combinations.length) {\n return getAnyOfCombinations(rest, flatten(combinations.map(combination => values.map(item => ([item].concat(combination))))))\n }\n return getAnyOfCombinations(rest, values.map(item => (item)))\n}\n\nfunction mergeWithArray(base, newItems) {\n if (Array.isArray(base)) {\n base.splice.apply(base, [0, 0].concat(newItems))\n return base\n } else {\n return newItems\n }\n}\n\nfunction throwIncompatible(values, paths) {\n var asJSON\n try {\n asJSON = values.map(function(val) {\n return JSON.stringify(val, null, 2)\n }).join('\\n')\n } catch (variable) {\n asJSON = values.join(', ')\n }\n throw new Error('Could not resolve values for path:\"' + paths.join('.') + '\". They are probably incompatible. Values: \\n' + asJSON)\n}\n\nfunction cleanupReturnValue(returnObject) {\n // cleanup empty\n for (var prop in returnObject) {\n if (returnObject.hasOwnProperty(prop) && isEmptySchema(returnObject[prop])) {\n delete returnObject[prop]\n }\n }\n return returnObject\n}\n\nfunction applyOverrides(originalValue, newValue) {\n if (\n isPlainObject(newValue) &&\n isPlainObject(originalValue) &&\n ('summary' in originalValue || 'description' in originalValue)\n ) {\n return {\n ...newValue,\n ...('description' in originalValue\n ? { description: originalValue.description }\n : null),\n ...('summary' in originalValue\n ? { summary: originalValue.summary }\n : null)\n }\n }\n\n return newValue\n}\n\nfunction createRequiredSubMerger(mergeSchemas, key, parents) {\n return function(schemas, subKey) {\n if (subKey === undefined) {\n throw new Error('You need to call merger with a key for the property name or index if array.')\n }\n subKey = String(subKey)\n return mergeSchemas(schemas, null, parents.concat(key, subKey))\n }\n}\n\nfunction callGroupResolver(keys, resolverName, schemas, mergeSchemas, options, parents) {\n if (keys.length) {\n var resolver = options.resolvers[resolverName]\n if (!resolver) {\n throw new Error('No resolver found for ' + resolverName)\n }\n\n var compacted = uniqWith(schemas.map(function(schema) {\n return keys.reduce(function(all, key) {\n if (schema[key] !== undefined) {\n all[key] = schema[key]\n }\n return all\n }, {})\n }).filter(notUndefined), compare)\n\n var related = resolverName === 'properties'\n ? propertyRelated\n : itemsRelated\n\n var mergers = related.reduce(function(all, key) {\n if (contains(schemaGroupProps, key)) {\n all[key] = createRequiredSubMerger(mergeSchemas, key, parents)\n } else {\n all[key] = function(schemas) {\n return mergeSchemas(schemas, null, parents.concat(key))\n }\n }\n return all\n }, {})\n\n if (resolverName === 'items') {\n mergers.itemsArray = createRequiredSubMerger(mergeSchemas, 'items', parents)\n mergers.items = function(schemas) {\n return mergeSchemas(schemas, null, parents.concat('items'))\n }\n }\n\n var result = resolver(compacted, parents.concat(resolverName), mergers, options)\n\n if (!isPlainObject(result)) {\n throwIncompatible(compacted, parents.concat(resolverName))\n }\n\n return cleanupReturnValue(result)\n }\n}\n\n// Provide source when array\nfunction mergeSchemaGroup(group, mergeSchemas, source) {\n var allKeys = allUniqueKeys(source || group)\n var extractor = source\n ? getItemSchemas\n : getValues\n return allKeys.reduce(function(all, key) {\n var schemas = extractor(group, key)\n var compacted = uniqWith(schemas.filter(notUndefined), compare)\n all[key] = mergeSchemas(compacted, key)\n return all\n }, source\n ? []\n : {})\n}\n\nfunction removeFalseSchemas(target) {\n forEach(target, function(schema, prop) {\n if (schema === false) {\n delete target[prop]\n }\n })\n}\n\nfunction removeFalseSchemasFromArray(target) {\n forEach(target, function(schema, index) {\n if (schema === false) {\n target.splice(index, 1)\n }\n })\n}\n\nfunction createRequiredMetaArray(arr) {\n return {required: arr}\n}\n\nfunction default$RefResolver(reference) {\n return {$ref: reference}\n}\n\nfunction inferType(schema) {\n if (!isPlainObject(schema)) return\n if ('type' in schema) return typeof schema.type === 'string' ? schema.type : undefined\n\n var types = Object.keys(implicitTypes).filter(type => implicitTypes[type].some(prop => prop in schema))\n if (types.length > 0) return types\n}\n\nvar propertyRelated = ['properties', 'patternProperties', 'additionalProperties']\nvar itemsRelated = ['items', 'additionalItems']\nvar schemaGroupProps = ['properties', 'patternProperties', 'definitions', 'dependencies']\nvar schemaArrays = ['anyOf', 'oneOf']\nvar schemaProps = [\n 'additionalProperties',\n 'additionalItems',\n 'contains',\n 'propertyNames',\n 'not',\n 'items'\n]\nvar annotationProps = ['title', 'description']\n\nvar implicitTypes = {\n object: [...propertyRelated, 'required'],\n array: [...itemsRelated, 'contains', 'uniqueItems', 'minContains', 'maxContains'],\n number: ['multipleOf', 'minimum', 'maximum', 'exclusiveMinimum', 'exclusiveMaximum'],\n get integer() { return this.number },\n string: ['pattern', 'minLength', 'maxLength']\n}\n\nvar defaultResolvers = {\n type(compacted) {\n if (compacted.some(Array.isArray)) {\n var normalized = compacted.map(function(val) {\n return Array.isArray(val)\n ? val\n : [val]\n })\n var common = intersection.apply(null, normalized)\n\n if (common.length === 1) {\n return common[0]\n } else if (common.length > 1) {\n return uniq(common)\n }\n }\n },\n properties(values, key, mergers, options) {\n // first get rid of all non permitted properties\n if (!options.ignoreAdditionalProperties) {\n values.forEach(function(subSchema) {\n var otherSubSchemas = values.filter(s => s !== subSchema)\n var ownKeys = keys(subSchema.properties)\n var ownPatternKeys = keys(subSchema.patternProperties)\n var ownPatterns = ownPatternKeys.map(k => new RegExp(k))\n otherSubSchemas.forEach(function(other) {\n var allOtherKeys = keys(other.properties)\n var keysMatchingPattern = allOtherKeys.filter(k => ownPatterns.some(pk => pk.test(k)))\n var additionalKeys = withoutArr(allOtherKeys, ownKeys, keysMatchingPattern)\n other.properties = Object.assign({}, other.properties)\n additionalKeys.forEach(function(key) {\n other.properties[key] = mergers.properties([\n other.properties[key], subSchema.additionalProperties\n ], key)\n })\n })\n })\n\n // remove disallowed patternProperties\n values.forEach(function(subSchema) {\n var otherSubSchemas = values.filter(s => s !== subSchema)\n var ownPatternKeys = keys(subSchema.patternProperties)\n if (subSchema.additionalProperties === false) {\n otherSubSchemas.forEach(function(other) {\n other.patternProperties = Object.assign({}, other.patternProperties)\n var allOtherPatterns = keys(other.patternProperties)\n var additionalPatternKeys = withoutArr(allOtherPatterns, ownPatternKeys)\n additionalPatternKeys.forEach(key => delete other.patternProperties[key])\n })\n }\n })\n }\n\n var returnObject = {\n additionalProperties: mergers.additionalProperties(values.map(s => s.additionalProperties)),\n patternProperties: mergeSchemaGroup(values.map(s => s.patternProperties), mergers.patternProperties),\n properties: mergeSchemaGroup(values.map(s => s.properties), mergers.properties)\n }\n\n if (returnObject.additionalProperties === false) {\n removeFalseSchemas(returnObject.properties)\n }\n\n return returnObject\n },\n dependencies(compacted, paths, mergeSchemas) {\n var allChildren = allUniqueKeys(compacted)\n\n return allChildren.reduce(function(all, childKey) {\n var childSchemas = getValues(compacted, childKey)\n var innerCompacted = uniqWith(childSchemas.filter(notUndefined), isEqual)\n\n // to support dependencies\n var innerArrays = innerCompacted.filter(Array.isArray)\n\n if (innerArrays.length) {\n if (innerArrays.length === innerCompacted.length) {\n all[childKey] = stringArray(innerCompacted)\n } else {\n var innerSchemas = innerCompacted.filter(isSchema)\n var arrayMetaScheams = innerArrays.map(createRequiredMetaArray)\n all[childKey] = mergeSchemas(innerSchemas.concat(arrayMetaScheams), childKey)\n }\n return all\n }\n\n innerCompacted = uniqWith(innerCompacted, compare)\n\n all[childKey] = mergeSchemas(innerCompacted, childKey)\n return all\n }, {})\n },\n items(values, paths, mergers) {\n var items = values.map(s => s.items)\n var itemsCompacted = items.filter(notUndefined)\n var returnObject = {}\n\n if (itemsCompacted.every(isSchema)) {\n returnObject.items = mergers.items(items)\n } else {\n returnObject.items = mergeSchemaGroup(values, mergers.itemsArray, items)\n }\n\n var schemasAtLastPos\n if (itemsCompacted.every(Array.isArray)) {\n schemasAtLastPos = values.map(s => s.additionalItems)\n } else if (itemsCompacted.some(Array.isArray)) {\n schemasAtLastPos = getAdditionalSchemas(values)\n }\n\n if (schemasAtLastPos) {\n returnObject.additionalItems = mergers.additionalItems(schemasAtLastPos)\n }\n\n if (returnObject.additionalItems === false && Array.isArray(returnObject.items)) {\n removeFalseSchemasFromArray(returnObject.items)\n }\n\n return returnObject\n },\n oneOf(compacted, paths, mergeSchemas) {\n var combinations = getAnyOfCombinations(compacted)\n var result = tryMergeSchemaGroups(combinations, mergeSchemas)\n var unique = uniqWith(result, compare)\n\n if (unique.length) {\n return unique\n }\n },\n not(compacted) {\n return {anyOf: compacted}\n },\n pattern(compacted) {\n return compacted.map(r => '(?=' + r + ')').join('')\n },\n multipleOf(compacted) {\n var integers = compacted.slice(0)\n var factor = 1\n while (integers.some(n => !Number.isInteger(n))) {\n integers = integers.map(n => n * 10)\n factor = factor * 10\n }\n return computeLcm(integers) / factor\n },\n enum(compacted) {\n var enums = intersectionWith.apply(null, compacted.concat(isEqual))\n if (enums.length) {\n return sortBy(enums)\n }\n }\n}\n\ndefaultResolvers.$id = first\ndefaultResolvers.$ref = first\ndefaultResolvers.$schema = first\ndefaultResolvers.additionalItems = schemaResolver\ndefaultResolvers.additionalProperties = schemaResolver\ndefaultResolvers.anyOf = defaultResolvers.oneOf\ndefaultResolvers.contains = schemaResolver\ndefaultResolvers.default = last\ndefaultResolvers.definitions = defaultResolvers.dependencies\ndefaultResolvers.description = last\ndefaultResolvers.examples = examples\ndefaultResolvers.exclusiveMaximum = minimumValue\ndefaultResolvers.exclusiveMinimum = maximumValue\ndefaultResolvers.maximum = minimumValue\ndefaultResolvers.maxItems = minimumValue\ndefaultResolvers.maxLength = minimumValue\ndefaultResolvers.maxProperties = minimumValue\ndefaultResolvers.minimum = maximumValue\ndefaultResolvers.minItems = maximumValue\ndefaultResolvers.minLength = maximumValue\ndefaultResolvers.minProperties = maximumValue\ndefaultResolvers.propertyNames = schemaResolver\ndefaultResolvers.required = required\ndefaultResolvers.title = last\ndefaultResolvers.uniqueItems = uniqueItems\n\nfunction merger(rootSchema, options, totalSchemas) {\n totalSchemas = totalSchemas || []\n options = defaultsDeep(options, {\n ignoreAdditionalProperties: false,\n resolvers: defaultResolvers,\n deep: true,\n $refResolver: default$RefResolver\n })\n\n function mergeSchemas(schemas, base, parents) {\n schemas = schemas.filter(notUndefined)\n parents = parents || []\n var merged = isPlainObject(base)\n ? Object.assign({}, base)\n : {}\n\n // return undefined, an empty schema\n if (!schemas.length) {\n return\n }\n\n if (schemas.some(isFalse)) {\n return false\n }\n\n if (schemas.every(isTrue)) {\n return true\n }\n\n // there are no false and we don't need the true ones as they accept everything\n schemas = schemas.filter(isPlainObject)\n\n schemas = schemas.map(schema => '$ref' in schema ? applyOverrides(\n schema,\n options.$refResolver(schema.$ref)\n ) : Object.assign({}, schema))\n\n var types = schemas.map(schema => inferType(schema)).filter(notUndefined)\n\n if (types.length > 1) {\n let first = Array.isArray(types[0]) ? types[0] : [types[0]]\n types.slice(1).forEach(function (type) {\n if (Array.isArray(type) ? !intersection(first, type).length : !first.includes(type)) {\n throwIncompatible(types, parents.concat('type'))\n }\n })\n }\n\n var allKeys = allUniqueKeys(schemas)\n\n if (options.deep && contains(allKeys, 'allOf')) {\n return merger({\n allOf: schemas\n }, options, totalSchemas)\n }\n\n var propertyKeys = allKeys.filter(isPropertyRelated)\n pullAll(allKeys, propertyKeys)\n\n var itemKeys = allKeys.filter(isItemsRelated)\n pullAll(allKeys, itemKeys)\n\n allKeys.forEach(function(key) {\n var values = getValues(schemas, key).filter(notUndefined)\n var compacted = annotationProps.includes(key) ? values : uniqWith(values, compareProp(key))\n\n // arrayprops like anyOf and oneOf must be merged first, as they contains schemas\n // allOf is treated differently alltogether\n if (compacted.length === 1 && contains(schemaArrays, key)) {\n merged[key] = compacted[0].map(function(schema) {\n return mergeSchemas([schema], schema)\n })\n // prop groups must always be resolved\n } else if (compacted.length === 1 && !contains(schemaGroupProps, key) && !contains(schemaProps, key)) {\n merged[key] = compacted[0]\n } else {\n var resolver = options.resolvers[key] || options.resolvers.defaultResolver\n\n if (!resolver) {\n throw new Error('No resolver found for key ' + key + '. You can provide a resolver for this keyword in the options, or provide a default resolver.')\n }\n\n var merger\n // get custom merger for groups\n if (contains(schemaGroupProps, key) || contains(schemaArrays, key)) {\n merger = createRequiredSubMerger(mergeSchemas, key, parents)\n } else {\n merger = function(schemas) {\n return mergeSchemas(schemas, null, parents.concat(key))\n }\n }\n\n var calledWithArray = false\n merged[key] = resolver(compacted, parents.concat(key), merger, options, function(unresolvedSchemas) {\n calledWithArray = Array.isArray(unresolvedSchemas)\n return addToAllOf(unresolvedSchemas)\n })\n\n if (merged[key] === undefined && !calledWithArray) {\n throwIncompatible(compacted, parents.concat(key))\n } else if (merged[key] === undefined) {\n delete merged[key]\n }\n }\n })\n\n Object.assign(merged, callGroupResolver(propertyKeys, 'properties', schemas, mergeSchemas, options, parents))\n Object.assign(merged, callGroupResolver(itemKeys, 'items', schemas, mergeSchemas, options, parents))\n\n function addToAllOf(unresolvedSchemas) {\n merged.allOf = mergeWithArray(merged.allOf, unresolvedSchemas)\n }\n\n return merged\n }\n\n var allSchemas = flattenDeep(getAllOf(rootSchema))\n var merged = mergeSchemas(allSchemas)\n\n return merged\n}\n\nmerger.options = {\n resolvers: defaultResolvers\n}\n\nmerger.stoplightResolvers = {\n defaultResolver(values) {\n if (Array.isArray(values)) {\n return values\n }\n\n return Object.assign({}, ...Object(values))\n },\n example(values) {\n return defaultResolvers.enum(values) || null\n },\n enum(values) {\n return defaultResolvers.enum(compact(values)) || []\n },\n $ref(values) {\n return {}\n }\n}\n\nmodule.exports = merger\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n'use strict';\nimport { createScanner } from './scanner';\nvar ParseOptions;\n(function (ParseOptions) {\n ParseOptions.DEFAULT = {\n allowTrailingComma: false\n };\n})(ParseOptions || (ParseOptions = {}));\n/**\n * For a given offset, evaluate the location in the JSON document. Each segment in the location path is either a property name or an array index.\n */\nexport function getLocation(text, position) {\n var segments = []; // strings or numbers\n var earlyReturnException = new Object();\n var previousNode = undefined;\n var previousNodeInst = {\n value: {},\n offset: 0,\n length: 0,\n type: 'object',\n parent: undefined\n };\n var isAtPropertyKey = false;\n function setPreviousNode(value, offset, length, type) {\n previousNodeInst.value = value;\n previousNodeInst.offset = offset;\n previousNodeInst.length = length;\n previousNodeInst.type = type;\n previousNodeInst.colonOffset = undefined;\n previousNode = previousNodeInst;\n }\n try {\n visit(text, {\n onObjectBegin: function (offset, length) {\n if (position <= offset) {\n throw earlyReturnException;\n }\n previousNode = undefined;\n isAtPropertyKey = position > offset;\n segments.push(''); // push a placeholder (will be replaced)\n },\n onObjectProperty: function (name, offset, length) {\n if (position < offset) {\n throw earlyReturnException;\n }\n setPreviousNode(name, offset, length, 'property');\n segments[segments.length - 1] = name;\n if (position <= offset + length) {\n throw earlyReturnException;\n }\n },\n onObjectEnd: function (offset, length) {\n if (position <= offset) {\n throw earlyReturnException;\n }\n previousNode = undefined;\n segments.pop();\n },\n onArrayBegin: function (offset, length) {\n if (position <= offset) {\n throw earlyReturnException;\n }\n previousNode = undefined;\n segments.push(0);\n },\n onArrayEnd: function (offset, length) {\n if (position <= offset) {\n throw earlyReturnException;\n }\n previousNode = undefined;\n segments.pop();\n },\n onLiteralValue: function (value, offset, length) {\n if (position < offset) {\n throw earlyReturnException;\n }\n setPreviousNode(value, offset, length, getNodeType(value));\n if (position <= offset + length) {\n throw earlyReturnException;\n }\n },\n onSeparator: function (sep, offset, length) {\n if (position <= offset) {\n throw earlyReturnException;\n }\n if (sep === ':' && previousNode && previousNode.type === 'property') {\n previousNode.colonOffset = offset;\n isAtPropertyKey = false;\n previousNode = undefined;\n }\n else if (sep === ',') {\n var last = segments[segments.length - 1];\n if (typeof last === 'number') {\n segments[segments.length - 1] = last + 1;\n }\n else {\n isAtPropertyKey = true;\n segments[segments.length - 1] = '';\n }\n previousNode = undefined;\n }\n }\n });\n }\n catch (e) {\n if (e !== earlyReturnException) {\n throw e;\n }\n }\n return {\n path: segments,\n previousNode: previousNode,\n isAtPropertyKey: isAtPropertyKey,\n matches: function (pattern) {\n var k = 0;\n for (var i = 0; k < pattern.length && i < segments.length; i++) {\n if (pattern[k] === segments[i] || pattern[k] === '*') {\n k++;\n }\n else if (pattern[k] !== '**') {\n return false;\n }\n }\n return k === pattern.length;\n }\n };\n}\n/**\n * Parses the given text and returns the object the JSON content represents. On invalid input, the parser tries to be as fault tolerant as possible, but still return a result.\n * Therefore always check the errors list to find out if the input was valid.\n */\nexport function parse(text, errors, options) {\n if (errors === void 0) { errors = []; }\n if (options === void 0) { options = ParseOptions.DEFAULT; }\n var currentProperty = null;\n var currentParent = [];\n var previousParents = [];\n function onValue(value) {\n if (Array.isArray(currentParent)) {\n currentParent.push(value);\n }\n else if (currentProperty !== null) {\n currentParent[currentProperty] = value;\n }\n }\n var visitor = {\n onObjectBegin: function () {\n var object = {};\n onValue(object);\n previousParents.push(currentParent);\n currentParent = object;\n currentProperty = null;\n },\n onObjectProperty: function (name) {\n currentProperty = name;\n },\n onObjectEnd: function () {\n currentParent = previousParents.pop();\n },\n onArrayBegin: function () {\n var array = [];\n onValue(array);\n previousParents.push(currentParent);\n currentParent = array;\n currentProperty = null;\n },\n onArrayEnd: function () {\n currentParent = previousParents.pop();\n },\n onLiteralValue: onValue,\n onError: function (error, offset, length) {\n errors.push({ error: error, offset: offset, length: length });\n }\n };\n visit(text, visitor, options);\n return currentParent[0];\n}\n/**\n * Parses the given text and returns a tree representation the JSON content. On invalid input, the parser tries to be as fault tolerant as possible, but still return a result.\n */\nexport function parseTree(text, errors, options) {\n if (errors === void 0) { errors = []; }\n if (options === void 0) { options = ParseOptions.DEFAULT; }\n var currentParent = { type: 'array', offset: -1, length: -1, children: [], parent: undefined }; // artificial root\n function ensurePropertyComplete(endOffset) {\n if (currentParent.type === 'property') {\n currentParent.length = endOffset - currentParent.offset;\n currentParent = currentParent.parent;\n }\n }\n function onValue(valueNode) {\n currentParent.children.push(valueNode);\n return valueNode;\n }\n var visitor = {\n onObjectBegin: function (offset) {\n currentParent = onValue({ type: 'object', offset: offset, length: -1, parent: currentParent, children: [] });\n },\n onObjectProperty: function (name, offset, length) {\n currentParent = onValue({ type: 'property', offset: offset, length: -1, parent: currentParent, children: [] });\n currentParent.children.push({ type: 'string', value: name, offset: offset, length: length, parent: currentParent });\n },\n onObjectEnd: function (offset, length) {\n ensurePropertyComplete(offset + length); // in case of a missing value for a property: make sure property is complete\n currentParent.length = offset + length - currentParent.offset;\n currentParent = currentParent.parent;\n ensurePropertyComplete(offset + length);\n },\n onArrayBegin: function (offset, length) {\n currentParent = onValue({ type: 'array', offset: offset, length: -1, parent: currentParent, children: [] });\n },\n onArrayEnd: function (offset, length) {\n currentParent.length = offset + length - currentParent.offset;\n currentParent = currentParent.parent;\n ensurePropertyComplete(offset + length);\n },\n onLiteralValue: function (value, offset, length) {\n onValue({ type: getNodeType(value), offset: offset, length: length, parent: currentParent, value: value });\n ensurePropertyComplete(offset + length);\n },\n onSeparator: function (sep, offset, length) {\n if (currentParent.type === 'property') {\n if (sep === ':') {\n currentParent.colonOffset = offset;\n }\n else if (sep === ',') {\n ensurePropertyComplete(offset);\n }\n }\n },\n onError: function (error, offset, length) {\n errors.push({ error: error, offset: offset, length: length });\n }\n };\n visit(text, visitor, options);\n var result = currentParent.children[0];\n if (result) {\n delete result.parent;\n }\n return result;\n}\n/**\n * Finds the node at the given path in a JSON DOM.\n */\nexport function findNodeAtLocation(root, path) {\n if (!root) {\n return undefined;\n }\n var node = root;\n for (var _i = 0, path_1 = path; _i < path_1.length; _i++) {\n var segment = path_1[_i];\n if (typeof segment === 'string') {\n if (node.type !== 'object' || !Array.isArray(node.children)) {\n return undefined;\n }\n var found = false;\n for (var _a = 0, _b = node.children; _a < _b.length; _a++) {\n var propertyNode = _b[_a];\n if (Array.isArray(propertyNode.children) && propertyNode.children[0].value === segment) {\n node = propertyNode.children[1];\n found = true;\n break;\n }\n }\n if (!found) {\n return undefined;\n }\n }\n else {\n var index = segment;\n if (node.type !== 'array' || index < 0 || !Array.isArray(node.children) || index >= node.children.length) {\n return undefined;\n }\n node = node.children[index];\n }\n }\n return node;\n}\n/**\n * Gets the JSON path of the given JSON DOM node\n */\nexport function getNodePath(node) {\n if (!node.parent || !node.parent.children) {\n return [];\n }\n var path = getNodePath(node.parent);\n if (node.parent.type === 'property') {\n var key = node.parent.children[0].value;\n path.push(key);\n }\n else if (node.parent.type === 'array') {\n var index = node.parent.children.indexOf(node);\n if (index !== -1) {\n path.push(index);\n }\n }\n return path;\n}\n/**\n * Evaluates the JavaScript object of the given JSON DOM node\n */\nexport function getNodeValue(node) {\n switch (node.type) {\n case 'array':\n return node.children.map(getNodeValue);\n case 'object':\n var obj = Object.create(null);\n for (var _i = 0, _a = node.children; _i < _a.length; _i++) {\n var prop = _a[_i];\n var valueNode = prop.children[1];\n if (valueNode) {\n obj[prop.children[0].value] = getNodeValue(valueNode);\n }\n }\n return obj;\n case 'null':\n case 'string':\n case 'number':\n case 'boolean':\n return node.value;\n default:\n return undefined;\n }\n}\nexport function contains(node, offset, includeRightBound) {\n if (includeRightBound === void 0) { includeRightBound = false; }\n return (offset >= node.offset && offset < (node.offset + node.length)) || includeRightBound && (offset === (node.offset + node.length));\n}\n/**\n * Finds the most inner node at the given offset. If includeRightBound is set, also finds nodes that end at the given offset.\n */\nexport function findNodeAtOffset(node, offset, includeRightBound) {\n if (includeRightBound === void 0) { includeRightBound = false; }\n if (contains(node, offset, includeRightBound)) {\n var children = node.children;\n if (Array.isArray(children)) {\n for (var i = 0; i < children.length && children[i].offset <= offset; i++) {\n var item = findNodeAtOffset(children[i], offset, includeRightBound);\n if (item) {\n return item;\n }\n }\n }\n return node;\n }\n return undefined;\n}\n/**\n * Parses the given text and invokes the visitor functions for each object, array and literal reached.\n */\nexport function visit(text, visitor, options) {\n if (options === void 0) { options = ParseOptions.DEFAULT; }\n var _scanner = createScanner(text, false);\n function toNoArgVisit(visitFunction) {\n return visitFunction ? function () { return visitFunction(_scanner.getTokenOffset(), _scanner.getTokenLength(), _scanner.getTokenStartLine(), _scanner.getTokenStartCharacter()); } : function () { return true; };\n }\n function toOneArgVisit(visitFunction) {\n return visitFunction ? function (arg) { return visitFunction(arg, _scanner.getTokenOffset(), _scanner.getTokenLength(), _scanner.getTokenStartLine(), _scanner.getTokenStartCharacter()); } : function () { return true; };\n }\n var onObjectBegin = toNoArgVisit(visitor.onObjectBegin), onObjectProperty = toOneArgVisit(visitor.onObjectProperty), onObjectEnd = toNoArgVisit(visitor.onObjectEnd), onArrayBegin = toNoArgVisit(visitor.onArrayBegin), onArrayEnd = toNoArgVisit(visitor.onArrayEnd), onLiteralValue = toOneArgVisit(visitor.onLiteralValue), onSeparator = toOneArgVisit(visitor.onSeparator), onComment = toNoArgVisit(visitor.onComment), onError = toOneArgVisit(visitor.onError);\n var disallowComments = options && options.disallowComments;\n var allowTrailingComma = options && options.allowTrailingComma;\n function scanNext() {\n while (true) {\n var token = _scanner.scan();\n switch (_scanner.getTokenError()) {\n case 4 /* InvalidUnicode */:\n handleError(14 /* InvalidUnicode */);\n break;\n case 5 /* InvalidEscapeCharacter */:\n handleError(15 /* InvalidEscapeCharacter */);\n break;\n case 3 /* UnexpectedEndOfNumber */:\n handleError(13 /* UnexpectedEndOfNumber */);\n break;\n case 1 /* UnexpectedEndOfComment */:\n if (!disallowComments) {\n handleError(11 /* UnexpectedEndOfComment */);\n }\n break;\n case 2 /* UnexpectedEndOfString */:\n handleError(12 /* UnexpectedEndOfString */);\n break;\n case 6 /* InvalidCharacter */:\n handleError(16 /* InvalidCharacter */);\n break;\n }\n switch (token) {\n case 12 /* LineCommentTrivia */:\n case 13 /* BlockCommentTrivia */:\n if (disallowComments) {\n handleError(10 /* InvalidCommentToken */);\n }\n else {\n onComment();\n }\n break;\n case 16 /* Unknown */:\n handleError(1 /* InvalidSymbol */);\n break;\n case 15 /* Trivia */:\n case 14 /* LineBreakTrivia */:\n break;\n default:\n return token;\n }\n }\n }\n function handleError(error, skipUntilAfter, skipUntil) {\n if (skipUntilAfter === void 0) { skipUntilAfter = []; }\n if (skipUntil === void 0) { skipUntil = []; }\n onError(error);\n if (skipUntilAfter.length + skipUntil.length > 0) {\n var token = _scanner.getToken();\n while (token !== 17 /* EOF */) {\n if (skipUntilAfter.indexOf(token) !== -1) {\n scanNext();\n break;\n }\n else if (skipUntil.indexOf(token) !== -1) {\n break;\n }\n token = scanNext();\n }\n }\n }\n function parseString(isValue) {\n var value = _scanner.getTokenValue();\n if (isValue) {\n onLiteralValue(value);\n }\n else {\n onObjectProperty(value);\n }\n scanNext();\n return true;\n }\n function parseLiteral() {\n switch (_scanner.getToken()) {\n case 11 /* NumericLiteral */:\n var value = 0;\n try {\n value = JSON.parse(_scanner.getTokenValue());\n if (typeof value !== 'number') {\n handleError(2 /* InvalidNumberFormat */);\n value = 0;\n }\n }\n catch (e) {\n handleError(2 /* InvalidNumberFormat */);\n }\n onLiteralValue(value);\n break;\n case 7 /* NullKeyword */:\n onLiteralValue(null);\n break;\n case 8 /* TrueKeyword */:\n onLiteralValue(true);\n break;\n case 9 /* FalseKeyword */:\n onLiteralValue(false);\n break;\n default:\n return false;\n }\n scanNext();\n return true;\n }\n function parseProperty() {\n if (_scanner.getToken() !== 10 /* StringLiteral */) {\n handleError(3 /* PropertyNameExpected */, [], [2 /* CloseBraceToken */, 5 /* CommaToken */]);\n return false;\n }\n parseString(false);\n if (_scanner.getToken() === 6 /* ColonToken */) {\n onSeparator(':');\n scanNext(); // consume colon\n if (!parseValue()) {\n handleError(4 /* ValueExpected */, [], [2 /* CloseBraceToken */, 5 /* CommaToken */]);\n }\n }\n else {\n handleError(5 /* ColonExpected */, [], [2 /* CloseBraceToken */, 5 /* CommaToken */]);\n }\n return true;\n }\n function parseObject() {\n onObjectBegin();\n scanNext(); // consume open brace\n var needsComma = false;\n while (_scanner.getToken() !== 2 /* CloseBraceToken */ && _scanner.getToken() !== 17 /* EOF */) {\n if (_scanner.getToken() === 5 /* CommaToken */) {\n if (!needsComma) {\n handleError(4 /* ValueExpected */, [], []);\n }\n onSeparator(',');\n scanNext(); // consume comma\n if (_scanner.getToken() === 2 /* CloseBraceToken */ && allowTrailingComma) {\n break;\n }\n }\n else if (needsComma) {\n handleError(6 /* CommaExpected */, [], []);\n }\n if (!parseProperty()) {\n handleError(4 /* ValueExpected */, [], [2 /* CloseBraceToken */, 5 /* CommaToken */]);\n }\n needsComma = true;\n }\n onObjectEnd();\n if (_scanner.getToken() !== 2 /* CloseBraceToken */) {\n handleError(7 /* CloseBraceExpected */, [2 /* CloseBraceToken */], []);\n }\n else {\n scanNext(); // consume close brace\n }\n return true;\n }\n function parseArray() {\n onArrayBegin();\n scanNext(); // consume open bracket\n var needsComma = false;\n while (_scanner.getToken() !== 4 /* CloseBracketToken */ && _scanner.getToken() !== 17 /* EOF */) {\n if (_scanner.getToken() === 5 /* CommaToken */) {\n if (!needsComma) {\n handleError(4 /* ValueExpected */, [], []);\n }\n onSeparator(',');\n scanNext(); // consume comma\n if (_scanner.getToken() === 4 /* CloseBracketToken */ && allowTrailingComma) {\n break;\n }\n }\n else if (needsComma) {\n handleError(6 /* CommaExpected */, [], []);\n }\n if (!parseValue()) {\n handleError(4 /* ValueExpected */, [], [4 /* CloseBracketToken */, 5 /* CommaToken */]);\n }\n needsComma = true;\n }\n onArrayEnd();\n if (_scanner.getToken() !== 4 /* CloseBracketToken */) {\n handleError(8 /* CloseBracketExpected */, [4 /* CloseBracketToken */], []);\n }\n else {\n scanNext(); // consume close bracket\n }\n return true;\n }\n function parseValue() {\n switch (_scanner.getToken()) {\n case 3 /* OpenBracketToken */:\n return parseArray();\n case 1 /* OpenBraceToken */:\n return parseObject();\n case 10 /* StringLiteral */:\n return parseString(true);\n default:\n return parseLiteral();\n }\n }\n scanNext();\n if (_scanner.getToken() === 17 /* EOF */) {\n if (options.allowEmptyContent) {\n return true;\n }\n handleError(4 /* ValueExpected */, [], []);\n return false;\n }\n if (!parseValue()) {\n handleError(4 /* ValueExpected */, [], []);\n return false;\n }\n if (_scanner.getToken() !== 17 /* EOF */) {\n handleError(9 /* EndOfFileExpected */, [], []);\n }\n return true;\n}\n/**\n * Takes JSON with JavaScript-style comments and remove\n * them. Optionally replaces every none-newline character\n * of comments with a replaceCharacter\n */\nexport function stripComments(text, replaceCh) {\n var _scanner = createScanner(text), parts = [], kind, offset = 0, pos;\n do {\n pos = _scanner.getPosition();\n kind = _scanner.scan();\n switch (kind) {\n case 12 /* LineCommentTrivia */:\n case 13 /* BlockCommentTrivia */:\n case 17 /* EOF */:\n if (offset !== pos) {\n parts.push(text.substring(offset, pos));\n }\n if (replaceCh !== undefined) {\n parts.push(_scanner.getTokenValue().replace(/[^\\r\\n]/g, replaceCh));\n }\n offset = _scanner.getPosition();\n break;\n }\n } while (kind !== 17 /* EOF */);\n return parts.join('');\n}\nexport function getNodeType(value) {\n switch (typeof value) {\n case 'boolean': return 'boolean';\n case 'number': return 'number';\n case 'string': return 'string';\n case 'object': {\n if (!value) {\n return 'null';\n }\n else if (Array.isArray(value)) {\n return 'array';\n }\n return 'object';\n }\n default: return 'null';\n }\n}\n","import{cloneDeep as e,get as t,set as r,has as n,setWith as o,omit as i,trimStart as a}from\"lodash\";import{isAbsolute as s,join as c,dirname as u}from\"@stoplight/path\";import{createScanner as l,findNodeAtOffset as f,getNodePath as p,visit as h,printParseErrorCode as y}from\"jsonc-parser\";import g,{getOrder as d,ORDER_KEY_ID as m}from\"@stoplight/ordered-object-literal\";import{DiagnosticSeverity as v}from\"@stoplight/types\";import b from\"safe-stable-stringify\";function w(e){if(\"object\"!=typeof e||null===e)return!1;const t=Object.getPrototypeOf(e);return null===t||t===Object.prototype||\"function\"==typeof e.constructor&&Function.toString.call(Object)===Function.toString.call(e.constructor)}function O(e,t,r){if(!w(e)&&!Array.isArray(e)||!(t in e))throw new ReferenceError(`Could not resolve '${r}'`)}function j(e){if(\"string\"!=typeof e.$ref)throw new TypeError(\"$ref should be a string\")}const A=e=>w(e)&&\"$ref\"in e,$=e=>A(e)&&\"string\"==typeof e.$ref,E=e=>e.length>0&&(\"#\"===e||/^#\\S*$/.test(e)),S=(e,t,r)=>{const n=e.toString();let o=\"\",i=n,a=0,s=i.indexOf(t);for(;s>-1;)o+=n.substring(a,a+s)+r,i=i.substring(s+t.length,i.length),a+=s+t.length,s=i.indexOf(t);return i.length>0&&(o+=n.substring(n.length-i.length,n.length)),o},x=e=>\"number\"==typeof e?e:S(S(e,\"~\",\"~0\"),\"/\",\"~1\"),_=/[^a-zA–Z0–9_.!~*'()\\/\\-\\u{D800}-\\u{DFFF}]/gu;function N(e){return e.replace(_,encodeURIComponent)}const k=e=>{const t=x(e);return\"number\"==typeof t?t:N(t)},P=e=>I(e),I=e=>{if(e&&\"object\"!=typeof e)throw new TypeError(\"Invalid type: path must be an array of segments.\");return 0===e.length?\"#\":`#/${e.map(k).join(\"/\")}`};function T(e){try{return decodeURIComponent(e)}catch(t){return e}}const R=/%[0-9a-f]+/gi,U=e=>{let t;try{t=decodeURIComponent(e)}catch(r){t=e.replace(R,T)}return S(S(t,\"~1\",\"/\"),\"~0\",\"~\")},K=e=>J(e),J=e=>{if(\"string\"!=typeof e)throw new TypeError(\"Invalid type: JSON Pointers are represented as strings.\");if(0===e.length||\"#\"!==e[0])throw new URIError(\"Invalid JSON Pointer syntax; URI fragment identifiers must begin with a hash.\");if(1===e.length)return[];if(\"/\"!==e[1])throw new URIError(\"Invalid JSON Pointer syntax.\");return(e=>{const t=e.length,r=[];let n=-1;for(;++n{const n={value:e,path:r};t.onEnter&&t.onEnter(n);for(const n of Object.keys(e)){const o=e[n];t.onProperty&&t.onProperty({parent:e,parentPath:r,property:n,propertyValue:o}),\"object\"==typeof o&&null!==o&&C(o,t,r.concat(n))}t.onLeave&&t.onLeave(n)},D=(e,t)=>{\"object\"==typeof e&&null!==e&&C(e,\"function\"==typeof t?{onProperty:t}:t,[])};function F(e,t,r){D(e,{onProperty({property:e,propertyValue:n,parent:o}){\"$ref\"===e&&\"string\"==typeof n&&n.startsWith(t)&&(o.$ref=`${r}${n.slice(t.length)}`)}})}const M=e=>e.length>0&&\"#\"!==e[0],V=e=>{if(\"string\"!=typeof e||0===e.length||!M(e))return null;const t=e.indexOf(\"#\");return-1===t?e:e.slice(0,t)};function W(e,t){return w(t)&&w(e)&&(\"summary\"in e||\"description\"in e)?Object.assign(Object.assign(Object.assign({},t),\"description\"in e?{description:e.description}:null),\"summary\"in e?{summary:e.summary}:null):t}function*L(e,t,r){A(e.value)&&(j(e.value),yield[-1,e.value]);for(const[n,o]of t.entries())O(e.value,o,r),e.value=e.value[o],A(e.value)&&(j(e.value),yield[n,e.value])}function B(e,t){return z(e,t).value}function z(e,t){return function e(t,r,n,o){if(null!==V(r))throw new ReferenceError(\"Cannot resolve external references\");const i=K(r);let a=[...i];\"#\"===r&&A(t)&&(j(t),i.unshift(...K(t.$ref)));const s={value:t};for(const[c,u]of L(s,i,r)){if(n.includes(u))return{source:null,location:null!=o?o:a,value:n[n.length-1]};n.push(u);const r=e(t,u.$ref,n,a);s.value=r.value,(a=r.location).push(...i.slice(c+1))}return{source:null,location:a,value:n.length>0?W(n[n.length-1],s.value):s.value}}(e,t,[])}const Z=\"#/__bundled__\",q=\"#/__errors__\",G=({document:t,path:r,bundleRoot:n=\"#/__bundled__\",errorsRoot:o=\"#/__errors__\",cloneDocument:i=!0,keyProvider:a},s)=>{if(r===n||r===o)throw new Error(\"Roots do not make any sense\");const c=i?e(t):t;return H(c,K(n),K(o),r,a)(r,{[r]:!0},s)},H=(e,a,s,c,u)=>{const l=new Set,f=(p,h,y,g={},d={},m={})=>{const v=K(p),b=t(e,v);D(y||b,{onEnter:({value:s})=>{if($(s)&&E(s.$ref)){const y=s.$ref;if(m[y])return;if(y===p&&(g[y]=\"#\"),g[y])return void(s.$ref=g[y]);let v,b,w,O,j;try{let r;v=K(y),u&&(r=u({document:e,path:v})),r||(r=(({document:e,path:r})=>{if(0===r.length)return\"root\";if(Array.isArray(t(e,r.slice(0,-1))))return`${r[r.length-2]}_${r[r.length-1]}`;return String(r[r.length-1])})({document:e,path:v})),w=r;let n=1;for(;l.has(w);)if(w=`${r}_${++n}`,n>20)throw new Error(`Keys ${r}_2 through ${r}_20 already taken.`);l.add(w),b=[...a,w],O=P(b)}catch(e){m[y]=e instanceof Error?e.message:String(e)}if(!v||!b||!O)return;if(\"object\"==typeof e&&null!==e&&!(j=t(e,v)))try{j=B(Object(e),y)}catch(e){}void 0!==j&&(g[y]=O,s.$ref=O,n(d,b)||(Array.isArray(j)?r(d,b,new Array(j.length).fill(null)):\"object\"==typeof j&&o(d,b,{},Object),r(d,b,j),\"#\"===y?function(e,t,n,o){const a=n.map(e=>`[${JSON.stringify(e)}]`).join(\"\"),s=JSON.parse(JSON.stringify(i(Object(e),a))),c={};r(t,o,s),r(s,n,c),F(s,\"#\",P(o)),c.$ref=\"#\"}(e,d,K(c),b):h[y]||(h[y]=!0,f(p,h,j,g,d,m),h[y]=!1)))}}});const w=t(d,a);return w&&Object.keys(w).length&&r(b,a,w),(Object.keys(m).length||n(e,s))&&r(b,s,n(e,s)?t(e,s):m),b};return f};const Q=e=>S(S(e,\"~1\",\"/\"),\"~0\",\"~\"),X=(e,t)=>{const r=new WeakMap;return function e(n,o){let i;if(t&&(n=t(n)),w(n)||Array.isArray(n)){const t=r.get(n);return t?{$ref:t}:(r.set(n,P(o)),Array.isArray(n)?i=n.map((t,r)=>e(t,[...o,String(r)])):(i={},Object.keys(n).forEach(t=>{i[t]=e(n[t],[...o,t])})),r.delete(n),i)}return n}(e,[])},Y=e=>S(S(e,\"~\",\"~0\"),\"//\",\"/~1\"),ee=e=>{if(\"string\"!=typeof e||0===e.length)return null;const t=e.indexOf(\"#\");return-1===t?null:e.slice(t)},te=e=>{const t=l(e,!0);if(t.scan(),1!==t.getToken())return;if(t.scan(),2===t.getToken())return;if(10!==t.getToken())throw new SyntaxError(\"Unexpected character\");const r=t.getTokenValue();if(t.scan(),6!==t.getToken())throw new SyntaxError(\"Colon expected\");switch(t.scan(),t.getToken()){case 10:return[r,t.getTokenValue()];case 11:return[r,Number(t.getTokenValue())];case 8:return[r,!0];case 9:return[r,!1];case 7:return[r,null];case 16:throw new SyntaxError(\"Unexpected character\");case 17:throw new SyntaxError(\"Unexpected end of file\");default:return}},re=({lineMap:e,ast:t},r)=>{const n=e[r.line],o=e[r.line+1];if(void 0===n)return;const i=f(t,void 0===o?n+r.character:Math.min(o,n+r.character),!0);if(void 0===i)return;const a=p(i);return 0!==a.length?a:void 0};function ne(e){return Q(e.split(\"/\").pop()||\"\")}const oe=({ast:e},t,r=!1)=>{const n=function(e,t,r){e:for(const n of t){const t=Number.isInteger(Number(n))?Number(n):n;if(\"string\"==typeof t||\"number\"==typeof t&&\"array\"!==e.type){if(\"object\"!==e.type||!Array.isArray(e.children))return r?e:void 0;for(const r of e.children)if(Array.isArray(r.children)&&r.children[0].value===String(t)&&2===r.children.length){e=r.children[1];continue e}return r?e:void 0}if(\"array\"!==e.type||t<0||!Array.isArray(e.children)||t>=e.children.length)return r?e:void 0;e=e.children[t]}return e}(e,t,r);if(void 0!==n&&void 0!==n.range)return{range:n.range}};const ie=(e,t={disallowComments:!0})=>{const r=[],{ast:n,data:o,lineMap:i}=ae(e,r,t);return{data:o,diagnostics:r,ast:n,lineMap:i}};function ae(e,t=[],r){const n=ce(e);let o={type:\"array\",offset:-1,length:-1,children:[],parent:void 0},i=null,a=[];const s=new WeakMap,c=[];function u(e){\"property\"===o.type&&(o.length=e-o.offset,o=o.parent)}function l(e,t,r){return{start:{line:e,character:t},end:{line:e,character:t+r}}}function f(e){return o.children.push(e),e}function p(e){Array.isArray(a)?a.push(e):null!==i&&(a[i]=e)}function m(e){p(e),c.push(a),a=e,i=null}function b(){a=c.pop()}h(e,{onObjectBegin:(e,t,n,i)=>{o=f({type:\"object\",offset:e,length:-1,parent:o,children:[],range:l(n,i,t)}),!1===r.ignoreDuplicateKeys&&s.set(o,[]),m(function(e){return e?g({}):{}}(!0===r.preserveKeyOrder))},onObjectProperty:(e,n,c,u,p)=>{if((o=f({type:\"property\",offset:n,length:-1,parent:o,children:[]})).children.push({type:\"string\",value:e,offset:n,length:c,parent:o}),!1===r.ignoreDuplicateKeys){const r=s.get(o.parent);r&&(0!==r.length&&r.includes(e)?t.push({range:l(u,p,c),message:\"DuplicateKey\",severity:v.Error,path:ue(o),code:20}):r.push(e))}!0===r.preserveKeyOrder&&function(e,t){if(!(t in e))return;const r=d(e),n=r.indexOf(t);-1!==n&&(r.splice(n,1),r.push(t))}(a,e),i=e},onObjectEnd:(e,t,n,i)=>{!1===r.ignoreDuplicateKeys&&s.delete(o),o.length=e+t-o.offset,o.range&&(o.range.end.line=n,o.range.end.character=i+t),o=o.parent,u(e+t),b()},onArrayBegin:(e,t,r,n)=>{o=f({type:\"array\",offset:e,length:-1,parent:o,children:[],range:l(r,n,t)}),m([])},onArrayEnd:(e,t,r,n)=>{o.length=e+t-o.offset,o.range&&(o.range.end.line=r,o.range.end.character=n+t),o=o.parent,u(e+t),b()},onLiteralValue:(e,t,r,n,i)=>{f({type:se(e),offset:t,length:r,parent:o,value:e,range:l(n,i,r)}),u(t+r),p(e)},onSeparator:(e,t)=>{\"property\"===o.type&&(\":\"===e?o.colonOffset=t:\",\"===e&&u(t))},onError:(e,r,n,o,i)=>{t.push({range:l(o,i,n),message:y(e),severity:v.Error,code:e})}},r);const w=o.children[0];return w&&delete w.parent,{ast:w,data:a[0],lineMap:n}}function se(e){switch(typeof e){case\"boolean\":return\"boolean\";case\"number\":return\"number\";case\"string\":return\"string\";default:return\"null\"}}const ce=e=>{const t=[0];let r=0;for(;r{if(!e||!Object.hasOwnProperty.call(e,t)||t===r)return e;const n={};for(const[o,i]of Object.entries(e))o===t?n[r]=i:o in n||(n[o]=i);return n};function fe(e){return w(e)||Array.isArray(e)}function pe(e,t,r){if(r.length<=1||t.length<=1)throw Error(\"Source/target path must not be empty and point at root\");if(0===t.indexOf(r))throw Error(\"Target path cannot be contained within source\");const n=K(t);let o=e;for(const e of n){if(!fe(o))return;o=o[e]}if(!fe(o))return;const i=K(r);let a=e;for(const[e,t]of i.entries()){if(!fe(a)||t in a)return;const r=e===i.length-1?o:{};a[t]=r,a=r}delete e[n[0]],function e(t,r,n){for(const o of Object.keys(t)){const i=t[o];if(\"$ref\"!==o)fe(i)&&e(i,r,n);else{if(\"string\"!=typeof i||!E(i))continue;0===i.indexOf(r)&&(t[o]=i.replace(r,n))}}}(e,t,r)}async function he(e,t,r,n,o){let i=function(e,t){const r=V(t);return null===r?e:s(r)?r:c(u(e),r)}(t,r);const a=ee(r)||\"#\",l=await e[i],f=K(a);let p=[...f];const h={value:l};for(const[r,s]of L(h,f,a)){if(n.includes(s))return{source:t,location:null!=o?o:p,value:n[n.length-1]};n.push(s);const a=await he(e,i,s.$ref,n,p);({source:i,location:p}=a),h.value=a.value,p.push(...f.slice(r+1))}return{source:i,location:p,value:n.length>0?W(n[n.length-1],h.value):h.value}}async function ye(e,t,r){return(await ge(e,t,r)).value}function ge(e,t,r){return he(e,t,r,[])}const de=(e,t)=>{if(\"string\"!=typeof e)return e;try{const r=me(e);return\"string\"==typeof r?r:JSON.parse(e,t)}catch(e){return}},me=e=>{const t=Number(e);return Number.isFinite(t)?String(t)===e?t:e:NaN},ve=(e,t,r)=>{if(\"string\"==typeof e)return e;try{return JSON.stringify(e,t,r)}catch(n){return b(e,t,r)}},be=(e,t)=>{if(e instanceof Array){if(t instanceof Array){if(t.length>e.length)return!1;for(const r in t){if(!t.hasOwnProperty(r))continue;const n=parseInt(e[r]),o=parseInt(t[r]);if(isNaN(n)&&isNaN(o)){if(e[r]!==t[r])return!1}else if(n!==o)return!1}}}else{if(\"string\"!=typeof e)return!1;if(\"string\"==typeof t)return e.startsWith(t)}return!0},we=(e,t,r)=>{const n=ve(e,t,r);if(void 0===n)throw new Error(\"The value could not be stringified\");return n};function Oe(e){return e.replace(/^(\\/|#\\/)/,\"\").split(\"/\").map(Q).map(je).join(\".\")}function je(e){return e.includes(\".\")?`[\"${e.replace(/\"/g,'\\\\\"')}\"]`:e}const Ae=Symbol.for(m),$e={ownKeys:e=>Ae in e?e[Ae]:Reflect.ownKeys(e)},Ee=e=>new Proxy(e,$e);function Se(e,t){if(\"string\"==typeof e&&\"string\"==typeof t)return a(e,t);if(!(e&&Array.isArray(e)&&e.length&&t&&Array.isArray(t)&&t.length))return e;let r=0;for(const n in e)if(e.hasOwnProperty(n)){if(e[n]!==t[n])break;r++}return e.slice(r)}export{Z as BUNDLE_ROOT,q as ERRORS_ROOT,Ae as KEYS,G as bundleTarget,U as decodePointer,Q as decodePointerFragment,U as decodePointerUriFragment,X as decycle,Y as encodePointer,x as encodePointerFragment,k as encodePointerUriFragment,N as encodeUriPointer,ee as extractPointerFromRef,V as extractSourceFromRef,te as getFirstPrimitiveProperty,re as getJsonPathForPosition,ne as getLastPathSegment,oe as getLocationForJsonPath,$ as hasRef,M as isExternalRef,E as isLocalRef,w as isPlainObject,ae as parseTree,ie as parseWithPointers,P as pathToPointer,K as pointerToPath,F as remapRefs,le as renameObjectKey,pe as reparentBundleTarget,ye as resolveExternalRef,ge as resolveExternalRefWithLocation,B as resolveInlineRef,z as resolveInlineRefWithLocation,de as safeParse,ve as safeStringify,be as startsWith,we as stringify,Oe as toPropertyPath,Ee as trapAccess,D as traverse,Se as trimStart};\n","export default function (err) {\n return new Proxy(err, {\n getOwnPropertyDescriptor(target, key) {\n for (const prototype of traversePrototypeUntilErrorPrototype(target)) {\n if (Object.hasOwnProperty.call(prototype, key)) {\n const descriptor = Reflect.getOwnPropertyDescriptor(prototype, key);\n descriptor.enumerable = true;\n return descriptor;\n }\n }\n },\n\n ownKeys(target) {\n const keys = [];\n for (const prototype of traversePrototypeUntilErrorPrototype(target)) {\n for (const key of Reflect.ownKeys(prototype)) {\n if (!keys.includes(key)) {\n keys.push(key);\n }\n }\n }\n\n return keys;\n },\n\n set(target, key, value) {\n return Reflect.set(target, key, value);\n },\n });\n}\n\nfunction* traversePrototypeUntilErrorPrototype(prototype) {\n while (prototype !== null && prototype !== Error.prototype) {\n yield prototype;\n prototype = Object.getPrototypeOf(prototype);\n }\n}\n","import type { MirroredRegularNode } from './mirrored';\nimport type { RegularNode } from './RegularNode';\nimport type { RootNode } from './RootNode';\n\nlet SEED = BigInt(0); // cannot use literal, cause TS.\n\nexport abstract class BaseNode {\n public readonly id: string;\n\n public parent: RegularNode | RootNode | MirroredRegularNode | null = null;\n public subpath: string[];\n\n public get path(): ReadonlyArray {\n return this.parent === null ? this.subpath : [...this.parent.path, ...this.subpath];\n }\n\n public get depth(): number {\n return this.parent === null ? 0 : this.parent.depth + 1;\n }\n\n private get parentChildren(): BaseNode[] {\n return (this.parent?.children ?? []) as BaseNode[];\n }\n\n public get pos(): number {\n return Math.max(0, this.parentChildren.indexOf(this));\n }\n\n public get isFirst(): boolean {\n return this.pos === 0;\n }\n\n public get isLast(): boolean {\n return this.pos === this.parentChildren.length - 1;\n }\n\n protected constructor() {\n this.id = String(SEED++);\n this.subpath = [];\n }\n}\n","import { BaseNode } from './BaseNode';\n\nexport class BooleanishNode extends BaseNode {\n constructor(public readonly fragment: boolean) {\n super();\n }\n}\n","import type { SchemaFragment } from '../../types';\nimport { BaseNode } from '../BaseNode';\nimport type { ReferenceNode } from '../ReferenceNode';\n\nexport class MirroredReferenceNode extends BaseNode implements ReferenceNode {\n public readonly fragment: SchemaFragment;\n\n constructor(public readonly mirroredNode: ReferenceNode) {\n super();\n this.fragment = mirroredNode.fragment;\n }\n\n get error() {\n return this.mirroredNode.error;\n }\n\n get value() {\n return this.mirroredNode.value;\n }\n\n public get external() {\n return this.mirroredNode.external;\n }\n}\n","import type { Dictionary } from '@stoplight/types';\n\nimport type { SchemaFragment } from '../types';\n\nexport function isStringOrNumber(value: unknown): value is number | string {\n return typeof value === 'string' || typeof value === 'number';\n}\n\nexport function isObject(maybeObj: unknown): maybeObj is object {\n return maybeObj !== void 0 && maybeObj !== null && typeof maybeObj === 'object';\n}\n\nexport function isPrimitive(\n maybePrimitive: unknown,\n): maybePrimitive is string | number | boolean | undefined | null | symbol | bigint {\n return typeof maybePrimitive !== 'function' && !isObject(maybePrimitive);\n}\n\nexport function isObjectLiteral(maybeObj: unknown): maybeObj is Dictionary {\n if (isPrimitive(maybeObj) === true) return false;\n const proto = Object.getPrototypeOf(maybeObj);\n return proto === null || proto === Object.prototype;\n}\n\nexport function isNonNullable(maybeNullable: T): maybeNullable is NonNullable {\n return maybeNullable !== void 0 && maybeNullable !== null;\n}\n\nexport function isValidSchemaFragment(maybeSchemaFragment: unknown): maybeSchemaFragment is SchemaFragment {\n return typeof maybeSchemaFragment === 'boolean' || isObjectLiteral(maybeSchemaFragment);\n}\n","import type { Dictionary } from '@stoplight/types';\n\nexport function pick(target: object, keys: readonly (string | number)[]) {\n const source: Dictionary = {};\n\n for (const key of keys) {\n if (key in target) {\n source[key] = target[key];\n }\n }\n\n return source;\n}\n","import type { Dictionary } from '@stoplight/types';\n\nimport { isReferenceNode, isRegularNode } from '../../guards';\nimport type { SchemaFragment } from '../../types';\nimport { isNonNullable } from '../../utils';\nimport { BaseNode } from '../BaseNode';\nimport { BooleanishNode } from '../BooleanishNode';\nimport type { ReferenceNode } from '../ReferenceNode';\nimport type { RegularNode } from '../RegularNode';\nimport type { SchemaAnnotations, SchemaCombinerName, SchemaNodeKind } from '../types';\nimport { MirroredReferenceNode } from './MirroredReferenceNode';\n\nexport class MirroredRegularNode extends BaseNode implements RegularNode {\n public readonly fragment: SchemaFragment;\n public readonly $id!: string | null;\n public readonly types!: SchemaNodeKind[] | null;\n public readonly primaryType!: SchemaNodeKind | null;\n public readonly combiners!: SchemaCombinerName[] | null;\n\n public readonly required!: string[] | null;\n public readonly enum!: unknown[] | null;\n public readonly format!: string | null;\n public readonly title!: string | null;\n public readonly deprecated!: boolean;\n\n public readonly annotations!: Readonly>>;\n public readonly validations!: Readonly>;\n public readonly originalFragment!: SchemaFragment;\n\n public readonly simple!: boolean;\n public readonly unknown!: boolean;\n\n private readonly cache: WeakMap<\n RegularNode | BooleanishNode | ReferenceNode,\n MirroredRegularNode | BooleanishNode | MirroredReferenceNode\n >;\n\n constructor(public readonly mirroredNode: RegularNode, context?: { originalFragment?: SchemaFragment }) {\n super();\n this.fragment = mirroredNode.fragment;\n this.originalFragment = context?.originalFragment ?? mirroredNode.originalFragment;\n\n this.cache = new WeakMap();\n\n this._this = new Proxy(this, {\n get(target, key) {\n if (key in target) {\n return target[key];\n }\n\n if (key in mirroredNode) {\n return Reflect.get(mirroredNode, key, mirroredNode);\n }\n\n return;\n },\n\n has(target, key) {\n return key in target || key in mirroredNode;\n },\n });\n\n return this._this;\n }\n\n private readonly _this: MirroredRegularNode;\n\n private _children?: (MirroredRegularNode | BooleanishNode | MirroredReferenceNode)[];\n\n public get children(): (MirroredRegularNode | BooleanishNode | MirroredReferenceNode)[] | null | undefined {\n const referencedChildren = this.mirroredNode.children;\n\n if (!isNonNullable(referencedChildren)) {\n return referencedChildren;\n }\n\n if (this._children === void 0) {\n this._children = [];\n } else {\n this._children.length = 0;\n }\n\n const children: (MirroredRegularNode | BooleanishNode | MirroredReferenceNode)[] = this._children;\n for (const child of referencedChildren) {\n // this is to avoid pointing at nested mirroring\n const cached = this.cache.get(child);\n\n if (cached !== void 0) {\n children.push(cached);\n continue;\n }\n\n const mirroredChild = isRegularNode(child)\n ? new MirroredRegularNode(child)\n : isReferenceNode(child)\n ? new MirroredReferenceNode(child)\n : new BooleanishNode(child.fragment);\n\n mirroredChild.parent = this._this;\n mirroredChild.subpath = child.subpath;\n this.cache.set(child, mirroredChild);\n children.push(mirroredChild);\n }\n\n return children;\n }\n}\n","export function unwrapStringOrNull(value: unknown): string | null {\n return typeof value === 'string' ? value : null;\n}\n\nexport function unwrapArrayOrNull(value: unknown): unknown[] | null {\n return Array.isArray(value) ? value : null;\n}\n","import { isLocalRef } from '@stoplight/json';\n\nimport { unwrapStringOrNull } from '../accessors/unwrap';\nimport type { SchemaFragment } from '../types';\nimport { BaseNode } from './BaseNode';\n\nexport class ReferenceNode extends BaseNode {\n public readonly value: string | null;\n\n constructor(public readonly fragment: SchemaFragment, public readonly error: string | null) {\n super();\n\n this.value = unwrapStringOrNull(fragment.$ref);\n }\n\n public get external() {\n return this.value !== null && !isLocalRef(this.value);\n }\n}\n","import type { SchemaFragment } from '../types';\nimport { pick } from '../utils/pick';\n\nconst ANNOTATIONS = ['description', 'default', 'examples'] as const;\n\nexport type SchemaAnnotations = typeof ANNOTATIONS[number];\n\nexport function getAnnotations(fragment: SchemaFragment) {\n const annotations = pick(fragment, ANNOTATIONS);\n if ('example' in fragment && !Array.isArray(annotations.examples)) {\n // example is more OAS-ish, but it's common enough to be worth supporting\n annotations.examples = [fragment.example];\n }\n\n return annotations;\n}\n","import type { BooleanishNode } from './BooleanishNode';\nimport type { MirroredReferenceNode } from './mirrored/MirroredReferenceNode';\nimport type { MirroredRegularNode } from './mirrored/MirroredRegularNode';\nimport type { ReferenceNode } from './ReferenceNode';\nimport type { RegularNode } from './RegularNode';\nimport type { RootNode } from './RootNode';\n\nexport type MirroredSchemaNode = MirroredRegularNode | MirroredReferenceNode;\n\nexport type SchemaNode = RootNode | RegularNode | BooleanishNode | ReferenceNode | MirroredSchemaNode;\n\nexport enum SchemaNodeKind {\n Any = 'any',\n String = 'string',\n Number = 'number',\n Integer = 'integer',\n Boolean = 'boolean',\n Null = 'null',\n Array = 'array',\n Object = 'object',\n}\n\nexport enum SchemaCombinerName {\n AllOf = 'allOf',\n AnyOf = 'anyOf',\n OneOf = 'oneOf',\n}\n\nexport { SchemaAnnotations } from '../accessors/getAnnotations';\n","import { SchemaCombinerName } from '../nodes/types';\nimport type { SchemaFragment } from '../types';\n\nexport function getCombiners(fragment: SchemaFragment): SchemaCombinerName[] | null {\n let combiners: SchemaCombinerName[] | null = null;\n\n if (SchemaCombinerName.AnyOf in fragment) {\n combiners ??= [];\n combiners.push(SchemaCombinerName.AnyOf);\n }\n\n if (SchemaCombinerName.OneOf in fragment) {\n combiners ??= [];\n combiners.push(SchemaCombinerName.OneOf);\n }\n\n if (SchemaCombinerName.AllOf in fragment) {\n combiners ??= [];\n combiners.push(SchemaCombinerName.AllOf);\n }\n\n return combiners;\n}\n","import { SchemaNodeKind } from '../nodes/types';\nimport type { SchemaFragment } from '../types';\n\nexport function getPrimaryType(fragment: SchemaFragment, types: SchemaNodeKind[] | null) {\n if (types !== null) {\n if (types.includes(SchemaNodeKind.Object)) {\n return SchemaNodeKind.Object;\n }\n\n if (types.includes(SchemaNodeKind.Array)) {\n return SchemaNodeKind.Array;\n }\n\n if (types.length > 0) {\n return types[0];\n }\n\n return null;\n }\n\n return null;\n}\n","import { isStringOrNumber } from '../utils/guards';\n\nexport function getRequired(required: unknown): string[] | null {\n if (!Array.isArray(required)) return null;\n return required.filter(isStringOrNumber).map(String);\n}\n","import { SchemaNodeKind } from '../../nodes/types';\n\nconst VALID_TYPES = Object.values(SchemaNodeKind);\n\nexport const isValidType = (maybeType: unknown): maybeType is SchemaNodeKind =>\n typeof maybeType === 'string' && VALID_TYPES.includes(maybeType as SchemaNodeKind);\n","import { SchemaNodeKind } from '../nodes/types';\nimport type { SchemaFragment } from '../types';\n\nexport function inferType(fragment: SchemaFragment): SchemaNodeKind | null {\n if ('properties' in fragment || 'additionalProperties' in fragment || 'patternProperties' in fragment) {\n return SchemaNodeKind.Object;\n }\n\n if ('items' in fragment || 'additionalItems' in fragment) {\n return SchemaNodeKind.Array;\n }\n\n return null;\n}\n","import { SchemaNodeKind } from '../nodes/types';\nimport type { SchemaFragment } from '../types';\nimport { isValidType } from './guards/isValidType';\nimport { inferType } from './inferType';\n\nexport function getTypes(fragment: SchemaFragment): SchemaNodeKind[] | null {\n const types: SchemaNodeKind[] = [];\n let isNullable = false;\n\n if ('nullable' in fragment) {\n if (fragment.nullable === true) {\n isNullable = true;\n }\n }\n if ('type' in fragment) {\n if (Array.isArray(fragment.type)) {\n types.push(...fragment.type.filter(isValidType));\n } else if (isValidType(fragment.type)) {\n types.push(fragment.type);\n }\n if (isNullable && !types.includes(SchemaNodeKind.Null)) {\n types.push(SchemaNodeKind.Null);\n }\n return types;\n }\n\n const inferredType = inferType(fragment);\n if (inferredType !== null) {\n types.push(inferredType);\n if (isNullable && !types.includes(SchemaNodeKind.Null)) {\n types.push(SchemaNodeKind.Null);\n }\n return types;\n }\n\n return null;\n}\n","import type { Dictionary } from '@stoplight/types';\n\nimport type { SchemaNodeKind } from '../nodes/types';\nimport type { SchemaFragment } from '../types';\nimport { pick } from '../utils/pick';\n\nexport const COMMON_VALIDATION_TYPES: string[] = ['readOnly', 'writeOnly', 'style'];\n\nconst VALIDATION_TYPES: Partial> = {\n string: ['minLength', 'maxLength', 'pattern'],\n number: ['multipleOf', 'minimum', 'exclusiveMinimum', 'maximum', 'exclusiveMaximum'],\n get integer() {\n return this.number;\n },\n object: ['minProperties', 'maxProperties'],\n array: ['minItems', 'maxItems', 'uniqueItems'],\n};\n\nfunction getTypeValidations(types: SchemaNodeKind[]): (keyof SchemaFragment)[] | null {\n let extraValidations: (keyof SchemaFragment)[] | null = null;\n\n for (const type of types) {\n const value = VALIDATION_TYPES[type];\n if (value !== void 0) {\n extraValidations ??= [];\n extraValidations.push(...value);\n }\n }\n\n return extraValidations;\n}\n\nexport function getValidations(fragment: SchemaFragment, types: SchemaNodeKind[] | null): Dictionary {\n const extraValidations = types === null ? null : getTypeValidations(types);\n\n return {\n ...pick(fragment, COMMON_VALIDATION_TYPES),\n ...(extraValidations !== null ? pick(fragment, extraValidations) : null),\n };\n}\n","import type { SchemaFragment } from '../types';\n\nexport function isDeprecated(fragment: SchemaFragment): boolean {\n if ('x-deprecated' in fragment) {\n return fragment['x-deprecated'] === true;\n }\n\n if ('deprecated' in fragment) {\n return fragment.deprecated === true;\n }\n\n return false;\n}\n","import type { Dictionary } from '@stoplight/types';\n\nimport { getAnnotations } from '../accessors/getAnnotations';\nimport { getCombiners } from '../accessors/getCombiners';\nimport { getPrimaryType } from '../accessors/getPrimaryType';\nimport { getRequired } from '../accessors/getRequired';\nimport { getTypes } from '../accessors/getTypes';\nimport { getValidations } from '../accessors/getValidations';\nimport { isDeprecated } from '../accessors/isDeprecated';\nimport { unwrapArrayOrNull, unwrapStringOrNull } from '../accessors/unwrap';\nimport type { SchemaFragment } from '../types';\nimport { BaseNode } from './BaseNode';\nimport type { BooleanishNode } from './BooleanishNode';\nimport type { ReferenceNode } from './ReferenceNode';\nimport { MirroredSchemaNode, SchemaAnnotations, SchemaCombinerName, SchemaNodeKind } from './types';\n\nexport class RegularNode extends BaseNode {\n public readonly $id: string | null;\n public readonly types: SchemaNodeKind[] | null;\n public readonly primaryType: SchemaNodeKind | null; // object (first choice) or array (second option), primitive last\n public readonly combiners: SchemaCombinerName[] | null;\n\n public readonly required: string[] | null;\n public readonly enum: unknown[] | null; // https://tools.ietf.org/html/draft-fge-json-schema-validation-00#section-5.5.1\n public readonly format: string | null; // https://tools.ietf.org/html/draft-fge-json-schema-validation-00#section-7\n public readonly title: string | null;\n public readonly deprecated: boolean;\n\n public children: (RegularNode | BooleanishNode | ReferenceNode | MirroredSchemaNode)[] | null | undefined;\n\n public readonly annotations: Readonly>>;\n public readonly validations: Readonly>;\n public readonly originalFragment: SchemaFragment;\n\n constructor(public readonly fragment: SchemaFragment, context?: { originalFragment?: SchemaFragment }) {\n super();\n\n this.$id = unwrapStringOrNull('id' in fragment ? fragment.id : fragment.$id);\n this.types = getTypes(fragment);\n this.primaryType = getPrimaryType(fragment, this.types);\n this.combiners = getCombiners(fragment);\n\n this.deprecated = isDeprecated(fragment);\n this.enum = 'const' in fragment ? [fragment.const] : unwrapArrayOrNull(fragment.enum);\n this.required = getRequired(fragment.required);\n this.format = unwrapStringOrNull(fragment.format);\n this.title = unwrapStringOrNull(fragment.title);\n\n this.annotations = getAnnotations(fragment);\n this.validations = getValidations(fragment, this.types);\n this.originalFragment = context?.originalFragment ?? fragment;\n\n this.children = void 0;\n }\n\n public get simple() {\n return (\n this.primaryType !== SchemaNodeKind.Array && this.primaryType !== SchemaNodeKind.Object && this.combiners === null\n );\n }\n\n public get unknown() {\n return (\n this.types === null &&\n this.combiners === null &&\n this.format === null &&\n this.enum === null &&\n Object.keys(this.annotations).length + Object.keys(this.validations).length === 0\n );\n }\n}\n","import type { SchemaFragment } from '../types';\nimport { BaseNode } from './BaseNode';\nimport type { SchemaNode } from './types';\n\nexport class RootNode extends BaseNode {\n public readonly parent = null;\n public readonly children: SchemaNode[];\n\n constructor(public readonly fragment: SchemaFragment) {\n super();\n this.children = [];\n }\n}\n","import {\n MirroredReferenceNode,\n MirroredRegularNode,\n MirroredSchemaNode,\n ReferenceNode,\n RegularNode,\n RootNode,\n SchemaNode,\n} from '../nodes';\nimport type { BooleanishNode } from '../nodes/BooleanishNode';\n\nexport function isSchemaNode(node: unknown): node is SchemaNode {\n const name = Object.getPrototypeOf(node).constructor.name;\n return (\n name === RootNode.name ||\n name === RegularNode.name ||\n name === MirroredRegularNode.name ||\n name === ReferenceNode.name ||\n name === MirroredReferenceNode.name\n );\n}\n\nexport function isRootNode(node: SchemaNode): node is RootNode {\n return Object.getPrototypeOf(node).constructor.name === 'RootNode';\n}\n\nexport function isRegularNode(node: SchemaNode): node is RegularNode {\n return 'types' in node && 'primaryType' in node && 'combiners' in node;\n}\n\nexport function isMirroredNode(node: SchemaNode): node is MirroredSchemaNode {\n return 'mirroredNode' in node;\n}\n\nexport function isReferenceNode(node: SchemaNode): node is ReferenceNode {\n return 'external' in node && 'value' in node;\n}\n\nexport function isBooleanishNode(node: SchemaNode): node is BooleanishNode {\n return typeof node.fragment === 'boolean';\n}\n","export class ResolvingError extends ReferenceError {\n public readonly name = 'ResolvingError';\n}\n\nexport class MergingError extends Error {\n public readonly name = 'MergingError';\n}\n","import { pathToPointer } from '@stoplight/json';\n\nimport { ResolvingError } from '../errors';\nimport type { SchemaFragment } from '../types';\nimport type { WalkerRefResolver, WalkingOptions } from '../walker/types';\n\nconst resolveAllOf = require('@stoplight/json-schema-merge-allof');\n\nconst store = new WeakMap>();\n\nfunction _mergeAllOf(\n fragment: SchemaFragment,\n path: string[],\n resolveRef: WalkerRefResolver | null,\n seen: WeakMap,\n): SchemaFragment {\n const cached = seen.get(fragment);\n if (cached !== void 0) {\n return cached;\n }\n\n const merged = resolveAllOf(fragment, {\n deep: false,\n resolvers: resolveAllOf.stoplightResolvers,\n ...(resolveRef !== null\n ? {\n $refResolver($ref: unknown) {\n if (typeof $ref !== 'string') {\n return {};\n }\n\n if (pathToPointer(path).startsWith($ref)) {\n throw new ResolvingError('Circular reference detected');\n }\n\n const allRefs = store.get(resolveRef)!;\n let schemaRefs = allRefs.get(fragment);\n\n if (schemaRefs === void 0) {\n schemaRefs = [$ref];\n allRefs.set(fragment, schemaRefs);\n } else if (schemaRefs.includes($ref)) {\n const resolved = resolveRef(null, $ref);\n return 'allOf' in resolved ? _mergeAllOf(resolved, path, resolveRef, seen) : resolved;\n } else {\n schemaRefs.push($ref);\n }\n\n const resolved = resolveRef(null, $ref);\n\n if (Array.isArray(resolved.allOf)) {\n for (const member of resolved.allOf) {\n const index = schemaRefs.indexOf(member.$ref);\n if (typeof member.$ref === 'string' && index !== -1 && index !== schemaRefs.lastIndexOf(member.$ref)) {\n throw new ResolvingError('Circular reference detected');\n }\n }\n }\n\n return resolved;\n },\n }\n : null),\n });\n\n seen.set(fragment, merged);\n return merged;\n}\n\nexport function mergeAllOf(\n fragment: SchemaFragment,\n path: string[],\n walkingOptions: WalkingOptions,\n seen: WeakMap,\n) {\n if (walkingOptions.resolveRef !== null && !store.has(walkingOptions.resolveRef)) {\n store.set(walkingOptions.resolveRef, new WeakMap());\n }\n\n let merged = fragment;\n do {\n merged = _mergeAllOf(merged, path, walkingOptions.resolveRef, seen);\n } while ('allOf' in merged);\n\n return merged;\n}\n","import { SchemaCombinerName } from '../nodes/types';\nimport type { SchemaFragment } from '../types';\nimport type { WalkingOptions } from '../walker/types';\nimport { mergeAllOf } from './mergeAllOf';\n\nexport function mergeOneOrAnyOf(\n fragment: SchemaFragment,\n path: string[],\n walkingOptions: WalkingOptions,\n mergedAllOfs: WeakMap,\n): SchemaFragment[] {\n const combiner = SchemaCombinerName.OneOf in fragment ? SchemaCombinerName.OneOf : SchemaCombinerName.AnyOf;\n const items = fragment[combiner];\n\n if (!Array.isArray(items)) return []; // just in case\n\n const merged: SchemaFragment[] = [];\n\n if (Array.isArray(fragment.allOf)) {\n for (const item of items) {\n merged.push({\n allOf: [...fragment.allOf, item],\n });\n }\n\n return merged;\n } else {\n const prunedSchema = { ...fragment };\n delete prunedSchema[combiner];\n\n for (const item of items) {\n if (Object.keys(prunedSchema).length === 0) {\n merged.push(item);\n } else {\n merged.push(\n mergeAllOf(\n {\n allOf: [prunedSchema, item],\n },\n path,\n walkingOptions,\n mergedAllOfs,\n ),\n );\n }\n }\n }\n\n return merged;\n}\n","import { EventEmitter } from '@stoplight/lifecycle';\nimport type { Dictionary } from '@stoplight/types';\nimport createMagicError from 'magic-error';\n\nimport { MergingError } from '../errors';\nimport { isMirroredNode, isReferenceNode, isRegularNode, isRootNode } from '../guards';\nimport { mergeAllOf } from '../mergers/mergeAllOf';\nimport { mergeOneOrAnyOf } from '../mergers/mergeOneOrAnyOf';\nimport { MirroredReferenceNode, MirroredRegularNode, MirroredSchemaNode, ReferenceNode, RegularNode } from '../nodes';\nimport { BooleanishNode } from '../nodes/BooleanishNode';\nimport type { RootNode } from '../nodes/RootNode';\nimport { SchemaCombinerName, SchemaNode, SchemaNodeKind } from '../nodes/types';\nimport type { SchemaFragment } from '../types';\nimport { isNonNullable, isObjectLiteral, isValidSchemaFragment } from '../utils/guards';\nimport type { WalkerEmitter, WalkerHookAction, WalkerHookHandler, WalkerSnapshot, WalkingOptions } from './types';\n\ntype InternalWalkerState = {\n depth: number;\n pathLength: number;\n schemaNode: RegularNode | RootNode;\n};\n\ntype ProcessedFragment = SchemaFragment | SchemaFragment[];\n\nexport class Walker extends EventEmitter {\n public readonly path: string[];\n public depth: number;\n\n protected fragment: SchemaFragment | boolean;\n protected schemaNode: RegularNode | RootNode;\n\n private mergedAllOfs: WeakMap;\n private processedFragments: WeakMap;\n\n private readonly hooks: Partial>;\n\n constructor(protected readonly root: RootNode, protected readonly walkingOptions: WalkingOptions) {\n super();\n\n let maxRefDepth = walkingOptions.maxRefDepth ?? null;\n if (typeof maxRefDepth === 'number') {\n if (maxRefDepth < 1) {\n maxRefDepth = null;\n } else if (maxRefDepth > 1000) {\n // experimented with 1500 and the recursion limit is still lower than that\n maxRefDepth = 1000;\n }\n }\n walkingOptions.maxRefDepth = maxRefDepth;\n\n this.path = [];\n this.depth = -1;\n this.fragment = root.fragment;\n this.schemaNode = root;\n this.processedFragments = new WeakMap();\n this.mergedAllOfs = new WeakMap();\n\n this.hooks = {};\n }\n\n public destroy() {\n this.path.length = 0;\n this.depth = -1;\n this.fragment = this.root.fragment;\n this.schemaNode = this.root;\n this.processedFragments = new WeakMap();\n this.mergedAllOfs = new WeakMap();\n }\n\n public loadSnapshot(snapshot: WalkerSnapshot) {\n this.path.splice(0, this.path.length, ...snapshot.path);\n this.depth = snapshot.depth;\n this.fragment = snapshot.fragment;\n this.schemaNode = snapshot.schemaNode;\n }\n\n public saveSnapshot(): WalkerSnapshot {\n return {\n depth: this.depth,\n fragment: this.fragment,\n schemaNode: this.schemaNode,\n path: this.path.slice(),\n };\n }\n\n public hookInto(action: WalkerHookAction, handler: WalkerHookHandler) {\n this.hooks[action] = handler;\n }\n\n public restoreWalkerAtNode(node: RegularNode) {\n this.processedFragments.delete(node.fragment);\n this.path.splice(0, this.path.length, ...node.path);\n this.depth = node.depth;\n this.fragment = node.fragment;\n this.schemaNode = node;\n }\n\n public walk(): void {\n const { depth: initialDepth, fragment } = this;\n let { schemaNode: initialSchemaNode } = this;\n\n if (initialDepth === -1 && Object.keys(fragment).length === 0) {\n // empty schema, nothing to do\n return;\n }\n\n while (isMirroredNode(initialSchemaNode)) {\n if (!isRegularNode(initialSchemaNode.mirroredNode)) {\n return;\n }\n\n if (initialSchemaNode.mirroredNode.children === void 0) {\n this.restoreWalkerAtNode(initialSchemaNode.mirroredNode);\n initialSchemaNode = this.schemaNode;\n this.depth = initialDepth;\n } else {\n return;\n }\n }\n\n const state = this.dumpInternalWalkerState();\n\n super.emit('enterFragment', fragment);\n const [schemaNode, initialFragment] = this.processFragment();\n super.emit('enterNode', schemaNode);\n\n const actualNode = isMirroredNode(schemaNode) ? schemaNode.mirroredNode : schemaNode;\n if (typeof schemaNode.fragment !== 'boolean' && initialFragment !== null) {\n this.processedFragments.set(schemaNode.fragment, actualNode);\n this.processedFragments.set(initialFragment, actualNode);\n }\n\n this.fragment = schemaNode.fragment;\n this.depth = initialDepth + 1;\n\n if (!isRootNode(schemaNode)) {\n schemaNode.parent = initialSchemaNode;\n schemaNode.subpath = this.path.slice(initialSchemaNode.path.length);\n }\n\n const isIncluded = this.hooks.filter?.(schemaNode);\n\n if (isIncluded === false) {\n super.emit('skipNode', schemaNode);\n return;\n }\n\n if ('children' in initialSchemaNode && !isRootNode(schemaNode)) {\n if (initialSchemaNode.children === void 0) {\n (initialSchemaNode as RegularNode).children = [schemaNode];\n } else {\n initialSchemaNode.children!.push(schemaNode);\n }\n }\n\n super.emit('includeNode', schemaNode);\n\n if (isRegularNode(schemaNode)) {\n this.schemaNode = schemaNode;\n\n if (this.hooks.stepIn?.(schemaNode) !== false) {\n super.emit('stepInNode', schemaNode);\n this.walkNodeChildren();\n super.emit('stepOutNode', schemaNode);\n } else {\n super.emit('stepOverNode', schemaNode);\n }\n }\n\n super.emit('exitNode', schemaNode);\n this.restoreInternalWalkerState(state);\n super.emit('exitFragment', fragment);\n }\n\n protected dumpInternalWalkerState(): InternalWalkerState {\n return {\n depth: this.depth,\n pathLength: this.path.length,\n schemaNode: this.schemaNode,\n };\n }\n\n protected restoreInternalWalkerState({ depth, pathLength, schemaNode }: InternalWalkerState) {\n this.depth = depth;\n this.path.length = pathLength;\n this.schemaNode = schemaNode;\n }\n\n protected walkNodeChildren(): void {\n const { fragment, schemaNode } = this;\n\n if (!isRegularNode(schemaNode) || typeof fragment === 'boolean') return;\n\n const state = this.dumpInternalWalkerState();\n\n if (schemaNode.combiners !== null) {\n for (const combiner of schemaNode.combiners) {\n const items = fragment[combiner];\n if (!Array.isArray(items)) continue;\n\n let i = -1;\n for (const item of items) {\n i++;\n if (!isObjectLiteral(item)) continue;\n this.fragment = item;\n this.restoreInternalWalkerState(state);\n this.path.push(combiner, String(i));\n this.walk();\n }\n }\n }\n\n switch (schemaNode.primaryType) {\n case SchemaNodeKind.Array:\n if (Array.isArray(fragment.items)) {\n let i = -1;\n for (const item of fragment.items) {\n i++;\n if (!isValidSchemaFragment(item)) continue;\n this.fragment = item;\n this.restoreInternalWalkerState(state);\n this.path.push('items', String(i));\n this.walk();\n }\n } else {\n if (isObjectLiteral(fragment.items)) {\n this.fragment = fragment.items;\n this.restoreInternalWalkerState(state);\n this.path.push('items');\n this.walk();\n }\n\n if (isValidSchemaFragment(fragment.additionalItems)) {\n this.fragment = fragment.additionalItems;\n this.restoreInternalWalkerState(state);\n this.path.push('additionalItems');\n this.walk();\n }\n }\n\n break;\n case SchemaNodeKind.Object:\n if (isObjectLiteral(fragment.properties)) {\n for (const key of Object.keys(fragment.properties)) {\n const value = fragment.properties[key];\n if (!isValidSchemaFragment(value)) continue;\n this.fragment = value;\n this.restoreInternalWalkerState(state);\n this.path.push('properties', key);\n this.walk();\n }\n }\n\n if (isObjectLiteral(fragment.patternProperties)) {\n for (const key of Object.keys(fragment.patternProperties)) {\n const value = fragment.patternProperties[key];\n if (!isValidSchemaFragment(value)) continue;\n this.fragment = value;\n this.restoreInternalWalkerState(state);\n this.path.push('patternProperties', key);\n this.walk();\n }\n }\n\n if (isValidSchemaFragment(fragment.additionalProperties)) {\n this.fragment = fragment.additionalProperties;\n this.restoreInternalWalkerState(state);\n this.path.push('additionalProperties');\n this.walk();\n }\n\n break;\n }\n\n this.schemaNode = schemaNode;\n }\n\n protected retrieveFromFragment(\n fragment: ProcessedFragment,\n originalFragment: SchemaFragment,\n ): [MirroredSchemaNode, ProcessedFragment] | void {\n const processedSchemaNode = this.processedFragments.get(fragment);\n if (processedSchemaNode !== void 0) {\n if (isRegularNode(processedSchemaNode)) {\n return [new MirroredRegularNode(processedSchemaNode, { originalFragment }), fragment];\n }\n\n if (isReferenceNode(processedSchemaNode)) {\n return [new MirroredReferenceNode(processedSchemaNode), fragment];\n }\n\n // whoops, we don't know what to do with it\n throw new TypeError('Cannot mirror the node');\n }\n }\n\n protected processFragment(): [SchemaNode, ProcessedFragment | null] {\n const { walkingOptions, path, fragment: originalFragment, depth } = this;\n let { fragment } = this;\n\n if (typeof fragment === 'boolean') {\n return [new BooleanishNode(fragment), null];\n }\n\n if (typeof originalFragment === 'boolean') {\n throw new TypeError('Original fragment cannot be a boolean');\n }\n\n let retrieved = isNonNullable(fragment) ? this.retrieveFromFragment(fragment, fragment) : null;\n\n if (retrieved) {\n return retrieved;\n }\n\n let initialFragment: ProcessedFragment = fragment;\n\n if ('$ref' in fragment) {\n if (typeof walkingOptions.maxRefDepth === 'number' && walkingOptions.maxRefDepth < depth) {\n return [new ReferenceNode(fragment, `max $ref depth limit reached`), fragment];\n } else if (typeof fragment.$ref !== 'string') {\n return [new ReferenceNode(fragment, '$ref is not a string'), fragment];\n } else if (walkingOptions.resolveRef !== null) {\n try {\n let newFragment = walkingOptions.resolveRef(path, fragment.$ref);\n\n if (typeof fragment.description === 'string') {\n newFragment = { ...newFragment };\n Object.assign(newFragment, { description: fragment.description });\n } else {\n retrieved = this.retrieveFromFragment(newFragment, originalFragment);\n if (retrieved) {\n return retrieved;\n }\n }\n\n fragment = newFragment;\n } catch (ex) {\n super.emit('error', createMagicError(ex));\n return [new ReferenceNode(fragment, ex?.message ?? 'Unknown resolving error'), fragment];\n }\n } else {\n return [new ReferenceNode(fragment, null), fragment];\n }\n }\n //fragment with type 'array' and no description should adopt description of $ref if it exists.\n if (fragment.type === 'array' && fragment.description === void 0) {\n if (fragment.items !== void 0 && isObjectLiteral(fragment.items)) {\n for (const key of Object.keys(fragment.items)) {\n if (key === '$ref') {\n const refToResolve = fragment.items[key];\n if (typeof refToResolve !== 'string') {\n return [new ReferenceNode(fragment, '$ref is not a string'), fragment];\n } else if (walkingOptions.resolveRef !== null) {\n try {\n let newFragment = walkingOptions.resolveRef(path, refToResolve);\n if (newFragment.description !== void 0) {\n newFragment = { ...newFragment };\n Object.assign(fragment, { description: newFragment.description });\n }\n } catch (ex) {\n super.emit('error', createMagicError(ex));\n }\n }\n }\n }\n }\n }\n if (walkingOptions.mergeAllOf && SchemaCombinerName.AllOf in fragment) {\n try {\n if (Array.isArray(fragment.allOf)) {\n initialFragment = fragment.allOf;\n }\n\n fragment = mergeAllOf(fragment, path, walkingOptions, this.mergedAllOfs);\n } catch (ex) {\n initialFragment = fragment;\n super.emit('error', createMagicError(new MergingError(ex?.message ?? 'Unknown merging error')));\n // no the end of the world - we will render raw unprocessed fragment\n }\n }\n\n if (SchemaCombinerName.OneOf in fragment || SchemaCombinerName.AnyOf in fragment) {\n try {\n const merged = mergeOneOrAnyOf(fragment, path, walkingOptions, this.mergedAllOfs);\n if (merged.length === 1) {\n return [new RegularNode(merged[0], { originalFragment }), initialFragment];\n } else {\n const combiner = SchemaCombinerName.OneOf in fragment ? SchemaCombinerName.OneOf : SchemaCombinerName.AnyOf;\n return [new RegularNode({ [combiner]: merged }, { originalFragment }), initialFragment];\n }\n } catch (ex) {\n super.emit('error', createMagicError(new MergingError(ex?.message ?? 'Unknown merging error')));\n // no the end of the world - we will render raw unprocessed fragment\n }\n }\n\n retrieved = isNonNullable(fragment) ? this.retrieveFromFragment(initialFragment, originalFragment) : null;\n\n if (retrieved) {\n return retrieved;\n }\n\n return [new RegularNode(fragment, { originalFragment }), initialFragment];\n }\n}\n","import { extractPointerFromRef, extractSourceFromRef, resolveInlineRef } from '@stoplight/json';\n\nimport { ResolvingError } from '../errors';\nimport { RootNode } from '../nodes/RootNode';\nimport type { SchemaFragment } from '../types';\nimport { isObjectLiteral } from '../utils';\nimport { Walker } from '../walker';\nimport type { WalkerRefResolver } from '../walker/types';\nimport type { SchemaTreeOptions } from './types';\n\nexport class SchemaTree {\n public walker: Walker;\n public root: RootNode;\n private readonly resolvedRefs = new Map();\n\n constructor(public schema: SchemaFragment, protected readonly opts?: Partial) {\n this.root = new RootNode(schema);\n this.resolvedRefs = new Map();\n this.walker = new Walker(this.root, {\n mergeAllOf: this.opts?.mergeAllOf !== false,\n resolveRef: opts?.refResolver === null ? null : this.resolveRef,\n maxRefDepth: opts?.maxRefDepth,\n });\n }\n\n public destroy() {\n this.root.children.length = 0;\n this.walker.destroy();\n this.resolvedRefs.clear();\n }\n\n public populate() {\n this.invokeWalker(this.walker);\n }\n\n public invokeWalker(walker: Walker) {\n walker.walk();\n }\n\n protected resolveRef: WalkerRefResolver = (path, $ref) => {\n if (this.resolvedRefs.has($ref)) {\n return this.resolvedRefs.get($ref);\n }\n\n const seenRefs: string[] = [];\n let cur$ref: unknown = $ref;\n let resolvedValue!: SchemaFragment;\n\n while (typeof cur$ref === 'string') {\n if (seenRefs.includes(cur$ref)) {\n break;\n }\n\n seenRefs.push(cur$ref);\n resolvedValue = this._resolveRef(path, cur$ref);\n cur$ref = resolvedValue.$ref;\n }\n\n this.resolvedRefs.set($ref, resolvedValue);\n return resolvedValue;\n };\n\n private _resolveRef: WalkerRefResolver = (path, $ref) => {\n const source = extractSourceFromRef($ref);\n const pointer = extractPointerFromRef($ref);\n const refResolver = this.opts?.refResolver;\n\n if (typeof refResolver === 'function') {\n return refResolver({ source, pointer }, path, this.schema);\n } else if (source !== null) {\n throw new ResolvingError('Cannot dereference external references');\n } else if (pointer === null) {\n throw new ResolvingError('The pointer is empty');\n } else if (isObjectLiteral(this.schema)) {\n const value = resolveInlineRef(this.schema, pointer);\n if (!isObjectLiteral(value)) {\n throw new ResolvingError('Invalid value');\n }\n\n return value;\n } else {\n throw new ResolvingError('Unexpected input');\n }\n };\n}\n","import * as React from 'react';\n\nimport { ExtensionAddonRenderer, GoToRefHandler, RowAddonRenderer, ViewMode } from '../types';\n\nexport type ChangeType = 'added' | 'removed' | 'modified';\n\nexport type NodeHasChangedFn = (props: {\n nodeId: string;\n mode?: 'read' | 'write';\n}) => { type: ChangeType } | undefined;\n\nexport type JSVOptions = {\n defaultExpandedDepth: number;\n viewMode: ViewMode;\n onGoToRef?: GoToRefHandler;\n renderRowAddon?: RowAddonRenderer;\n renderExtensionAddon?: ExtensionAddonRenderer;\n hideExamples?: boolean;\n renderRootTreeLines?: boolean;\n disableCrumbs?: boolean;\n nodeHasChanged?: NodeHasChangedFn;\n};\n\nconst JSVOptionsContext = React.createContext({\n defaultExpandedDepth: 0,\n viewMode: 'standalone',\n hideExamples: false,\n});\n\nexport const useJSVOptionsContext = () => React.useContext(JSVOptionsContext);\n\nexport const JSVOptionsContextProvider = JSVOptionsContext.Provider;\n","export function isNonNullable(maybeNullable: T): maybeNullable is NonNullable {\n return maybeNullable !== void 0 && maybeNullable !== null;\n}\n","import { isPlainObject } from '@stoplight/json';\nimport {\n type MirroredSchemaNode,\n type ReferenceNode,\n type RegularNode,\n type SchemaNode,\n isBooleanishNode,\n isReferenceNode,\n isRegularNode,\n isRootNode,\n SchemaNodeKind,\n} from '@stoplight/json-schema-tree';\nimport { BooleanishNode } from '@stoplight/json-schema-tree/nodes/BooleanishNode';\n\nimport { isNonNullable } from '../guards/isNonNullable';\nimport type { ViewMode } from '../types';\nimport type {\n ArrayNode,\n ComplexArrayNode,\n ComplexDictionaryNode,\n DictionaryNode,\n FlattenableNode,\n PrimitiveArrayNode,\n PrimitiveDictionaryNode,\n} from './types';\n\nexport type ChildNode = RegularNode | ReferenceNode | MirroredSchemaNode;\n\nexport const isNonEmptyParentNode = (\n node: SchemaNode,\n): node is RegularNode & {\n children: ChildNode[] & { 0: ChildNode };\n} => isRegularNode(node) && !!node.children && node.children.length > 0;\n\nexport function isFlattenableNode(node: SchemaNode): node is FlattenableNode {\n if (!isRegularNode(node)) return false;\n\n if ((!isArrayNode(node) && !isDictionaryNode(node)) || !isNonNullable(node.children) || node.children.length === 0) {\n return false;\n }\n\n return (\n node.children.length === 1 &&\n ((isRegularNode(node.children[0]) && (!isArrayNode(node) || !isDictionaryNode(node.children[0]))) ||\n (isReferenceNode(node.children[0]) && node.children[0].error !== null))\n );\n}\n\nexport function isPrimitiveArray(node: SchemaNode): node is PrimitiveArrayNode {\n return isFlattenableNode(node) && isArrayNode(node) && isRegularNode(node.children[0]) && node.children[0].simple;\n}\n\nexport function isPrimitiveDictionary(node: SchemaNode): node is PrimitiveDictionaryNode {\n return (\n isFlattenableNode(node) && isDictionaryNode(node) && isRegularNode(node.children[0]) && node.children[0].simple\n );\n}\n\nexport function isComplexArray(node: SchemaNode): node is ComplexArrayNode {\n return isFlattenableNode(node) && isArrayNode(node) && isRegularNode(node.children[0]) && !node.children[0].simple;\n}\n\nexport function isComplexDictionary(node: SchemaNode): node is ComplexDictionaryNode {\n return (\n isFlattenableNode(node) && isDictionaryNode(node) && isRegularNode(node.children[0]) && !node.children[0].simple\n );\n}\n\nexport function isDictionaryNode(node: SchemaNode): node is DictionaryNode {\n return (\n isRegularNode(node) &&\n node.primaryType === SchemaNodeKind.Object &&\n isPlainObject(node.fragment.additionalProperties)\n );\n}\n\nexport function isArrayNode(node: SchemaNode): node is ArrayNode {\n return isRegularNode(node) && node.primaryType === SchemaNodeKind.Array;\n}\n\n/**\n * Returns the children of `node` that should be displayed in a viewer or\n * editor. Defaults to `node.children`, except for Arrays that get special\n * handling (flattening).\n */\nexport function visibleChildren(node: SchemaNode): SchemaNode[] {\n if (!isRegularNode(node) || isPrimitiveArray(node) || isPrimitiveDictionary(node)) {\n return [];\n }\n if (isComplexArray(node) || isComplexDictionary(node)) {\n // flatten the tree here, and show the properties of the item type directly\n return node.children[0].children ?? [];\n }\n return node.children ?? [];\n}\n\nexport function isPropertyRequired(schemaNode: SchemaNode): boolean {\n const { parent } = schemaNode;\n if (parent === null || !isRegularNode(parent) || schemaNode.subpath.length === 0) {\n return false;\n }\n\n return !!parent.required?.includes(schemaNode.subpath[schemaNode.subpath.length - 1]);\n}\n\nfunction isValidViewMode(node: RegularNode, viewMode: ViewMode): boolean {\n const { validations } = node;\n\n if (!!validations.writeOnly === !!validations.readOnly) {\n return true;\n }\n\n return !((viewMode === 'read' && !!validations.writeOnly) || (viewMode === 'write' && !!validations.readOnly));\n}\n\nfunction isRenderableNode(node: BooleanishNode | RegularNode): boolean {\n if (node.parent === null) return true;\n\n if (isDictionaryNode(node.parent)) {\n // if dictionary, do not render explicitly defined properties\n return node.subpath.length !== 2 || node.subpath[0] !== 'properties';\n }\n\n // do not render additionalItems\n if (isArrayNode(node.parent)) {\n return node.subpath[0] !== 'additionalItems';\n }\n\n // do not render true/false additionalProperties\n if (isRegularNode(node.parent) && node.parent.primaryType === SchemaNodeKind.Object && isBooleanishNode(node)) {\n return !(node.subpath.length === 1 || node.subpath[0] === 'additionalProperties');\n }\n\n return true;\n}\n\nexport function shouldNodeBeIncluded(node: SchemaNode, viewMode: ViewMode = 'standalone'): boolean {\n return (\n (isReferenceNode(node) || isRootNode(node) || isRenderableNode(node)) &&\n (!isRegularNode(node) || isValidViewMode(node, viewMode))\n );\n}\n","import { SchemaNode } from '@stoplight/json-schema-tree';\nimport { atom } from 'jotai';\nimport { atomFamily } from 'jotai/utils';\n\nexport const hoveredNodeAtom = atom(null);\n\nexport const isNodeHoveredAtom = atomFamily((node: SchemaNode) =>\n atom(get => node === get(hoveredNodeAtom)),\n);\n\nexport const isChildNodeHoveredAtom = atomFamily((parent: SchemaNode) =>\n atom(get => {\n const hoveredNode = get(hoveredNodeAtom);\n\n if (!hoveredNode || hoveredNode === parent) return false;\n\n return hoveredNode.parent === parent;\n }),\n);\n","import { isRegularNode, isRootNode, SchemaNode } from '@stoplight/json-schema-tree';\nimport { atom } from 'jotai';\n\nimport { hoveredNodeAtom } from '../SchemaRow/state';\n\nexport const pathCrumbsAtom = atom(get => {\n const node = get(hoveredNodeAtom);\n\n if (!node) return [];\n\n return propertyPathToObjectPath(node as SchemaNode);\n});\n\nfunction propertyPathToObjectPath(node: SchemaNode) {\n const objectPath: string[] = [];\n\n let currentNode: SchemaNode | null = node;\n while (currentNode && !isRootNode(currentNode)) {\n if (isRegularNode(currentNode)) {\n const pathPart = currentNode.subpath[currentNode.subpath.length - 1];\n\n if (currentNode.primaryType === 'array') {\n const key = `${pathPart || ''}[]`;\n if (objectPath[objectPath.length - 1]) {\n objectPath[objectPath.length - 1] = key;\n } else {\n objectPath.push(key);\n }\n } else if (\n pathPart &&\n (currentNode.subpath.length !== 2 || !['allOf', 'oneOf', 'anyOf'].includes(currentNode.subpath[0]))\n ) {\n objectPath.push(currentNode.subpath[currentNode.subpath.length - 1]);\n }\n }\n\n currentNode = currentNode.parent;\n }\n\n return objectPath.reverse();\n}\n","import { useAtomValue } from 'jotai';\nimport * as React from 'react';\n\nimport { useJSVOptionsContext } from '../../contexts';\nimport { pathCrumbsAtom } from './state';\n\nconst SCROLL_THRESHOLD = 20; // pixels scrolled before showing crumbs\n\nexport const PathCrumbs: React.FC<{ parentCrumbs?: string[] }> = ({ parentCrumbs = [] }) => {\n const pathCrumbs = useAtomValue(pathCrumbsAtom);\n const { disableCrumbs } = useJSVOptionsContext();\n const crumbsRef = React.useRef(null);\n const [style, setStyle] = React.useState({\n position: 'fixed',\n top: -100, // Start off-screen\n left: 0,\n width: 0,\n });\n const [hasScrolled, setHasScrolled] = React.useState(false);\n\n // JS-based sticky positioning\n React.useEffect(() => {\n const crumbsEl = crumbsRef.current;\n if (!crumbsEl) return;\n\n const scrollContainer = crumbsEl.closest('.jsv-root') as HTMLElement;\n if (!scrollContainer) return;\n\n const updatePosition = () => {\n const containerRect = scrollContainer.getBoundingClientRect();\n const scrolled = scrollContainer.scrollTop > SCROLL_THRESHOLD;\n \n setHasScrolled(scrolled);\n setStyle({\n position: 'fixed',\n top: Math.max(0, containerRect.top),\n left: containerRect.left,\n width: containerRect.width,\n });\n };\n\n updatePosition();\n scrollContainer.addEventListener('scroll', updatePosition);\n window.addEventListener('scroll', updatePosition);\n window.addEventListener('resize', updatePosition);\n\n return () => {\n scrollContainer.removeEventListener('scroll', updatePosition);\n window.removeEventListener('scroll', updatePosition);\n window.removeEventListener('resize', updatePosition);\n };\n }, []);\n\n if (disableCrumbs) {\n return null;\n }\n\n const parentCrumbElems: React.ReactNode[] = [];\n parentCrumbs.forEach((crumb, i) => {\n parentCrumbElems.push({crumb});\n });\n\n const pathCrumbElems: React.ReactNode[] = [];\n pathCrumbs.forEach((crumb, i) => {\n if (pathCrumbs[i + 1]) {\n pathCrumbElems.push({crumb});\n } else {\n pathCrumbElems.push(\n \n {crumb}\n ,\n );\n }\n });\n\n // Only show content when there's at least one crumb to display AND user has scrolled\n const hasCrumbs = parentCrumbElems.length > 0 || pathCrumbElems.length > 0;\n const isVisible = hasCrumbs && hasScrolled;\n\n return (\n
\n {parentCrumbElems.map((elem, i) => (\n \n {elem}\n {i < parentCrumbElems.length - 1 && /}\n \n ))}\n {parentCrumbElems.length > 0 && pathCrumbElems.length > 0 && /}\n {pathCrumbElems.map((elem, i) => (\n \n {elem}\n {i < pathCrumbElems.length - 1 && .}\n \n ))}\n
\n );\n};\n","import { SchemaCombinerName } from '@stoplight/json-schema-tree';\n\nexport const COMBINER_PRETTY_NAMES: Readonly> = {\n [SchemaCombinerName.AllOf]: 'and',\n [SchemaCombinerName.AnyOf]: 'and/or',\n [SchemaCombinerName.OneOf]: 'or',\n};\n\nexport const COMMON_JSON_SCHEMA_AND_OAS_FORMATS: Readonly> = {\n // strings are omitted because they are the default type to apply format to\n number: ['byte', 'int32', 'int64', 'float', 'double'],\n get integer() {\n return this.number;\n },\n};\n\nexport const NESTING_OFFSET = 3;\n\nexport const COMBINER_NAME_MAP: Record = {\n allOf: 'all of',\n anyOf: 'any of',\n oneOf: 'one of',\n};\n","import { isPlainObject } from '@stoplight/json';\nimport type { SchemaFragment, SchemaNode } from '@stoplight/json-schema-tree';\n\n// for easier debugging the values going into hash\nlet SKIP_HASHING = false;\n\nexport const setSkipHashing = (skip: boolean) => {\n SKIP_HASHING = skip;\n};\n\n// Simple FNV-1a 52-bit hash implementation\n// This produces the same output as fnv.fast1a52hex()\nfunction fnv1a52(str: string): string {\n const FNV_PRIME = 0x01000193;\n const FNV_OFFSET = 0x811c9dc5;\n \n let hash = FNV_OFFSET;\n for (let i = 0; i < str.length; i++) {\n hash ^= str.charCodeAt(i);\n hash = Math.imul(hash, FNV_PRIME);\n }\n \n // Convert to unsigned 32-bit and then to hex\n const hash32 = hash >>> 0;\n return hash32.toString(16).padStart(8, '0');\n}\n\nexport const hash = (value: string, skipHashing: boolean = SKIP_HASHING): string => {\n // Never change this, as it would affect how the default stable id is generated, and cause mismatches with whatever\n // we already have stored in our DB etc.\n return skipHashing ? value : fnv1a52(value);\n};\n\nfunction getStoplightId(fragment: SchemaFragment | boolean): string | undefined {\n if (typeof fragment === 'boolean') return undefined;\n const xStoplight = fragment['x-stoplight' as keyof typeof fragment];\n if (isPlainObject(xStoplight)) {\n const id = (xStoplight as Record).id;\n return typeof id === 'string' ? id : undefined;\n }\n return undefined;\n}\n\nexport const getNodeId = (node: SchemaNode, parentId?: string): string => {\n const nodeId = getStoplightId(node.fragment);\n if (nodeId) return nodeId;\n\n const key = node.path[node.path.length - 1];\n\n return hash(['schema_property', parentId, String(key)].join('-'));\n};\n\nexport const getOriginalNodeId = (node: SchemaNode, parentId?: string): string => {\n // @ts-expect-error originalFragment does exist...\n const nodeId = getStoplightId(node.originalFragment);\n if (nodeId) return nodeId;\n\n const key = node.path[node.path.length - 1];\n\n return hash(['schema_property', parentId, String(key)].join('-'));\n};\n","import { SchemaFragment } from '@stoplight/json-schema-tree';\n\nexport type VendorExtensionsList = {\n [keyof: string]: unknown;\n};\n\nexport type VendorExtensionsResult = [number, VendorExtensionsList];\n\n/**\n * Extract all vendor extensions or properties prefix with 'x-' from the schema definition\n * @param fragment The fragment to extract the vendor extensions from\n * @returns VendorExtensionsResult\n */\nexport function extractVendorExtensions(fragment: SchemaFragment | boolean): VendorExtensionsResult {\n if (typeof fragment === 'boolean') {\n return [0, {}];\n }\n\n const extensionKeys = Object.entries(fragment).filter(([key]) => key.startsWith('x-'));\n let vendorExtensions: VendorExtensionsList = {};\n\n for (const [key, value] of extensionKeys) {\n vendorExtensions[key] = value;\n }\n\n return [extensionKeys.length, vendorExtensions];\n}\n","import { CaretRight } from '@phosphor-icons/react';\nimport { clsx } from 'clsx';\nimport * as React from 'react';\n\nexport interface CaretProps {\n isExpanded: boolean;\n}\n\nexport const Caret: React.FC = ({ isExpanded }) => (\n \n \n \n);\n","import { SchemaNode } from '@stoplight/json-schema-tree';\nimport { clsx } from 'clsx';\nimport * as React from 'react';\n\nimport { useJSVOptionsContext } from '../../contexts';\nimport { SchemaRow, SchemaRowProps } from '../SchemaRow';\n\ntype ChangeType = 'added' | 'removed' | 'modified';\n\ntype ChildStackProps = {\n schemaNode: SchemaNode;\n childNodes: readonly SchemaNode[];\n currentNestingLevel: number;\n className?: string;\n parentNodeId?: string;\n RowComponent?: React.FC;\n parentChangeType?: ChangeType;\n};\n\nexport const ChildStack = React.memo(\n ({\n childNodes,\n currentNestingLevel,\n className,\n RowComponent = SchemaRow,\n parentNodeId,\n parentChangeType,\n }: ChildStackProps) => {\n const { renderRootTreeLines } = useJSVOptionsContext();\n const rootLevel = renderRootTreeLines ? 0 : 1;\n const isRootLevel = currentNestingLevel < rootLevel;\n\n return (\n \n {childNodes.map((childNode: SchemaNode) => (\n \n ))}\n \n );\n },\n);\n\nChildStack.displayName = 'ChildStack';\n","import * as React from 'react';\n\nexport interface DescriptionProps {\n value: unknown;\n}\n\nexport const Description: React.FC = ({ value }) => {\n const [showAll, setShowAll] = React.useState(false);\n\n if (typeof value !== 'string' || value.trim().length === 0) return null;\n\n const paragraphs = value.split('\\n\\n');\n\n if (paragraphs.length <= 1 || showAll) {\n return (\n
\n {value}\n
\n );\n }\n\n const firstParagraph = paragraphs[0];\n\n return (\n
\n

\n {firstParagraph}\n setShowAll(true)}\n >\n Show all...\n \n

\n
\n );\n};\n","import { clsx } from 'clsx';\nimport { Atom, useAtomValue } from 'jotai';\nimport * as React from 'react';\n\ninterface DividerProps {\n hoveredAtom: Atom;\n}\n\nexport const Divider: React.FC = ({ hoveredAtom }) => {\n const isHovered = useAtomValue(hoveredAtom);\n\n return (\n \n );\n};\n","import { isPlainObject } from '@stoplight/json';\nimport type { SchemaNode } from '@stoplight/json-schema-tree';\n\nexport function getInternalSchemaError(schemaNode: SchemaNode): string | undefined {\n let errorMessage;\n const fragment: unknown = schemaNode.fragment;\n if (!isPlainObject(fragment)) return;\n\n const xStoplight = fragment['x-stoplight'];\n\n if (isPlainObject(xStoplight) && typeof xStoplight['error-message'] === 'string') {\n errorMessage = xStoplight['error-message'];\n } else {\n const fragmentErrorMessage = fragment['x-sl-error-message'];\n if (typeof fragmentErrorMessage === 'string') {\n errorMessage = fragmentErrorMessage;\n } else {\n const items: unknown = fragment['items'];\n if (isPlainObject(items)) {\n const itemsErrorMessage = items['x-sl-error-message'];\n if (typeof itemsErrorMessage === 'string') {\n errorMessage = itemsErrorMessage;\n }\n }\n }\n }\n\n return errorMessage;\n}\n","import { isReferenceNode, isRegularNode, ReferenceNode, SchemaNode, SchemaNodeKind } from '@stoplight/json-schema-tree';\nimport { Warning } from '@phosphor-icons/react';\nimport * as React from 'react';\n\nimport { isFlattenableNode } from '../../tree';\nimport { getInternalSchemaError } from '../../utils/getInternalSchemaError';\n\nfunction useRefNode(schemaNode: SchemaNode) {\n return React.useMemo(() => {\n if (isReferenceNode(schemaNode)) {\n return schemaNode;\n }\n\n if (\n isRegularNode(schemaNode) &&\n (isFlattenableNode(schemaNode) ||\n (schemaNode.primaryType === SchemaNodeKind.Array && schemaNode.children?.length === 1))\n ) {\n return (schemaNode.children?.find(isReferenceNode) as ReferenceNode | undefined) ?? null;\n }\n\n return null;\n }, [schemaNode]);\n}\n\nexport const Error: React.FC<{ schemaNode: SchemaNode }> = ({ schemaNode }) => {\n const refNode = useRefNode(schemaNode);\n const error = getInternalSchemaError(schemaNode) ?? refNode?.error;\n\n if (typeof error !== 'string') return null;\n\n return (\n \n \n \n );\n};\n","import { clsx } from 'clsx';\nimport * as React from 'react';\n\ntype ChangeType = 'added' | 'removed' | 'modified';\n\nexport interface NodeAnnotationProps {\n change?: { type: ChangeType } | null;\n style?: React.CSSProperties;\n}\n\nexport const NodeAnnotation: React.FC = ({ change, style }) => {\n if (!change) return null;\n\n return (\n \n );\n};\n","import * as React from 'react';\n\nimport { useJSVOptionsContext } from '../../contexts';\n\nexport interface PropertiesProps {\n required: boolean;\n deprecated: boolean;\n validations: Record;\n}\n\nexport const useHasProperties = ({ required, deprecated, validations: { readOnly, writeOnly } }: PropertiesProps) => {\n const { viewMode } = useJSVOptionsContext();\n\n const showVisibilityValidations = viewMode === 'standalone' && !!readOnly !== !!writeOnly;\n\n return deprecated || showVisibilityValidations || required;\n};\n\nexport const Properties: React.FC = ({\n required,\n deprecated,\n validations: { readOnly, writeOnly },\n}) => {\n const { viewMode } = useJSVOptionsContext();\n\n // Show readOnly writeOnly validations only in standalone mode and only if just one of them is present\n const showVisibilityValidations = viewMode === 'standalone' && !!readOnly !== !!writeOnly;\n const visibility = showVisibilityValidations ? (\n readOnly ? (\n \n read-only\n \n ) : (\n \n write-only\n \n )\n ) : null;\n\n return (\n <>\n {deprecated ? (\n \n deprecated\n \n ) : null}\n {visibility}\n {required && (\n \n required\n \n )}\n \n );\n};\n","import { Select as BaseSelect } from '@base-ui/react/select';\nimport { CaretDown, Check } from '@phosphor-icons/react';\nimport * as React from 'react';\n\nexport interface SelectOption {\n value: string;\n label: string;\n}\n\nexport interface SelectProps {\n 'aria-label'?: string;\n options: SelectOption[];\n value: string;\n onChange: (value: string) => void;\n prefix?: string;\n}\n\nexport const Select: React.FC = ({\n 'aria-label': ariaLabel,\n options,\n value,\n onChange,\n prefix,\n}) => {\n return (\n {\n if (newValue !== null) {\n onChange(newValue);\n }\n }}\n >\n \n \n {(val) => {\n const selectedOption = options.find(opt => opt.value === val);\n return (\n <>\n {prefix}\n {selectedOption?.label ?? val}\n \n );\n }}\n \n \n \n \n \n \n \n \n {options.map(option => (\n \n \n \n \n {option.label}\n \n ))}\n \n \n \n \n );\n};\n","import { isPlainObject } from '@stoplight/json';\nimport { RegularNode, SchemaNodeKind } from '@stoplight/json-schema-tree';\n\nimport { COMMON_JSON_SCHEMA_AND_OAS_FORMATS } from '../consts';\n\nexport function getApplicableFormats(schemaNode: RegularNode): [type: SchemaNodeKind, format: string] | null {\n // JSON Schema itself doesn't directly support defining binary data types.\n // Within the http-spec repository, we address this limitation using\n // OpenAPI features i.e. `contentMediaType: 'application/octet-stream'`.\n // which is specific to OpenAPI and not supported by JSON Schema itself.\n\n const fragment = schemaNode.fragment;\n if (\n isPlainObject(fragment) &&\n (fragment as Record)['contentMediaType'] === 'application/octet-stream' &&\n schemaNode.types &&\n schemaNode.types.length > 0\n ) {\n return [schemaNode.types[0], 'binary'];\n }\n\n if (schemaNode.format === null) {\n return null;\n }\n\n if (schemaNode.types !== null) {\n for (const type of schemaNode.types) {\n if (!(type in COMMON_JSON_SCHEMA_AND_OAS_FORMATS)) continue;\n\n if (COMMON_JSON_SCHEMA_AND_OAS_FORMATS[type].includes(schemaNode.format)) {\n return [type, schemaNode.format];\n }\n }\n }\n\n return [SchemaNodeKind.String, schemaNode.format];\n}\n","import { getLastPathSegment } from '@stoplight/json';\nimport { isReferenceNode, isRegularNode, RegularNode, SchemaNodeKind } from '@stoplight/json-schema-tree';\n\nimport { isNonNullable } from '../guards/isNonNullable';\nimport {\n isComplexArray,\n isComplexDictionary,\n isDictionaryNode,\n isFlattenableNode,\n isPrimitiveArray,\n isPrimitiveDictionary,\n} from '../tree';\nimport { getApplicableFormats } from './getApplicableFormats';\n\nfunction upperFirst(str: string): string {\n return str.charAt(0).toUpperCase() + str.slice(1);\n}\n\ntype PrintNameOptions = {\n shouldUseRefNameFallback?: boolean;\n};\n\nexport function printName(\n schemaNode: RegularNode,\n { shouldUseRefNameFallback = false }: PrintNameOptions = {},\n): string | undefined {\n if (!isFlattenableNode(schemaNode)) {\n return schemaNode.title ?? (shouldUseRefNameFallback ? getNodeNameFromOriginalRef(schemaNode) : undefined);\n }\n\n return printFlattenedName(schemaNode, { shouldUseRefNameFallback });\n}\n\nfunction printFlattenedName(\n schemaNode: RegularNode,\n { shouldUseRefNameFallback = false }: PrintNameOptions,\n): string | undefined {\n if (!isNonNullable(schemaNode.children) || schemaNode.children.length === 0) {\n return schemaNode.title ?? (shouldUseRefNameFallback ? getNodeNameFromOriginalRef(schemaNode) : undefined);\n }\n\n if (schemaNode.children.length === 1 && isReferenceNode(schemaNode.children[0])) {\n const value = `$ref(${schemaNode.children[0].value})`;\n return isDictionaryNode(schemaNode) ? `dictionary[string, ${value}]` : `${value}[]`;\n }\n\n const format = isDictionaryNode(schemaNode) ? 'dictionary[string, %s]' : 'array[%s]';\n\n if (isPrimitiveArray(schemaNode) || isPrimitiveDictionary(schemaNode)) {\n const val =\n schemaNode.children?.reduce<(SchemaNodeKind | `${SchemaNodeKind}<${string}>`)[] | null>((mergedTypes, child) => {\n if (mergedTypes === null) return null;\n\n if (!isRegularNode(child)) return null;\n\n if (child.types !== null && child.types.length > 0) {\n const formats = getApplicableFormats(child);\n for (const type of child.types) {\n if (mergedTypes.includes(type)) continue;\n\n if (formats !== null && formats[0] === type) {\n mergedTypes.push(`${type}<${formats[1]}>`);\n } else {\n mergedTypes.push(type);\n }\n }\n }\n\n return mergedTypes;\n }, []) ?? null;\n\n if (val !== null && val.length > 0) {\n return format.replace('%s', val.join(' or '));\n }\n\n return isDictionaryNode(schemaNode) ? 'dictionary[string, any]' : 'array';\n }\n\n if (isComplexArray(schemaNode) || isComplexDictionary(schemaNode)) {\n const firstChild = schemaNode.children[0];\n if (firstChild.title) {\n return format.replace('%s', firstChild.title);\n } else if (shouldUseRefNameFallback && getNodeNameFromOriginalRef(schemaNode)) {\n return format.replace('%s', getNodeNameFromOriginalRef(schemaNode) ?? 'any');\n } else if (firstChild.primaryType) {\n return format.replace('%s', firstChild.primaryType);\n } else if (firstChild.combiners?.length) {\n return format.replace('%s', firstChild.combiners.join(' '));\n }\n return isComplexArray(schemaNode) ? 'array' : format.replace('%s', 'any');\n }\n\n return undefined;\n}\n\nfunction getNodeNameFromOriginalRef(node: RegularNode) {\n if (typeof node.originalFragment.$ref === 'string') {\n return upperFirst(getLastPathSegment(node.originalFragment.$ref));\n }\n return undefined;\n}\n","import {\n isBooleanishNode,\n isReferenceNode,\n isRegularNode,\n RegularNode,\n SchemaCombinerName,\n SchemaNode,\n SchemaNodeKind,\n} from '@stoplight/json-schema-tree';\nimport * as React from 'react';\n\nimport { printName } from '../../utils';\nimport { getApplicableFormats } from '../../utils/getApplicableFormats';\n\nfunction shouldRenderName(type: SchemaNodeKind | SchemaCombinerName | '$ref'): boolean {\n return type === SchemaNodeKind.Array || type === SchemaNodeKind.Object || type === '$ref';\n}\n\nfunction getTypes(schemaNode: RegularNode): Array {\n return [schemaNode.types, schemaNode.combiners].reduce>(\n (values, value) => {\n if (value === null) {\n return values;\n }\n\n values.push(...value);\n return values;\n },\n [],\n );\n}\n\nexport const Types: React.FC<{ schemaNode: SchemaNode }> = ({ schemaNode }) => {\n if (isReferenceNode(schemaNode)) {\n return (\n \n {schemaNode.value ?? '$ref'}\n \n );\n }\n\n if (isBooleanishNode(schemaNode)) {\n return (\n \n {schemaNode.fragment ? 'any' : 'never'}\n \n );\n }\n\n if (!isRegularNode(schemaNode)) {\n return null;\n }\n\n const formats = getApplicableFormats(schemaNode);\n const types = getTypes(schemaNode);\n\n if (types.length === 0) {\n return (\n \n {formats === null ? 'any' : `<${formats[1]}>`}\n \n );\n }\n\n const rendered = types.map((type, i, { length }) => {\n let printedName;\n if (shouldRenderName(type)) {\n printedName = printName(schemaNode);\n }\n\n printedName ??= type + (formats === null || formats[0] !== type ? '' : `<${formats[1]}>`);\n\n return (\n \n \n {printedName}\n \n\n {i < length - 1 && (\n \n {' or '}\n \n )}\n \n );\n });\n\n return rendered.length > 1 ? {rendered} : <>{rendered};\n};\n\nTypes.displayName = 'JsonSchemaViewer.Types';\n","import { isRegularNode, RegularNode } from '@stoplight/json-schema-tree';\nimport * as React from 'react';\n\nexport interface ValidationsProps {\n validations: Record;\n hideExamples?: boolean;\n}\n\ntype ValidationFormat = {\n name: string;\n values: string[];\n};\n\nexport const numberValidationNames = [\n 'minimum',\n 'maximum',\n 'minLength',\n 'maxLength',\n 'minItems',\n 'maxItems',\n 'exclusiveMinimum',\n 'exclusiveMaximum',\n];\n\ntype NumberValidationNames = typeof numberValidationNames;\n\nconst exampleValidationNames = ['examples'];\n\nconst excludedValidations = ['exclusiveMinimum', 'exclusiveMaximum', 'readOnly', 'writeOnly'];\n\nconst numberValidationFormatters: Record string> = {\n minimum: value => `>= ${value}`,\n exclusiveMinimum: value => `> ${value}`,\n minItems: value => `>= ${value} items`,\n minLength: value => `>= ${value} characters`,\n maximum: value => `<= ${value}`,\n exclusiveMaximum: value => `< ${value}`,\n maxItems: value => `<= ${value} items`,\n maxLength: value => `<= ${value} characters`,\n};\n\nconst createStringFormatter = (nowrap: boolean | undefined) => (value: unknown) => {\n return nowrap && typeof value === 'string' ? value : JSON.stringify(value);\n};\n\nconst createValidationsFormatter =\n (name: string, options?: { exact?: boolean; nowrap?: boolean }) =>\n (value: unknown[] | unknown): ValidationFormat | null => {\n const values = Array.isArray(value) ? value : [value];\n if (values.length) {\n return {\n name: options?.exact ? name : values.length > 1 ? `${name}s` : `${name}`,\n values: values.map(createStringFormatter(options?.nowrap)),\n };\n }\n return null;\n };\n\nconst validationFormatters: Record ValidationFormat | null> = {\n enum: createValidationsFormatter('Allowed value', { nowrap: true }),\n examples: createValidationsFormatter('Example', { nowrap: true }),\n multipleOf: createValidationsFormatter('Multiple of', { exact: true }),\n pattern: createValidationsFormatter('Match pattern', { exact: true, nowrap: true }),\n default: createValidationsFormatter('Default', { exact: true, nowrap: true }),\n style: createValidationsFormatter('Style', { exact: true, nowrap: true }),\n};\n\nconst oasFormats = {\n int32: {\n minimum: 0 - 2 ** 31,\n maximum: 2 ** 31 - 1,\n },\n int64: {\n minimum: Number.MIN_SAFE_INTEGER,\n maximum: Number.MAX_SAFE_INTEGER,\n },\n float: {\n minimum: 0 - 2 ** 128,\n maximum: 2 ** 128 - 1,\n },\n double: {\n minimum: 0 - Number.MAX_VALUE,\n maximum: Number.MAX_VALUE,\n },\n byte: {\n pattern: '^[\\\\w\\\\d+\\\\/=]*$',\n },\n};\n\nfunction isOasFormat(format: string): format is keyof typeof oasFormats {\n return format in oasFormats;\n}\n\nfunction filterOutOasFormatValidations(format: string, values: Record) {\n if (!isOasFormat(format)) {\n return values;\n }\n\n const newValues = { ...values };\n\n for (const [key, value] of Object.entries(oasFormats[format])) {\n if (value === newValues[key]) {\n delete newValues[key];\n }\n }\n\n return newValues;\n}\n\nfunction pick>(obj: T, keys: string[]): Partial {\n const result: Partial = {};\n for (const key of keys) {\n if (key in obj) {\n result[key as keyof T] = obj[key as keyof T];\n }\n }\n return result;\n}\n\nfunction omit>(obj: T, keys: string[]): Partial {\n const result = { ...obj };\n for (const key of keys) {\n delete result[key as keyof T];\n }\n return result;\n}\n\nfunction capitalize(str: string): string {\n return str.charAt(0).toUpperCase() + str.slice(1);\n}\n\nfunction uniq(arr: T[]): T[] {\n return [...new Set(arr)];\n}\n\nexport const Validations: React.FC = ({ validations, hideExamples }) => {\n const numberValidations = pick(validations, numberValidationNames);\n const keyValueValidations = omit(validations, [\n ...Object.keys(numberValidations),\n ...excludedValidations,\n ...(hideExamples ? exampleValidationNames : []),\n ]);\n\n return (\n
\n \n \n
\n );\n};\n\nconst NumberValidations: React.FC<{\n validations: Partial>;\n}> = ({ validations }) => {\n const entries = Object.entries(validations);\n if (!entries.length) {\n return null;\n }\n return (\n
\n {entries\n .map(([key, value]) => numberValidationFormatters[key](value))\n .map((value, i) => (\n \n ))}\n
\n );\n};\n\nconst KeyValueValidations: React.FC<{ validations: Record }> = ({ validations }) => (\n <>\n {Object.keys(validations)\n .filter(key => Object.keys(validationFormatters).includes(key) && validations[key] !== void 0)\n .map(key => {\n const validation = validationFormatters[key](validations[key]);\n if (validation) {\n return ;\n } else {\n return null;\n }\n })}\n \n);\n\nconst KeyValueValidation: React.FC<{ name: string; values: string[] }> = ({ name, values }) => {\n return (\n
\n {capitalize(name)}:\n
\n {uniq(values).map(value => (\n \n ))}\n
\n
\n );\n};\n\nconst Value: React.FC<{ name: string }> = ({ name }) => (\n {name}\n);\n\nexport function validationCount(schemaNode: RegularNode) {\n const validations = getValidationsFromSchema(schemaNode);\n const validationKeys = Object.keys(omit(validations, excludedValidations));\n return uniq(validationKeys.map(key => ([...numberValidationNames].includes(key) ? 'number' : key))).length;\n}\n\nconst getArrayValidations = (schemaNode: RegularNode) => {\n if (schemaNode.children?.length === 1 && isRegularNode(schemaNode.children[0])) {\n if (schemaNode.children[0].enum !== null) {\n return { enum: schemaNode.children[0].enum };\n } else if (schemaNode.children[0].fragment.pattern !== void 0) {\n return { pattern: schemaNode.children[0].fragment.pattern };\n }\n }\n return null;\n};\n\nexport function getValidationsFromSchema(schemaNode: RegularNode) {\n return {\n ...(schemaNode.enum !== null\n ? { enum: schemaNode.enum }\n : schemaNode.primaryType === 'array'\n ? // in case schemaNode is type: \"array\", check if its child has an additional validation\n getArrayValidations(schemaNode)\n : null),\n ...('annotations' in schemaNode\n ? {\n ...(schemaNode.annotations.default !== void 0 ? { default: schemaNode.annotations.default } : null),\n ...(schemaNode.annotations.examples ? { examples: schemaNode.annotations.examples } : null),\n }\n : null),\n ...getFilteredValidations(schemaNode),\n };\n}\n\nfunction getFilteredValidations(schemaNode: RegularNode) {\n if (schemaNode.format !== null) {\n return filterOutOasFormatValidations(schemaNode.format, schemaNode.validations);\n }\n\n return schemaNode.validations;\n}\n","import { extractPointerFromRef, pointerToPath } from '@stoplight/json';\nimport { isReferenceNode, isRegularNode, SchemaNode } from '@stoplight/json-schema-tree';\nimport * as React from 'react';\n\nimport { isComplexArray, isNonEmptyParentNode } from '../../tree';\nimport { printName } from '../../utils';\n\n/** one option among several mutually exclusive sub-schemas */\nexport type Choice = {\n title: string;\n type: SchemaNode;\n};\n\nfunction last(arr: T[]): T | undefined {\n return arr[arr.length - 1];\n}\n\nfunction calculateChoiceTitle(node: SchemaNode, isPlural: boolean): string {\n const primitiveSuffix = isPlural ? 's' : '';\n if (isRegularNode(node)) {\n const realName = printName(node, { shouldUseRefNameFallback: true });\n if (realName) {\n return realName;\n }\n return node.primaryType !== null\n ? node.primaryType + primitiveSuffix\n : String(node.originalFragment.title || 'any');\n }\n if (isReferenceNode(node)) {\n if (node.value) {\n const value = extractPointerFromRef(node.value);\n const lastPiece = !node.error && value ? last(pointerToPath(value)) : null;\n if (typeof lastPiece === 'string') {\n return lastPiece.split('.')[0];\n }\n }\n return '$ref' + primitiveSuffix;\n }\n\n return 'any';\n}\n\nfunction makeChoice(node: SchemaNode): Choice {\n return {\n type: node,\n title: calculateChoiceTitle(node, false),\n };\n}\n\nfunction makeArrayChoice(node: SchemaNode, combiner?: string): Choice {\n const itemTitle = calculateChoiceTitle(node, true);\n const title = itemTitle !== 'any' ? `array ${combiner ? `(${combiner})` : null} [${itemTitle}]` : 'array';\n return {\n type: node,\n title,\n };\n}\n\n/**\n * Enumerates the sub-schema type for a given node.\n *\n * Usually a node has one choice, only one possible type: itself. If a node is\n * a oneOf or anyOf combiner, the possible types are the sub-types of the\n * combiner.\n */\nexport const useChoices = (schemaNode: SchemaNode) => {\n const choices: Choice[] = React.useMemo(() => {\n // handle flattening of arrays that contain oneOfs, same logic as below\n if (\n isComplexArray(schemaNode) &&\n isNonEmptyParentNode(schemaNode.children[0]) &&\n shouldShowChildSelector(schemaNode.children[0])\n ) {\n return schemaNode.children[0].children.map(child =>\n makeArrayChoice(child, schemaNode.children[0].combiners?.[0]),\n );\n }\n\n // if current node is a combiner, offer its children\n if (isNonEmptyParentNode(schemaNode) && shouldShowChildSelector(schemaNode)) {\n return schemaNode.children.map(makeChoice);\n }\n // regular node, single choice - itself\n return [makeChoice(schemaNode)];\n }, [schemaNode]);\n\n const defaultChoice = choices[0];\n\n const [selectedChoice, setSelectedChoice] = React.useState(defaultChoice);\n\n React.useEffect(() => {\n setSelectedChoice(defaultChoice);\n }, [defaultChoice]);\n\n const actualSelectedChoice = selectedChoice && choices.includes(selectedChoice) ? selectedChoice : defaultChoice;\n\n return { selectedChoice: actualSelectedChoice, setSelectedChoice, choices };\n};\n\nconst shouldShowChildSelector = (schemaNode: SchemaNode) =>\n isNonEmptyParentNode(schemaNode) && ['anyOf', 'oneOf'].includes(schemaNode.combiners?.[0] ?? '');\n","import { isMirroredNode, isReferenceNode, isRegularNode, SchemaNode } from '@stoplight/json-schema-tree';\nimport { clsx } from 'clsx';\nimport { useSetAtom } from 'jotai';\nimport * as React from 'react';\n\nimport { COMBINER_NAME_MAP } from '../../consts';\nimport { useJSVOptionsContext } from '../../contexts';\nimport { getNodeId, getOriginalNodeId } from '../../hash';\nimport { isPropertyRequired, visibleChildren } from '../../tree';\nimport { extractVendorExtensions } from '../../utils/extractVendorExtensions';\nimport {\n Caret,\n ChildStack,\n Description,\n Divider,\n Error,\n getValidationsFromSchema,\n NodeAnnotation,\n Properties,\n Select,\n Types,\n useHasProperties,\n Validations,\n} from '../shared';\nimport { hoveredNodeAtom, isNodeHoveredAtom } from './state';\nimport { useChoices } from './useChoices';\n\ntype ChangeType = 'added' | 'removed' | 'modified';\n\nexport interface SchemaRowProps {\n schemaNode: SchemaNode;\n nestingLevel: number;\n pl?: number;\n parentNodeId?: string;\n parentChangeType?: ChangeType;\n}\n\nexport const SchemaRow: React.FC = React.memo(\n ({ schemaNode, nestingLevel, pl, parentNodeId, parentChangeType }) => {\n const {\n defaultExpandedDepth,\n renderRowAddon,\n renderExtensionAddon,\n onGoToRef,\n hideExamples,\n renderRootTreeLines,\n nodeHasChanged,\n viewMode,\n } = useJSVOptionsContext();\n\n const setHoveredNode = useSetAtom(hoveredNodeAtom);\n\n const nodeId = getNodeId(schemaNode, parentNodeId);\n\n // @ts-expect-error originalFragment does exist...\n const originalNodeId = schemaNode.originalFragment?.$ref ? getOriginalNodeId(schemaNode, parentNodeId) : nodeId;\n const mode = viewMode === 'standalone' ? undefined : viewMode;\n const hasChanged = nodeHasChanged?.({ nodeId: originalNodeId, mode });\n\n const [isExpanded, setExpanded] = React.useState(\n !isMirroredNode(schemaNode) && nestingLevel <= defaultExpandedDepth,\n );\n\n const { selectedChoice, setSelectedChoice, choices } = useChoices(schemaNode);\n const typeToShow = selectedChoice.type;\n const description = isRegularNode(typeToShow) ? typeToShow.annotations.description : null;\n\n const rootLevel = renderRootTreeLines ? 1 : 2;\n const childNodes = React.useMemo(() => visibleChildren(typeToShow), [typeToShow]);\n const combiner = isRegularNode(schemaNode) && schemaNode.combiners?.length ? schemaNode.combiners[0] : null;\n const isCollapsible = childNodes.length > 0;\n const isRootLevel = nestingLevel < rootLevel;\n\n const required = isPropertyRequired(schemaNode);\n const deprecated = isRegularNode(schemaNode) && schemaNode.deprecated;\n const validations = isRegularNode(schemaNode) ? schemaNode.validations : {};\n const hasProperties = useHasProperties({ required, deprecated, validations });\n\n const [totalVendorExtensions, vendorExtensions] = React.useMemo(\n () => extractVendorExtensions(schemaNode.fragment),\n [schemaNode.fragment],\n );\n const hasVendorProperties = totalVendorExtensions > 0;\n\n const annotationRootOffset = renderRootTreeLines ? 0 : 8;\n let annotationLeftOffset = -20 - annotationRootOffset;\n if (nestingLevel > 1) {\n annotationLeftOffset =\n -1 * 29 * Math.max(nestingLevel - 1, 1) - Math.min(nestingLevel, 2) * 2 - 16 - annotationRootOffset;\n\n if (!renderRootTreeLines) {\n annotationLeftOffset += 27;\n }\n }\n\n if (parentChangeType === 'added' && hasChanged && hasChanged.type === 'removed') {\n return null;\n }\n\n if (parentChangeType === 'removed' && hasChanged && hasChanged.type === 'added') {\n return null;\n }\n\n const lastSubpath = schemaNode.subpath.length > 0 ? schemaNode.subpath[schemaNode.subpath.length - 1] : null;\n const isHoveredAtom = isNodeHoveredAtom(schemaNode);\n\n return (\n <>\n {\n e.stopPropagation();\n setHoveredNode(selectedChoice.type);\n }}\n >\n {!isRootLevel && (\n \n )}\n {parentChangeType !== 'added' && parentChangeType !== 'removed' ? (\n \n ) : null}\n
\n setExpanded(!isExpanded) : undefined}\n >\n {isCollapsible ? : null}\n
\n {schemaNode.subpath.length > 0 && shouldShowPropertyName(schemaNode) && (\n \n {lastSubpath}\n \n )}\n\n {choices.length === 1 && }\n\n {onGoToRef && isReferenceNode(schemaNode) && schemaNode.external ? (\n {\n e.preventDefault();\n e.stopPropagation();\n onGoToRef(schemaNode);\n }}\n >\n (go to ref)\n \n ) : null}\n\n {schemaNode.subpath.length > 1 && schemaNode.subpath[0] === 'patternProperties' ? (\n (pattern property)\n ) : null}\n\n {choices.length > 1 && (\n ({\n value: String(index),\n label: choice.title,\n }))}\n value={String(choices.indexOf(selectedChoice))}\n onChange={selectedIndex => setSelectedChoice(choices[Number(selectedIndex)])}\n />\n )}\n
\n {hasProperties && }\n \n
\n {typeof description === 'string' &&\n (!combiner || schemaNode.parent?.fragment.description !== description) &&\n description.length > 0 && }\n \n {hasVendorProperties && renderExtensionAddon ? (\n
{renderExtensionAddon({ schemaNode, nestingLevel, vendorExtensions })}
\n ) : null}\n \n \n {renderRowAddon ?
{renderRowAddon({ schemaNode, nestingLevel })}
: null}\n \n {isCollapsible && isExpanded ? (\n \n ) : null}\n \n );\n },\n);\n\nSchemaRow.displayName = 'SchemaRow';\n\nfunction shouldShowPropertyName(schemaNode: SchemaNode) {\n return (\n schemaNode.subpath.length === 2 &&\n (schemaNode.subpath[0] === 'properties' || schemaNode.subpath[0] === 'patternProperties')\n );\n}\n","import { isPlainObject } from '@stoplight/json';\nimport { isRegularNode, RegularNode, SchemaFragment } from '@stoplight/json-schema-tree';\nimport { Menu } from '@base-ui/react/menu';\nimport { CaretDown } from '@phosphor-icons/react';\nimport * as React from 'react';\n\nimport { COMBINER_NAME_MAP } from '../../consts';\nimport { useJSVOptionsContext } from '../../contexts';\nimport { isComplexArray, isDictionaryNode, visibleChildren } from '../../tree';\nimport { extractVendorExtensions } from '../../utils/extractVendorExtensions';\nimport { ChildStack, Description, Error, getValidationsFromSchema, Validations } from '../shared';\nimport { SchemaRow, SchemaRowProps } from './SchemaRow';\nimport { useChoices } from './useChoices';\n\nfunction isEmpty(obj: Record): boolean {\n return Object.keys(obj).length === 0;\n}\n\nfunction getStoplightId(fragment: SchemaFragment | boolean): string | undefined {\n if (typeof fragment === 'boolean') return undefined;\n const xStoplight = fragment['x-stoplight' as keyof typeof fragment];\n if (isPlainObject(xStoplight)) {\n const id = (xStoplight as Record).id;\n return typeof id === 'string' ? id : undefined;\n }\n return undefined;\n}\n\nexport const TopLevelSchemaRow: React.FC & { skipDescription?: boolean }> = ({\n schemaNode,\n skipDescription,\n}) => {\n const { renderExtensionAddon } = useJSVOptionsContext();\n\n const { selectedChoice, setSelectedChoice, choices } = useChoices(schemaNode);\n const childNodes = React.useMemo(() => visibleChildren(selectedChoice.type), [selectedChoice.type]);\n const nestingLevel = 0;\n\n const nodeId = getStoplightId(schemaNode.fragment);\n \n const [totalVendorExtensions, vendorExtensions] = React.useMemo(\n () => extractVendorExtensions(schemaNode.fragment),\n [schemaNode.fragment],\n );\n const hasVendorProperties = totalVendorExtensions > 0;\n\n // regular objects are flattened at the top level\n if (isRegularNode(schemaNode) && isPureObjectNode(schemaNode)) {\n return (\n <>\n {!skipDescription ? : null}\n {hasVendorProperties && renderExtensionAddon\n ? renderExtensionAddon({ schemaNode, nestingLevel, vendorExtensions })\n : null}\n \n \n \n );\n }\n\n if (isRegularNode(schemaNode) && choices.length > 1) {\n const combiner = isRegularNode(schemaNode) && schemaNode.combiners?.length ? schemaNode.combiners[0] : null;\n\n return (\n <>\n {schemaNode.annotations.description !== schemaNode.parent?.fragment.description && (\n \n )}\n
\n \n \n {selectedChoice.title}\n \n \n \n \n \n {choices.map((choice, index) => (\n setSelectedChoice(choice)}\n >\n {choice.title}\n \n ))}\n \n \n \n \n\n {combiner !== null ? (\n \n {`(${COMBINER_NAME_MAP[combiner]})`}\n \n ) : null}\n
\n {childNodes.length > 0 ? (\n \n ) : combiner ? (\n \n ) : null}\n \n );\n }\n\n if (isComplexArray(schemaNode) && isPureObjectNode(schemaNode.children[0])) {\n const validations = isRegularNode(schemaNode) ? getValidationsFromSchema(schemaNode) : {};\n return (\n <>\n \n\n
array of:
\n\n {!isEmpty(validations) && (\n
\n \n
\n )}\n\n {childNodes.length > 0 ? (\n \n ) : null}\n \n );\n }\n\n return ;\n};\n\nfunction isPureObjectNode(schemaNode: RegularNode) {\n return schemaNode.primaryType === 'object' && schemaNode.types?.length === 1 && !isDictionaryNode(schemaNode);\n}\n","import {\n isRegularNode,\n RootNode,\n SchemaTree as JsonSchemaTree,\n SchemaTreeRefDereferenceFn,\n} from '@stoplight/json-schema-tree';\nimport { clsx } from 'clsx';\nimport { Provider, useSetAtom } from 'jotai';\nimport * as React from 'react';\n\nimport { JSVOptions, JSVOptionsContextProvider } from '../contexts';\nimport { shouldNodeBeIncluded } from '../tree/utils';\nimport { JSONSchema } from '../types';\nimport { PathCrumbs } from './PathCrumbs';\nimport { TopLevelSchemaRow } from './SchemaRow';\nimport { hoveredNodeAtom } from './SchemaRow/state';\n\nexport type JsonSchemaProps = Partial & {\n schema: JSONSchema;\n emptyText?: string;\n className?: string;\n resolveRef?: SchemaTreeRefDereferenceFn;\n /** Controls the level of recursion of refs. Prevents overly complex trees and running out of stack depth. */\n maxRefDepth?: number;\n onTreePopulated?: (props: { rootNode: RootNode; nodeCount: number }) => void;\n maxHeight?: number;\n parentCrumbs?: string[];\n skipTopLevelDescription?: boolean;\n /** Theme mode - set to \"dark\" for dark mode styling */\n 'data-theme'?: 'dark' | 'light';\n};\n\nexport const JsonSchemaViewer: React.FC = ({\n viewMode = 'standalone',\n defaultExpandedDepth = 1,\n onGoToRef,\n renderRowAddon,\n renderExtensionAddon,\n hideExamples,\n renderRootTreeLines,\n disableCrumbs,\n nodeHasChanged,\n skipTopLevelDescription,\n ...rest\n}) => {\n const options = React.useMemo(\n () => ({\n defaultExpandedDepth,\n viewMode,\n onGoToRef,\n renderRowAddon,\n renderExtensionAddon,\n hideExamples,\n renderRootTreeLines,\n disableCrumbs,\n nodeHasChanged,\n }),\n [\n defaultExpandedDepth,\n viewMode,\n onGoToRef,\n renderRowAddon,\n renderExtensionAddon,\n hideExamples,\n renderRootTreeLines,\n disableCrumbs,\n nodeHasChanged,\n ],\n );\n\n return (\n \n \n \n \n \n );\n};\n\nconst JsonSchemaViewerInner: React.FC<\n Pick<\n JsonSchemaProps,\n | 'schema'\n | 'viewMode'\n | 'className'\n | 'resolveRef'\n | 'maxRefDepth'\n | 'emptyText'\n | 'onTreePopulated'\n | 'maxHeight'\n | 'parentCrumbs'\n | 'skipTopLevelDescription'\n | 'data-theme'\n >\n> = ({\n schema,\n viewMode,\n className,\n resolveRef,\n maxRefDepth,\n emptyText = 'No schema defined',\n onTreePopulated,\n maxHeight,\n parentCrumbs,\n skipTopLevelDescription,\n 'data-theme': dataTheme,\n}) => {\n const setHoveredNode = useSetAtom(hoveredNodeAtom);\n const onMouseLeave = React.useCallback(() => {\n setHoveredNode(null);\n }, [setHoveredNode]);\n\n const { jsonSchemaTreeRoot, nodeCount } = React.useMemo(() => {\n const jsonSchemaTree = new JsonSchemaTree(schema, {\n mergeAllOf: true,\n refResolver: resolveRef,\n maxRefDepth,\n });\n\n let nodeCount = 0;\n\n jsonSchemaTree.walker.hookInto('filter', node => {\n if (shouldNodeBeIncluded(node, viewMode)) {\n nodeCount++;\n return true;\n }\n return false;\n });\n jsonSchemaTree.populate();\n\n return {\n jsonSchemaTreeRoot: jsonSchemaTree.root,\n nodeCount,\n };\n }, [schema, resolveRef, maxRefDepth, viewMode]);\n\n React.useEffect(() => {\n onTreePopulated?.({\n rootNode: jsonSchemaTreeRoot,\n nodeCount: nodeCount,\n });\n }, [jsonSchemaTreeRoot, onTreePopulated, nodeCount]);\n\n const isEmpty = React.useMemo(\n () => jsonSchemaTreeRoot.children.every(node => !isRegularNode(node) || node.unknown),\n [jsonSchemaTreeRoot],\n );\n\n if (isEmpty) {\n return (\n
\n {emptyText}\n
\n );\n }\n\n return (\n \n \n
\n \n
\n \n );\n};\n\n// Error boundary wrapper\nexport class JsonSchemaViewerErrorBoundary extends React.Component<\n { children: React.ReactNode; fallback?: React.ReactNode },\n { hasError: boolean; error: Error | null }\n> {\n constructor(props: { children: React.ReactNode; fallback?: React.ReactNode }) {\n super(props);\n this.state = { hasError: false, error: null };\n }\n\n static getDerivedStateFromError(error: Error) {\n return { hasError: true, error };\n }\n\n render() {\n if (this.state.hasError) {\n if (this.props.fallback) {\n return this.props.fallback;\n }\n return (\n
\n Error\n {this.state.error !== null ? `: ${this.state.error.message}` : null}\n
\n );\n }\n\n return this.props.children;\n }\n}\n"]} +\ No newline at end of file ++{"version":3,"sources":["../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_freeGlobal.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_root.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_Symbol.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_getRawTag.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_objectToString.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseGetTag.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/isObjectLike.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/isSymbol.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_arrayMap.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/isArray.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseToString.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/isObject.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/identity.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/isFunction.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_coreJsData.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_isMasked.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_toSource.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseIsNative.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_getValue.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_getNative.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_WeakMap.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseCreate.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_apply.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/noop.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_copyArray.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_shortOut.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/constant.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_defineProperty.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseSetToString.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_setToString.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_arrayEach.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseFindIndex.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseIsNaN.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_strictIndexOf.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseIndexOf.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_arrayIncludes.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_isIndex.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseAssignValue.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/eq.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_assignValue.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_copyObject.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_overRest.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseRest.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/isLength.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/isArrayLike.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_isIterateeCall.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_createAssigner.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_isPrototype.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseTimes.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseIsArguments.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/isArguments.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/stubFalse.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/isBuffer.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseIsTypedArray.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseUnary.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_nodeUtil.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/isTypedArray.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_arrayLikeKeys.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_overArg.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_nativeKeys.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseKeys.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/keys.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_nativeKeysIn.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseKeysIn.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/keysIn.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_isKey.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_nativeCreate.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_hashClear.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_hashDelete.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_hashGet.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_hashHas.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_hashSet.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_Hash.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_listCacheClear.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_assocIndexOf.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_listCacheDelete.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_listCacheGet.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_listCacheHas.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_listCacheSet.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_ListCache.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_Map.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_mapCacheClear.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_isKeyable.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_getMapData.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_mapCacheDelete.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_mapCacheGet.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_mapCacheHas.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_mapCacheSet.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_MapCache.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/memoize.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_memoizeCapped.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_stringToPath.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/toString.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_castPath.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_toKey.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseGet.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/get.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_arrayPush.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_isFlattenable.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseFlatten.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/flatten.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_flatRest.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_getPrototype.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/isPlainObject.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_stackClear.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_stackDelete.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_stackGet.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_stackHas.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_stackSet.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_Stack.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_cloneBuffer.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_arrayFilter.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/stubArray.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_getSymbols.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseGetAllKeys.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_getAllKeys.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_DataView.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_Promise.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_Set.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_getTag.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_Uint8Array.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_cloneArrayBuffer.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_cloneTypedArray.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_initCloneObject.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/compact.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_setCacheAdd.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_setCacheHas.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_SetCache.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_arraySome.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_cacheHas.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_equalArrays.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_mapToArray.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_setToArray.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_equalByTag.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_equalObjects.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseIsEqualDeep.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseIsEqual.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseIsMatch.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_isStrictComparable.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_getMatchData.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_matchesStrictComparable.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseMatches.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseHasIn.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_hasPath.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/hasIn.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseMatchesProperty.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseProperty.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_basePropertyDeep.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/property.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseIteratee.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_createBaseFor.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseFor.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseForOwn.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_createBaseEach.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseEach.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/defaults.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_assignMergeValue.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/isArrayLikeObject.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_safeGet.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/toPlainObject.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseMergeDeep.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseMerge.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_customDefaultsMerge.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/mergeWith.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/defaultsDeep.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_arrayIncludesWith.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseDifference.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/last.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_castFunction.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/forEach.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseMap.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/flattenDeep.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseIntersection.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_castArrayLikeObject.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/intersection.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/intersectionWith.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/isBoolean.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/isEqual.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseSet.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_basePickBy.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseSortBy.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_compareAscending.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_compareMultiple.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseOrderBy.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_basePick.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/pick.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseIndexOfWith.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_basePullAll.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/pullAll.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/sortBy.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_createSet.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/_baseUniq.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/uniq.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/uniqWith.js","../node_modules/.pnpm/lodash-es@4.17.23/node_modules/lodash-es/without.js","../node_modules/.pnpm/safe-stable-stringify@1.1.1/node_modules/safe-stable-stringify/stable.js","../node_modules/.pnpm/safe-stable-stringify@1.1.1/node_modules/safe-stable-stringify/index.js","../node_modules/.pnpm/tslib@2.8.1/node_modules/tslib/tslib.es6.mjs","../node_modules/.pnpm/@stoplight+lifecycle@2.3.3/node_modules/@stoplight/src/activatable/activatable.ts","../node_modules/.pnpm/@stoplight+lifecycle@2.3.3/node_modules/@stoplight/src/activatable/index.ts","../node_modules/.pnpm/@stoplight+lifecycle@2.3.3/node_modules/@stoplight/src/disposable/AsyncDisposer.ts","../node_modules/.pnpm/@stoplight+lifecycle@2.3.3/node_modules/@stoplight/src/disposable/AsyncDisposableSet.ts","../node_modules/.pnpm/@stoplight+lifecycle@2.3.3/node_modules/@stoplight/src/disposable/Disposer.ts","../node_modules/.pnpm/@stoplight+lifecycle@2.3.3/node_modules/@stoplight/src/disposable/DisposableSet.ts","../node_modules/.pnpm/@stoplight+lifecycle@2.3.3/node_modules/@stoplight/src/disposable/createDisposable.ts","../node_modules/.pnpm/@stoplight+lifecycle@2.3.3/node_modules/@stoplight/src/disposable/DisposableCollection.ts","../node_modules/.pnpm/@stoplight+lifecycle@2.3.3/node_modules/@stoplight/src/disposable/index.ts","../node_modules/.pnpm/wolfy87-eventemitter@5.2.9/node_modules/wolfy87-eventemitter/EventEmitter.js","../node_modules/.pnpm/@stoplight+lifecycle@2.3.3/node_modules/@stoplight/src/emitter/emitter.ts","../node_modules/.pnpm/@stoplight+lifecycle@2.3.3/node_modules/@stoplight/src/emitter/index.ts","../node_modules/.pnpm/@stoplight+lifecycle@2.3.3/node_modules/@stoplight/src/index.ts","../node_modules/.pnpm/json-schema-compare@0.2.2/node_modules/json-schema-compare/src/index.js","../node_modules/.pnpm/validate.io-array@1.0.6/node_modules/validate.io-array/lib/index.js","../node_modules/.pnpm/validate.io-number@1.0.3/node_modules/validate.io-number/lib/index.js","../node_modules/.pnpm/validate.io-integer@1.0.5/node_modules/validate.io-integer/lib/index.js","../node_modules/.pnpm/validate.io-integer-array@1.0.0/node_modules/validate.io-integer-array/lib/index.js","../node_modules/.pnpm/validate.io-function@1.0.2/node_modules/validate.io-function/lib/index.js","../node_modules/.pnpm/compute-gcd@1.2.1/node_modules/compute-gcd/lib/index.js","../node_modules/.pnpm/compute-lcm@1.1.2/node_modules/compute-lcm/lib/index.js","../node_modules/.pnpm/@stoplight+json-schema-merge-allof@0.8.0/node_modules/@stoplight/json-schema-merge-allof/src/index.js","../node_modules/.pnpm/jsonc-parser@2.2.1/node_modules/jsonc-parser/lib/esm/impl/parser.js","../node_modules/.pnpm/@stoplight+json@3.21.7/node_modules/@stoplight/json/index.es.js","../node_modules/.pnpm/magic-error@0.0.1/node_modules/magic-error/index.mjs","../node_modules/.pnpm/@stoplight+json-schema-tree@4.0.0/node_modules/@stoplight/src/nodes/BaseNode.ts","../node_modules/.pnpm/@stoplight+json-schema-tree@4.0.0/node_modules/@stoplight/src/nodes/BooleanishNode.ts","../node_modules/.pnpm/@stoplight+json-schema-tree@4.0.0/node_modules/@stoplight/src/nodes/mirrored/MirroredReferenceNode.ts","../node_modules/.pnpm/@stoplight+json-schema-tree@4.0.0/node_modules/@stoplight/src/utils/guards.ts","../node_modules/.pnpm/@stoplight+json-schema-tree@4.0.0/node_modules/@stoplight/src/utils/pick.ts","../node_modules/.pnpm/@stoplight+json-schema-tree@4.0.0/node_modules/@stoplight/src/nodes/mirrored/MirroredRegularNode.ts","../node_modules/.pnpm/@stoplight+json-schema-tree@4.0.0/node_modules/@stoplight/src/accessors/unwrap.ts","../node_modules/.pnpm/@stoplight+json-schema-tree@4.0.0/node_modules/@stoplight/src/nodes/ReferenceNode.ts","../node_modules/.pnpm/@stoplight+json-schema-tree@4.0.0/node_modules/@stoplight/src/accessors/getAnnotations.ts","../node_modules/.pnpm/@stoplight+json-schema-tree@4.0.0/node_modules/@stoplight/src/nodes/types.ts","../node_modules/.pnpm/@stoplight+json-schema-tree@4.0.0/node_modules/@stoplight/src/accessors/getCombiners.ts","../node_modules/.pnpm/@stoplight+json-schema-tree@4.0.0/node_modules/@stoplight/src/accessors/getPrimaryType.ts","../node_modules/.pnpm/@stoplight+json-schema-tree@4.0.0/node_modules/@stoplight/src/accessors/getRequired.ts","../node_modules/.pnpm/@stoplight+json-schema-tree@4.0.0/node_modules/@stoplight/src/accessors/guards/isValidType.ts","../node_modules/.pnpm/@stoplight+json-schema-tree@4.0.0/node_modules/@stoplight/src/accessors/inferType.ts","../node_modules/.pnpm/@stoplight+json-schema-tree@4.0.0/node_modules/@stoplight/src/accessors/getTypes.ts","../node_modules/.pnpm/@stoplight+json-schema-tree@4.0.0/node_modules/@stoplight/src/accessors/getValidations.ts","../node_modules/.pnpm/@stoplight+json-schema-tree@4.0.0/node_modules/@stoplight/src/accessors/isDeprecated.ts","../node_modules/.pnpm/@stoplight+json-schema-tree@4.0.0/node_modules/@stoplight/src/nodes/RegularNode.ts","../node_modules/.pnpm/@stoplight+json-schema-tree@4.0.0/node_modules/@stoplight/src/nodes/RootNode.ts","../node_modules/.pnpm/@stoplight+json-schema-tree@4.0.0/node_modules/@stoplight/src/guards/nodes.ts","../node_modules/.pnpm/@stoplight+json-schema-tree@4.0.0/node_modules/@stoplight/src/errors.ts","../node_modules/.pnpm/@stoplight+json-schema-tree@4.0.0/node_modules/@stoplight/src/mergers/mergeAllOf.ts","../node_modules/.pnpm/@stoplight+json-schema-tree@4.0.0/node_modules/@stoplight/src/mergers/mergeOneOrAnyOf.ts","../node_modules/.pnpm/@stoplight+json-schema-tree@4.0.0/node_modules/@stoplight/src/walker/walker.ts","../node_modules/.pnpm/@stoplight+json-schema-tree@4.0.0/node_modules/@stoplight/src/tree/tree.ts","../src/contexts/jsvOptions.tsx","../src/guards/isNonNullable.ts","../src/tree/utils.ts","../src/components/SchemaRow/state.ts","../src/components/PathCrumbs/state.ts","../src/components/PathCrumbs/index.tsx","../src/consts.ts","../src/hash.ts","../src/utils/extractVendorExtensions.ts","../src/components/shared/Caret.tsx","../src/components/shared/ChildStack.tsx","../src/components/shared/Description.tsx","../src/components/shared/Divider.tsx","../src/utils/getInternalSchemaError.ts","../src/components/shared/Error.tsx","../src/components/shared/NodeAnnotation.tsx","../src/components/shared/Properties.tsx","../src/components/shared/Select.tsx","../src/utils/getApplicableFormats.ts","../src/utils/printName.ts","../src/components/shared/Types.tsx","../src/components/shared/Validations.tsx","../src/components/SchemaRow/useChoices.ts","../src/components/SchemaRow/SchemaRow.tsx","../src/components/SchemaRow/TopLevelSchemaRow.tsx","../src/components/JsonSchemaViewer.tsx"],"names":["Symbol","nativeObjectToString","objectProto","symToStringTag","funcProto","funcToString","hasOwnProperty","WeakMap","MAX_SAFE_INTEGER","Buffer","argsTag","funcTag","freeExports","freeModule","moduleExports","HASH_UNDEFINED","Map","INFINITY","objectTag","propertyIsEnumerable","Promise","Set","mapTag","setTag","weakMapTag","dataViewTag","Uint8Array","othValue","arrayBufferTag","boolTag","dateTag","numberTag","errorTag","regexpTag","stringTag","COMPARE_PARTIAL_FLAG","COMPARE_UNORDERED_FLAG","symbolTag","symbolProto","arrayTag","LARGE_ARRAY_SIZE","collection","splice","arrayProto","exports","module","last","tmp","keys","j","b","_","x","P","k","v","d","__assign","k2","o","EventEmitter","isEqual","sortBy","uniq","uniqWith","defaults","intersectionWith","isPlainObject","isBoolean","compare","key","a","isArray","require_lib","isFunction","require_src","compact","defaultsDeep","flatten","flattenDeep","intersection","pullAll","pick","forEach","without","schemas","inferType","ownKeys","merged","first","merger","ParseOptions","e","t","r","isObject","SchemaNodeKind","SchemaCombinerName","resolved","root","_a","React","isNonNullable","get","atom","hash","jsx","React3","clsx","React4","jsxs","useAtomValue","React5","Error","Fragment","BaseSelect","format","getTypes","React6","React7","React8","getStoplightId","React9","CaretDown","React10","useSetAtom","nodeCount","isEmpty"],"mappings":"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","file":"index.js","sourcesContent":["/** Detect free variable `global` from Node.js. */\nvar freeGlobal = typeof global == 'object' && global && global.Object === Object && global;\n\nexport default freeGlobal;\n","import freeGlobal from './_freeGlobal.js';\n\n/** Detect free variable `self`. */\nvar freeSelf = typeof self == 'object' && self && self.Object === Object && self;\n\n/** Used as a reference to the global object. */\nvar root = freeGlobal || freeSelf || Function('return this')();\n\nexport default root;\n","import root from './_root.js';\n\n/** Built-in value references. */\nvar Symbol = root.Symbol;\n\nexport default Symbol;\n","import Symbol from './_Symbol.js';\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * Used to resolve the\n * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)\n * of values.\n */\nvar nativeObjectToString = objectProto.toString;\n\n/** Built-in value references. */\nvar symToStringTag = Symbol ? Symbol.toStringTag : undefined;\n\n/**\n * A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values.\n *\n * @private\n * @param {*} value The value to query.\n * @returns {string} Returns the raw `toStringTag`.\n */\nfunction getRawTag(value) {\n var isOwn = hasOwnProperty.call(value, symToStringTag),\n tag = value[symToStringTag];\n\n try {\n value[symToStringTag] = undefined;\n var unmasked = true;\n } catch (e) {}\n\n var result = nativeObjectToString.call(value);\n if (unmasked) {\n if (isOwn) {\n value[symToStringTag] = tag;\n } else {\n delete value[symToStringTag];\n }\n }\n return result;\n}\n\nexport default getRawTag;\n","/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/**\n * Used to resolve the\n * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)\n * of values.\n */\nvar nativeObjectToString = objectProto.toString;\n\n/**\n * Converts `value` to a string using `Object.prototype.toString`.\n *\n * @private\n * @param {*} value The value to convert.\n * @returns {string} Returns the converted string.\n */\nfunction objectToString(value) {\n return nativeObjectToString.call(value);\n}\n\nexport default objectToString;\n","import Symbol from './_Symbol.js';\nimport getRawTag from './_getRawTag.js';\nimport objectToString from './_objectToString.js';\n\n/** `Object#toString` result references. */\nvar nullTag = '[object Null]',\n undefinedTag = '[object Undefined]';\n\n/** Built-in value references. */\nvar symToStringTag = Symbol ? Symbol.toStringTag : undefined;\n\n/**\n * The base implementation of `getTag` without fallbacks for buggy environments.\n *\n * @private\n * @param {*} value The value to query.\n * @returns {string} Returns the `toStringTag`.\n */\nfunction baseGetTag(value) {\n if (value == null) {\n return value === undefined ? undefinedTag : nullTag;\n }\n return (symToStringTag && symToStringTag in Object(value))\n ? getRawTag(value)\n : objectToString(value);\n}\n\nexport default baseGetTag;\n","/**\n * Checks if `value` is object-like. A value is object-like if it's not `null`\n * and has a `typeof` result of \"object\".\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is object-like, else `false`.\n * @example\n *\n * _.isObjectLike({});\n * // => true\n *\n * _.isObjectLike([1, 2, 3]);\n * // => true\n *\n * _.isObjectLike(_.noop);\n * // => false\n *\n * _.isObjectLike(null);\n * // => false\n */\nfunction isObjectLike(value) {\n return value != null && typeof value == 'object';\n}\n\nexport default isObjectLike;\n","import baseGetTag from './_baseGetTag.js';\nimport isObjectLike from './isObjectLike.js';\n\n/** `Object#toString` result references. */\nvar symbolTag = '[object Symbol]';\n\n/**\n * Checks if `value` is classified as a `Symbol` primitive or object.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a symbol, else `false`.\n * @example\n *\n * _.isSymbol(Symbol.iterator);\n * // => true\n *\n * _.isSymbol('abc');\n * // => false\n */\nfunction isSymbol(value) {\n return typeof value == 'symbol' ||\n (isObjectLike(value) && baseGetTag(value) == symbolTag);\n}\n\nexport default isSymbol;\n","/**\n * A specialized version of `_.map` for arrays without support for iteratee\n * shorthands.\n *\n * @private\n * @param {Array} [array] The array to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @returns {Array} Returns the new mapped array.\n */\nfunction arrayMap(array, iteratee) {\n var index = -1,\n length = array == null ? 0 : array.length,\n result = Array(length);\n\n while (++index < length) {\n result[index] = iteratee(array[index], index, array);\n }\n return result;\n}\n\nexport default arrayMap;\n","/**\n * Checks if `value` is classified as an `Array` object.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an array, else `false`.\n * @example\n *\n * _.isArray([1, 2, 3]);\n * // => true\n *\n * _.isArray(document.body.children);\n * // => false\n *\n * _.isArray('abc');\n * // => false\n *\n * _.isArray(_.noop);\n * // => false\n */\nvar isArray = Array.isArray;\n\nexport default isArray;\n","import Symbol from './_Symbol.js';\nimport arrayMap from './_arrayMap.js';\nimport isArray from './isArray.js';\nimport isSymbol from './isSymbol.js';\n\n/** Used as references for various `Number` constants. */\nvar INFINITY = 1 / 0;\n\n/** Used to convert symbols to primitives and strings. */\nvar symbolProto = Symbol ? Symbol.prototype : undefined,\n symbolToString = symbolProto ? symbolProto.toString : undefined;\n\n/**\n * The base implementation of `_.toString` which doesn't convert nullish\n * values to empty strings.\n *\n * @private\n * @param {*} value The value to process.\n * @returns {string} Returns the string.\n */\nfunction baseToString(value) {\n // Exit early for strings to avoid a performance hit in some environments.\n if (typeof value == 'string') {\n return value;\n }\n if (isArray(value)) {\n // Recursively convert values (susceptible to call stack limits).\n return arrayMap(value, baseToString) + '';\n }\n if (isSymbol(value)) {\n return symbolToString ? symbolToString.call(value) : '';\n }\n var result = (value + '');\n return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result;\n}\n\nexport default baseToString;\n","/**\n * Checks if `value` is the\n * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)\n * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an object, else `false`.\n * @example\n *\n * _.isObject({});\n * // => true\n *\n * _.isObject([1, 2, 3]);\n * // => true\n *\n * _.isObject(_.noop);\n * // => true\n *\n * _.isObject(null);\n * // => false\n */\nfunction isObject(value) {\n var type = typeof value;\n return value != null && (type == 'object' || type == 'function');\n}\n\nexport default isObject;\n","/**\n * This method returns the first argument it receives.\n *\n * @static\n * @since 0.1.0\n * @memberOf _\n * @category Util\n * @param {*} value Any value.\n * @returns {*} Returns `value`.\n * @example\n *\n * var object = { 'a': 1 };\n *\n * console.log(_.identity(object) === object);\n * // => true\n */\nfunction identity(value) {\n return value;\n}\n\nexport default identity;\n","import baseGetTag from './_baseGetTag.js';\nimport isObject from './isObject.js';\n\n/** `Object#toString` result references. */\nvar asyncTag = '[object AsyncFunction]',\n funcTag = '[object Function]',\n genTag = '[object GeneratorFunction]',\n proxyTag = '[object Proxy]';\n\n/**\n * Checks if `value` is classified as a `Function` object.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a function, else `false`.\n * @example\n *\n * _.isFunction(_);\n * // => true\n *\n * _.isFunction(/abc/);\n * // => false\n */\nfunction isFunction(value) {\n if (!isObject(value)) {\n return false;\n }\n // The use of `Object#toString` avoids issues with the `typeof` operator\n // in Safari 9 which returns 'object' for typed arrays and other constructors.\n var tag = baseGetTag(value);\n return tag == funcTag || tag == genTag || tag == asyncTag || tag == proxyTag;\n}\n\nexport default isFunction;\n","import root from './_root.js';\n\n/** Used to detect overreaching core-js shims. */\nvar coreJsData = root['__core-js_shared__'];\n\nexport default coreJsData;\n","import coreJsData from './_coreJsData.js';\n\n/** Used to detect methods masquerading as native. */\nvar maskSrcKey = (function() {\n var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || '');\n return uid ? ('Symbol(src)_1.' + uid) : '';\n}());\n\n/**\n * Checks if `func` has its source masked.\n *\n * @private\n * @param {Function} func The function to check.\n * @returns {boolean} Returns `true` if `func` is masked, else `false`.\n */\nfunction isMasked(func) {\n return !!maskSrcKey && (maskSrcKey in func);\n}\n\nexport default isMasked;\n","/** Used for built-in method references. */\nvar funcProto = Function.prototype;\n\n/** Used to resolve the decompiled source of functions. */\nvar funcToString = funcProto.toString;\n\n/**\n * Converts `func` to its source code.\n *\n * @private\n * @param {Function} func The function to convert.\n * @returns {string} Returns the source code.\n */\nfunction toSource(func) {\n if (func != null) {\n try {\n return funcToString.call(func);\n } catch (e) {}\n try {\n return (func + '');\n } catch (e) {}\n }\n return '';\n}\n\nexport default toSource;\n","import isFunction from './isFunction.js';\nimport isMasked from './_isMasked.js';\nimport isObject from './isObject.js';\nimport toSource from './_toSource.js';\n\n/**\n * Used to match `RegExp`\n * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns).\n */\nvar reRegExpChar = /[\\\\^$.*+?()[\\]{}|]/g;\n\n/** Used to detect host constructors (Safari). */\nvar reIsHostCtor = /^\\[object .+?Constructor\\]$/;\n\n/** Used for built-in method references. */\nvar funcProto = Function.prototype,\n objectProto = Object.prototype;\n\n/** Used to resolve the decompiled source of functions. */\nvar funcToString = funcProto.toString;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/** Used to detect if a method is native. */\nvar reIsNative = RegExp('^' +\n funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\\\$&')\n .replace(/hasOwnProperty|(function).*?(?=\\\\\\()| for .+?(?=\\\\\\])/g, '$1.*?') + '$'\n);\n\n/**\n * The base implementation of `_.isNative` without bad shim checks.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a native function,\n * else `false`.\n */\nfunction baseIsNative(value) {\n if (!isObject(value) || isMasked(value)) {\n return false;\n }\n var pattern = isFunction(value) ? reIsNative : reIsHostCtor;\n return pattern.test(toSource(value));\n}\n\nexport default baseIsNative;\n","/**\n * Gets the value at `key` of `object`.\n *\n * @private\n * @param {Object} [object] The object to query.\n * @param {string} key The key of the property to get.\n * @returns {*} Returns the property value.\n */\nfunction getValue(object, key) {\n return object == null ? undefined : object[key];\n}\n\nexport default getValue;\n","import baseIsNative from './_baseIsNative.js';\nimport getValue from './_getValue.js';\n\n/**\n * Gets the native function at `key` of `object`.\n *\n * @private\n * @param {Object} object The object to query.\n * @param {string} key The key of the method to get.\n * @returns {*} Returns the function if it's native, else `undefined`.\n */\nfunction getNative(object, key) {\n var value = getValue(object, key);\n return baseIsNative(value) ? value : undefined;\n}\n\nexport default getNative;\n","import getNative from './_getNative.js';\nimport root from './_root.js';\n\n/* Built-in method references that are verified to be native. */\nvar WeakMap = getNative(root, 'WeakMap');\n\nexport default WeakMap;\n","import isObject from './isObject.js';\n\n/** Built-in value references. */\nvar objectCreate = Object.create;\n\n/**\n * The base implementation of `_.create` without support for assigning\n * properties to the created object.\n *\n * @private\n * @param {Object} proto The object to inherit from.\n * @returns {Object} Returns the new object.\n */\nvar baseCreate = (function() {\n function object() {}\n return function(proto) {\n if (!isObject(proto)) {\n return {};\n }\n if (objectCreate) {\n return objectCreate(proto);\n }\n object.prototype = proto;\n var result = new object;\n object.prototype = undefined;\n return result;\n };\n}());\n\nexport default baseCreate;\n","/**\n * A faster alternative to `Function#apply`, this function invokes `func`\n * with the `this` binding of `thisArg` and the arguments of `args`.\n *\n * @private\n * @param {Function} func The function to invoke.\n * @param {*} thisArg The `this` binding of `func`.\n * @param {Array} args The arguments to invoke `func` with.\n * @returns {*} Returns the result of `func`.\n */\nfunction apply(func, thisArg, args) {\n switch (args.length) {\n case 0: return func.call(thisArg);\n case 1: return func.call(thisArg, args[0]);\n case 2: return func.call(thisArg, args[0], args[1]);\n case 3: return func.call(thisArg, args[0], args[1], args[2]);\n }\n return func.apply(thisArg, args);\n}\n\nexport default apply;\n","/**\n * This method returns `undefined`.\n *\n * @static\n * @memberOf _\n * @since 2.3.0\n * @category Util\n * @example\n *\n * _.times(2, _.noop);\n * // => [undefined, undefined]\n */\nfunction noop() {\n // No operation performed.\n}\n\nexport default noop;\n","/**\n * Copies the values of `source` to `array`.\n *\n * @private\n * @param {Array} source The array to copy values from.\n * @param {Array} [array=[]] The array to copy values to.\n * @returns {Array} Returns `array`.\n */\nfunction copyArray(source, array) {\n var index = -1,\n length = source.length;\n\n array || (array = Array(length));\n while (++index < length) {\n array[index] = source[index];\n }\n return array;\n}\n\nexport default copyArray;\n","/** Used to detect hot functions by number of calls within a span of milliseconds. */\nvar HOT_COUNT = 800,\n HOT_SPAN = 16;\n\n/* Built-in method references for those with the same name as other `lodash` methods. */\nvar nativeNow = Date.now;\n\n/**\n * Creates a function that'll short out and invoke `identity` instead\n * of `func` when it's called `HOT_COUNT` or more times in `HOT_SPAN`\n * milliseconds.\n *\n * @private\n * @param {Function} func The function to restrict.\n * @returns {Function} Returns the new shortable function.\n */\nfunction shortOut(func) {\n var count = 0,\n lastCalled = 0;\n\n return function() {\n var stamp = nativeNow(),\n remaining = HOT_SPAN - (stamp - lastCalled);\n\n lastCalled = stamp;\n if (remaining > 0) {\n if (++count >= HOT_COUNT) {\n return arguments[0];\n }\n } else {\n count = 0;\n }\n return func.apply(undefined, arguments);\n };\n}\n\nexport default shortOut;\n","/**\n * Creates a function that returns `value`.\n *\n * @static\n * @memberOf _\n * @since 2.4.0\n * @category Util\n * @param {*} value The value to return from the new function.\n * @returns {Function} Returns the new constant function.\n * @example\n *\n * var objects = _.times(2, _.constant({ 'a': 1 }));\n *\n * console.log(objects);\n * // => [{ 'a': 1 }, { 'a': 1 }]\n *\n * console.log(objects[0] === objects[1]);\n * // => true\n */\nfunction constant(value) {\n return function() {\n return value;\n };\n}\n\nexport default constant;\n","import getNative from './_getNative.js';\n\nvar defineProperty = (function() {\n try {\n var func = getNative(Object, 'defineProperty');\n func({}, '', {});\n return func;\n } catch (e) {}\n}());\n\nexport default defineProperty;\n","import constant from './constant.js';\nimport defineProperty from './_defineProperty.js';\nimport identity from './identity.js';\n\n/**\n * The base implementation of `setToString` without support for hot loop shorting.\n *\n * @private\n * @param {Function} func The function to modify.\n * @param {Function} string The `toString` result.\n * @returns {Function} Returns `func`.\n */\nvar baseSetToString = !defineProperty ? identity : function(func, string) {\n return defineProperty(func, 'toString', {\n 'configurable': true,\n 'enumerable': false,\n 'value': constant(string),\n 'writable': true\n });\n};\n\nexport default baseSetToString;\n","import baseSetToString from './_baseSetToString.js';\nimport shortOut from './_shortOut.js';\n\n/**\n * Sets the `toString` method of `func` to return `string`.\n *\n * @private\n * @param {Function} func The function to modify.\n * @param {Function} string The `toString` result.\n * @returns {Function} Returns `func`.\n */\nvar setToString = shortOut(baseSetToString);\n\nexport default setToString;\n","/**\n * A specialized version of `_.forEach` for arrays without support for\n * iteratee shorthands.\n *\n * @private\n * @param {Array} [array] The array to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @returns {Array} Returns `array`.\n */\nfunction arrayEach(array, iteratee) {\n var index = -1,\n length = array == null ? 0 : array.length;\n\n while (++index < length) {\n if (iteratee(array[index], index, array) === false) {\n break;\n }\n }\n return array;\n}\n\nexport default arrayEach;\n","/**\n * The base implementation of `_.findIndex` and `_.findLastIndex` without\n * support for iteratee shorthands.\n *\n * @private\n * @param {Array} array The array to inspect.\n * @param {Function} predicate The function invoked per iteration.\n * @param {number} fromIndex The index to search from.\n * @param {boolean} [fromRight] Specify iterating from right to left.\n * @returns {number} Returns the index of the matched value, else `-1`.\n */\nfunction baseFindIndex(array, predicate, fromIndex, fromRight) {\n var length = array.length,\n index = fromIndex + (fromRight ? 1 : -1);\n\n while ((fromRight ? index-- : ++index < length)) {\n if (predicate(array[index], index, array)) {\n return index;\n }\n }\n return -1;\n}\n\nexport default baseFindIndex;\n","/**\n * The base implementation of `_.isNaN` without support for number objects.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`.\n */\nfunction baseIsNaN(value) {\n return value !== value;\n}\n\nexport default baseIsNaN;\n","/**\n * A specialized version of `_.indexOf` which performs strict equality\n * comparisons of values, i.e. `===`.\n *\n * @private\n * @param {Array} array The array to inspect.\n * @param {*} value The value to search for.\n * @param {number} fromIndex The index to search from.\n * @returns {number} Returns the index of the matched value, else `-1`.\n */\nfunction strictIndexOf(array, value, fromIndex) {\n var index = fromIndex - 1,\n length = array.length;\n\n while (++index < length) {\n if (array[index] === value) {\n return index;\n }\n }\n return -1;\n}\n\nexport default strictIndexOf;\n","import baseFindIndex from './_baseFindIndex.js';\nimport baseIsNaN from './_baseIsNaN.js';\nimport strictIndexOf from './_strictIndexOf.js';\n\n/**\n * The base implementation of `_.indexOf` without `fromIndex` bounds checks.\n *\n * @private\n * @param {Array} array The array to inspect.\n * @param {*} value The value to search for.\n * @param {number} fromIndex The index to search from.\n * @returns {number} Returns the index of the matched value, else `-1`.\n */\nfunction baseIndexOf(array, value, fromIndex) {\n return value === value\n ? strictIndexOf(array, value, fromIndex)\n : baseFindIndex(array, baseIsNaN, fromIndex);\n}\n\nexport default baseIndexOf;\n","import baseIndexOf from './_baseIndexOf.js';\n\n/**\n * A specialized version of `_.includes` for arrays without support for\n * specifying an index to search from.\n *\n * @private\n * @param {Array} [array] The array to inspect.\n * @param {*} target The value to search for.\n * @returns {boolean} Returns `true` if `target` is found, else `false`.\n */\nfunction arrayIncludes(array, value) {\n var length = array == null ? 0 : array.length;\n return !!length && baseIndexOf(array, value, 0) > -1;\n}\n\nexport default arrayIncludes;\n","/** Used as references for various `Number` constants. */\nvar MAX_SAFE_INTEGER = 9007199254740991;\n\n/** Used to detect unsigned integer values. */\nvar reIsUint = /^(?:0|[1-9]\\d*)$/;\n\n/**\n * Checks if `value` is a valid array-like index.\n *\n * @private\n * @param {*} value The value to check.\n * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index.\n * @returns {boolean} Returns `true` if `value` is a valid index, else `false`.\n */\nfunction isIndex(value, length) {\n var type = typeof value;\n length = length == null ? MAX_SAFE_INTEGER : length;\n\n return !!length &&\n (type == 'number' ||\n (type != 'symbol' && reIsUint.test(value))) &&\n (value > -1 && value % 1 == 0 && value < length);\n}\n\nexport default isIndex;\n","import defineProperty from './_defineProperty.js';\n\n/**\n * The base implementation of `assignValue` and `assignMergeValue` without\n * value checks.\n *\n * @private\n * @param {Object} object The object to modify.\n * @param {string} key The key of the property to assign.\n * @param {*} value The value to assign.\n */\nfunction baseAssignValue(object, key, value) {\n if (key == '__proto__' && defineProperty) {\n defineProperty(object, key, {\n 'configurable': true,\n 'enumerable': true,\n 'value': value,\n 'writable': true\n });\n } else {\n object[key] = value;\n }\n}\n\nexport default baseAssignValue;\n","/**\n * Performs a\n * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)\n * comparison between two values to determine if they are equivalent.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to compare.\n * @param {*} other The other value to compare.\n * @returns {boolean} Returns `true` if the values are equivalent, else `false`.\n * @example\n *\n * var object = { 'a': 1 };\n * var other = { 'a': 1 };\n *\n * _.eq(object, object);\n * // => true\n *\n * _.eq(object, other);\n * // => false\n *\n * _.eq('a', 'a');\n * // => true\n *\n * _.eq('a', Object('a'));\n * // => false\n *\n * _.eq(NaN, NaN);\n * // => true\n */\nfunction eq(value, other) {\n return value === other || (value !== value && other !== other);\n}\n\nexport default eq;\n","import baseAssignValue from './_baseAssignValue.js';\nimport eq from './eq.js';\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * Assigns `value` to `key` of `object` if the existing value is not equivalent\n * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)\n * for equality comparisons.\n *\n * @private\n * @param {Object} object The object to modify.\n * @param {string} key The key of the property to assign.\n * @param {*} value The value to assign.\n */\nfunction assignValue(object, key, value) {\n var objValue = object[key];\n if (!(hasOwnProperty.call(object, key) && eq(objValue, value)) ||\n (value === undefined && !(key in object))) {\n baseAssignValue(object, key, value);\n }\n}\n\nexport default assignValue;\n","import assignValue from './_assignValue.js';\nimport baseAssignValue from './_baseAssignValue.js';\n\n/**\n * Copies properties of `source` to `object`.\n *\n * @private\n * @param {Object} source The object to copy properties from.\n * @param {Array} props The property identifiers to copy.\n * @param {Object} [object={}] The object to copy properties to.\n * @param {Function} [customizer] The function to customize copied values.\n * @returns {Object} Returns `object`.\n */\nfunction copyObject(source, props, object, customizer) {\n var isNew = !object;\n object || (object = {});\n\n var index = -1,\n length = props.length;\n\n while (++index < length) {\n var key = props[index];\n\n var newValue = customizer\n ? customizer(object[key], source[key], key, object, source)\n : undefined;\n\n if (newValue === undefined) {\n newValue = source[key];\n }\n if (isNew) {\n baseAssignValue(object, key, newValue);\n } else {\n assignValue(object, key, newValue);\n }\n }\n return object;\n}\n\nexport default copyObject;\n","import apply from './_apply.js';\n\n/* Built-in method references for those with the same name as other `lodash` methods. */\nvar nativeMax = Math.max;\n\n/**\n * A specialized version of `baseRest` which transforms the rest array.\n *\n * @private\n * @param {Function} func The function to apply a rest parameter to.\n * @param {number} [start=func.length-1] The start position of the rest parameter.\n * @param {Function} transform The rest array transform.\n * @returns {Function} Returns the new function.\n */\nfunction overRest(func, start, transform) {\n start = nativeMax(start === undefined ? (func.length - 1) : start, 0);\n return function() {\n var args = arguments,\n index = -1,\n length = nativeMax(args.length - start, 0),\n array = Array(length);\n\n while (++index < length) {\n array[index] = args[start + index];\n }\n index = -1;\n var otherArgs = Array(start + 1);\n while (++index < start) {\n otherArgs[index] = args[index];\n }\n otherArgs[start] = transform(array);\n return apply(func, this, otherArgs);\n };\n}\n\nexport default overRest;\n","import identity from './identity.js';\nimport overRest from './_overRest.js';\nimport setToString from './_setToString.js';\n\n/**\n * The base implementation of `_.rest` which doesn't validate or coerce arguments.\n *\n * @private\n * @param {Function} func The function to apply a rest parameter to.\n * @param {number} [start=func.length-1] The start position of the rest parameter.\n * @returns {Function} Returns the new function.\n */\nfunction baseRest(func, start) {\n return setToString(overRest(func, start, identity), func + '');\n}\n\nexport default baseRest;\n","/** Used as references for various `Number` constants. */\nvar MAX_SAFE_INTEGER = 9007199254740991;\n\n/**\n * Checks if `value` is a valid array-like length.\n *\n * **Note:** This method is loosely based on\n * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.\n * @example\n *\n * _.isLength(3);\n * // => true\n *\n * _.isLength(Number.MIN_VALUE);\n * // => false\n *\n * _.isLength(Infinity);\n * // => false\n *\n * _.isLength('3');\n * // => false\n */\nfunction isLength(value) {\n return typeof value == 'number' &&\n value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;\n}\n\nexport default isLength;\n","import isFunction from './isFunction.js';\nimport isLength from './isLength.js';\n\n/**\n * Checks if `value` is array-like. A value is considered array-like if it's\n * not a function and has a `value.length` that's an integer greater than or\n * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is array-like, else `false`.\n * @example\n *\n * _.isArrayLike([1, 2, 3]);\n * // => true\n *\n * _.isArrayLike(document.body.children);\n * // => true\n *\n * _.isArrayLike('abc');\n * // => true\n *\n * _.isArrayLike(_.noop);\n * // => false\n */\nfunction isArrayLike(value) {\n return value != null && isLength(value.length) && !isFunction(value);\n}\n\nexport default isArrayLike;\n","import eq from './eq.js';\nimport isArrayLike from './isArrayLike.js';\nimport isIndex from './_isIndex.js';\nimport isObject from './isObject.js';\n\n/**\n * Checks if the given arguments are from an iteratee call.\n *\n * @private\n * @param {*} value The potential iteratee value argument.\n * @param {*} index The potential iteratee index or key argument.\n * @param {*} object The potential iteratee object argument.\n * @returns {boolean} Returns `true` if the arguments are from an iteratee call,\n * else `false`.\n */\nfunction isIterateeCall(value, index, object) {\n if (!isObject(object)) {\n return false;\n }\n var type = typeof index;\n if (type == 'number'\n ? (isArrayLike(object) && isIndex(index, object.length))\n : (type == 'string' && index in object)\n ) {\n return eq(object[index], value);\n }\n return false;\n}\n\nexport default isIterateeCall;\n","import baseRest from './_baseRest.js';\nimport isIterateeCall from './_isIterateeCall.js';\n\n/**\n * Creates a function like `_.assign`.\n *\n * @private\n * @param {Function} assigner The function to assign values.\n * @returns {Function} Returns the new assigner function.\n */\nfunction createAssigner(assigner) {\n return baseRest(function(object, sources) {\n var index = -1,\n length = sources.length,\n customizer = length > 1 ? sources[length - 1] : undefined,\n guard = length > 2 ? sources[2] : undefined;\n\n customizer = (assigner.length > 3 && typeof customizer == 'function')\n ? (length--, customizer)\n : undefined;\n\n if (guard && isIterateeCall(sources[0], sources[1], guard)) {\n customizer = length < 3 ? undefined : customizer;\n length = 1;\n }\n object = Object(object);\n while (++index < length) {\n var source = sources[index];\n if (source) {\n assigner(object, source, index, customizer);\n }\n }\n return object;\n });\n}\n\nexport default createAssigner;\n","/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/**\n * Checks if `value` is likely a prototype object.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a prototype, else `false`.\n */\nfunction isPrototype(value) {\n var Ctor = value && value.constructor,\n proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto;\n\n return value === proto;\n}\n\nexport default isPrototype;\n","/**\n * The base implementation of `_.times` without support for iteratee shorthands\n * or max array length checks.\n *\n * @private\n * @param {number} n The number of times to invoke `iteratee`.\n * @param {Function} iteratee The function invoked per iteration.\n * @returns {Array} Returns the array of results.\n */\nfunction baseTimes(n, iteratee) {\n var index = -1,\n result = Array(n);\n\n while (++index < n) {\n result[index] = iteratee(index);\n }\n return result;\n}\n\nexport default baseTimes;\n","import baseGetTag from './_baseGetTag.js';\nimport isObjectLike from './isObjectLike.js';\n\n/** `Object#toString` result references. */\nvar argsTag = '[object Arguments]';\n\n/**\n * The base implementation of `_.isArguments`.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an `arguments` object,\n */\nfunction baseIsArguments(value) {\n return isObjectLike(value) && baseGetTag(value) == argsTag;\n}\n\nexport default baseIsArguments;\n","import baseIsArguments from './_baseIsArguments.js';\nimport isObjectLike from './isObjectLike.js';\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/** Built-in value references. */\nvar propertyIsEnumerable = objectProto.propertyIsEnumerable;\n\n/**\n * Checks if `value` is likely an `arguments` object.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an `arguments` object,\n * else `false`.\n * @example\n *\n * _.isArguments(function() { return arguments; }());\n * // => true\n *\n * _.isArguments([1, 2, 3]);\n * // => false\n */\nvar isArguments = baseIsArguments(function() { return arguments; }()) ? baseIsArguments : function(value) {\n return isObjectLike(value) && hasOwnProperty.call(value, 'callee') &&\n !propertyIsEnumerable.call(value, 'callee');\n};\n\nexport default isArguments;\n","/**\n * This method returns `false`.\n *\n * @static\n * @memberOf _\n * @since 4.13.0\n * @category Util\n * @returns {boolean} Returns `false`.\n * @example\n *\n * _.times(2, _.stubFalse);\n * // => [false, false]\n */\nfunction stubFalse() {\n return false;\n}\n\nexport default stubFalse;\n","import root from './_root.js';\nimport stubFalse from './stubFalse.js';\n\n/** Detect free variable `exports`. */\nvar freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports;\n\n/** Detect free variable `module`. */\nvar freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module;\n\n/** Detect the popular CommonJS extension `module.exports`. */\nvar moduleExports = freeModule && freeModule.exports === freeExports;\n\n/** Built-in value references. */\nvar Buffer = moduleExports ? root.Buffer : undefined;\n\n/* Built-in method references for those with the same name as other `lodash` methods. */\nvar nativeIsBuffer = Buffer ? Buffer.isBuffer : undefined;\n\n/**\n * Checks if `value` is a buffer.\n *\n * @static\n * @memberOf _\n * @since 4.3.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a buffer, else `false`.\n * @example\n *\n * _.isBuffer(new Buffer(2));\n * // => true\n *\n * _.isBuffer(new Uint8Array(2));\n * // => false\n */\nvar isBuffer = nativeIsBuffer || stubFalse;\n\nexport default isBuffer;\n","import baseGetTag from './_baseGetTag.js';\nimport isLength from './isLength.js';\nimport isObjectLike from './isObjectLike.js';\n\n/** `Object#toString` result references. */\nvar argsTag = '[object Arguments]',\n arrayTag = '[object Array]',\n boolTag = '[object Boolean]',\n dateTag = '[object Date]',\n errorTag = '[object Error]',\n funcTag = '[object Function]',\n mapTag = '[object Map]',\n numberTag = '[object Number]',\n objectTag = '[object Object]',\n regexpTag = '[object RegExp]',\n setTag = '[object Set]',\n stringTag = '[object String]',\n weakMapTag = '[object WeakMap]';\n\nvar arrayBufferTag = '[object ArrayBuffer]',\n dataViewTag = '[object DataView]',\n float32Tag = '[object Float32Array]',\n float64Tag = '[object Float64Array]',\n int8Tag = '[object Int8Array]',\n int16Tag = '[object Int16Array]',\n int32Tag = '[object Int32Array]',\n uint8Tag = '[object Uint8Array]',\n uint8ClampedTag = '[object Uint8ClampedArray]',\n uint16Tag = '[object Uint16Array]',\n uint32Tag = '[object Uint32Array]';\n\n/** Used to identify `toStringTag` values of typed arrays. */\nvar typedArrayTags = {};\ntypedArrayTags[float32Tag] = typedArrayTags[float64Tag] =\ntypedArrayTags[int8Tag] = typedArrayTags[int16Tag] =\ntypedArrayTags[int32Tag] = typedArrayTags[uint8Tag] =\ntypedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] =\ntypedArrayTags[uint32Tag] = true;\ntypedArrayTags[argsTag] = typedArrayTags[arrayTag] =\ntypedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] =\ntypedArrayTags[dataViewTag] = typedArrayTags[dateTag] =\ntypedArrayTags[errorTag] = typedArrayTags[funcTag] =\ntypedArrayTags[mapTag] = typedArrayTags[numberTag] =\ntypedArrayTags[objectTag] = typedArrayTags[regexpTag] =\ntypedArrayTags[setTag] = typedArrayTags[stringTag] =\ntypedArrayTags[weakMapTag] = false;\n\n/**\n * The base implementation of `_.isTypedArray` without Node.js optimizations.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a typed array, else `false`.\n */\nfunction baseIsTypedArray(value) {\n return isObjectLike(value) &&\n isLength(value.length) && !!typedArrayTags[baseGetTag(value)];\n}\n\nexport default baseIsTypedArray;\n","/**\n * The base implementation of `_.unary` without support for storing metadata.\n *\n * @private\n * @param {Function} func The function to cap arguments for.\n * @returns {Function} Returns the new capped function.\n */\nfunction baseUnary(func) {\n return function(value) {\n return func(value);\n };\n}\n\nexport default baseUnary;\n","import freeGlobal from './_freeGlobal.js';\n\n/** Detect free variable `exports`. */\nvar freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports;\n\n/** Detect free variable `module`. */\nvar freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module;\n\n/** Detect the popular CommonJS extension `module.exports`. */\nvar moduleExports = freeModule && freeModule.exports === freeExports;\n\n/** Detect free variable `process` from Node.js. */\nvar freeProcess = moduleExports && freeGlobal.process;\n\n/** Used to access faster Node.js helpers. */\nvar nodeUtil = (function() {\n try {\n // Use `util.types` for Node.js 10+.\n var types = freeModule && freeModule.require && freeModule.require('util').types;\n\n if (types) {\n return types;\n }\n\n // Legacy `process.binding('util')` for Node.js < 10.\n return freeProcess && freeProcess.binding && freeProcess.binding('util');\n } catch (e) {}\n}());\n\nexport default nodeUtil;\n","import baseIsTypedArray from './_baseIsTypedArray.js';\nimport baseUnary from './_baseUnary.js';\nimport nodeUtil from './_nodeUtil.js';\n\n/* Node.js helper references. */\nvar nodeIsTypedArray = nodeUtil && nodeUtil.isTypedArray;\n\n/**\n * Checks if `value` is classified as a typed array.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a typed array, else `false`.\n * @example\n *\n * _.isTypedArray(new Uint8Array);\n * // => true\n *\n * _.isTypedArray([]);\n * // => false\n */\nvar isTypedArray = nodeIsTypedArray ? baseUnary(nodeIsTypedArray) : baseIsTypedArray;\n\nexport default isTypedArray;\n","import baseTimes from './_baseTimes.js';\nimport isArguments from './isArguments.js';\nimport isArray from './isArray.js';\nimport isBuffer from './isBuffer.js';\nimport isIndex from './_isIndex.js';\nimport isTypedArray from './isTypedArray.js';\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * Creates an array of the enumerable property names of the array-like `value`.\n *\n * @private\n * @param {*} value The value to query.\n * @param {boolean} inherited Specify returning inherited property names.\n * @returns {Array} Returns the array of property names.\n */\nfunction arrayLikeKeys(value, inherited) {\n var isArr = isArray(value),\n isArg = !isArr && isArguments(value),\n isBuff = !isArr && !isArg && isBuffer(value),\n isType = !isArr && !isArg && !isBuff && isTypedArray(value),\n skipIndexes = isArr || isArg || isBuff || isType,\n result = skipIndexes ? baseTimes(value.length, String) : [],\n length = result.length;\n\n for (var key in value) {\n if ((inherited || hasOwnProperty.call(value, key)) &&\n !(skipIndexes && (\n // Safari 9 has enumerable `arguments.length` in strict mode.\n key == 'length' ||\n // Node.js 0.10 has enumerable non-index properties on buffers.\n (isBuff && (key == 'offset' || key == 'parent')) ||\n // PhantomJS 2 has enumerable non-index properties on typed arrays.\n (isType && (key == 'buffer' || key == 'byteLength' || key == 'byteOffset')) ||\n // Skip index properties.\n isIndex(key, length)\n ))) {\n result.push(key);\n }\n }\n return result;\n}\n\nexport default arrayLikeKeys;\n","/**\n * Creates a unary function that invokes `func` with its argument transformed.\n *\n * @private\n * @param {Function} func The function to wrap.\n * @param {Function} transform The argument transform.\n * @returns {Function} Returns the new function.\n */\nfunction overArg(func, transform) {\n return function(arg) {\n return func(transform(arg));\n };\n}\n\nexport default overArg;\n","import overArg from './_overArg.js';\n\n/* Built-in method references for those with the same name as other `lodash` methods. */\nvar nativeKeys = overArg(Object.keys, Object);\n\nexport default nativeKeys;\n","import isPrototype from './_isPrototype.js';\nimport nativeKeys from './_nativeKeys.js';\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * The base implementation of `_.keys` which doesn't treat sparse arrays as dense.\n *\n * @private\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of property names.\n */\nfunction baseKeys(object) {\n if (!isPrototype(object)) {\n return nativeKeys(object);\n }\n var result = [];\n for (var key in Object(object)) {\n if (hasOwnProperty.call(object, key) && key != 'constructor') {\n result.push(key);\n }\n }\n return result;\n}\n\nexport default baseKeys;\n","import arrayLikeKeys from './_arrayLikeKeys.js';\nimport baseKeys from './_baseKeys.js';\nimport isArrayLike from './isArrayLike.js';\n\n/**\n * Creates an array of the own enumerable property names of `object`.\n *\n * **Note:** Non-object values are coerced to objects. See the\n * [ES spec](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)\n * for more details.\n *\n * @static\n * @since 0.1.0\n * @memberOf _\n * @category Object\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of property names.\n * @example\n *\n * function Foo() {\n * this.a = 1;\n * this.b = 2;\n * }\n *\n * Foo.prototype.c = 3;\n *\n * _.keys(new Foo);\n * // => ['a', 'b'] (iteration order is not guaranteed)\n *\n * _.keys('hi');\n * // => ['0', '1']\n */\nfunction keys(object) {\n return isArrayLike(object) ? arrayLikeKeys(object) : baseKeys(object);\n}\n\nexport default keys;\n","/**\n * This function is like\n * [`Object.keys`](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)\n * except that it includes inherited enumerable properties.\n *\n * @private\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of property names.\n */\nfunction nativeKeysIn(object) {\n var result = [];\n if (object != null) {\n for (var key in Object(object)) {\n result.push(key);\n }\n }\n return result;\n}\n\nexport default nativeKeysIn;\n","import isObject from './isObject.js';\nimport isPrototype from './_isPrototype.js';\nimport nativeKeysIn from './_nativeKeysIn.js';\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * The base implementation of `_.keysIn` which doesn't treat sparse arrays as dense.\n *\n * @private\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of property names.\n */\nfunction baseKeysIn(object) {\n if (!isObject(object)) {\n return nativeKeysIn(object);\n }\n var isProto = isPrototype(object),\n result = [];\n\n for (var key in object) {\n if (!(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) {\n result.push(key);\n }\n }\n return result;\n}\n\nexport default baseKeysIn;\n","import arrayLikeKeys from './_arrayLikeKeys.js';\nimport baseKeysIn from './_baseKeysIn.js';\nimport isArrayLike from './isArrayLike.js';\n\n/**\n * Creates an array of the own and inherited enumerable property names of `object`.\n *\n * **Note:** Non-object values are coerced to objects.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Object\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of property names.\n * @example\n *\n * function Foo() {\n * this.a = 1;\n * this.b = 2;\n * }\n *\n * Foo.prototype.c = 3;\n *\n * _.keysIn(new Foo);\n * // => ['a', 'b', 'c'] (iteration order is not guaranteed)\n */\nfunction keysIn(object) {\n return isArrayLike(object) ? arrayLikeKeys(object, true) : baseKeysIn(object);\n}\n\nexport default keysIn;\n","import isArray from './isArray.js';\nimport isSymbol from './isSymbol.js';\n\n/** Used to match property names within property paths. */\nvar reIsDeepProp = /\\.|\\[(?:[^[\\]]*|([\"'])(?:(?!\\1)[^\\\\]|\\\\.)*?\\1)\\]/,\n reIsPlainProp = /^\\w*$/;\n\n/**\n * Checks if `value` is a property name and not a property path.\n *\n * @private\n * @param {*} value The value to check.\n * @param {Object} [object] The object to query keys on.\n * @returns {boolean} Returns `true` if `value` is a property name, else `false`.\n */\nfunction isKey(value, object) {\n if (isArray(value)) {\n return false;\n }\n var type = typeof value;\n if (type == 'number' || type == 'symbol' || type == 'boolean' ||\n value == null || isSymbol(value)) {\n return true;\n }\n return reIsPlainProp.test(value) || !reIsDeepProp.test(value) ||\n (object != null && value in Object(object));\n}\n\nexport default isKey;\n","import getNative from './_getNative.js';\n\n/* Built-in method references that are verified to be native. */\nvar nativeCreate = getNative(Object, 'create');\n\nexport default nativeCreate;\n","import nativeCreate from './_nativeCreate.js';\n\n/**\n * Removes all key-value entries from the hash.\n *\n * @private\n * @name clear\n * @memberOf Hash\n */\nfunction hashClear() {\n this.__data__ = nativeCreate ? nativeCreate(null) : {};\n this.size = 0;\n}\n\nexport default hashClear;\n","/**\n * Removes `key` and its value from the hash.\n *\n * @private\n * @name delete\n * @memberOf Hash\n * @param {Object} hash The hash to modify.\n * @param {string} key The key of the value to remove.\n * @returns {boolean} Returns `true` if the entry was removed, else `false`.\n */\nfunction hashDelete(key) {\n var result = this.has(key) && delete this.__data__[key];\n this.size -= result ? 1 : 0;\n return result;\n}\n\nexport default hashDelete;\n","import nativeCreate from './_nativeCreate.js';\n\n/** Used to stand-in for `undefined` hash values. */\nvar HASH_UNDEFINED = '__lodash_hash_undefined__';\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * Gets the hash value for `key`.\n *\n * @private\n * @name get\n * @memberOf Hash\n * @param {string} key The key of the value to get.\n * @returns {*} Returns the entry value.\n */\nfunction hashGet(key) {\n var data = this.__data__;\n if (nativeCreate) {\n var result = data[key];\n return result === HASH_UNDEFINED ? undefined : result;\n }\n return hasOwnProperty.call(data, key) ? data[key] : undefined;\n}\n\nexport default hashGet;\n","import nativeCreate from './_nativeCreate.js';\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * Checks if a hash value for `key` exists.\n *\n * @private\n * @name has\n * @memberOf Hash\n * @param {string} key The key of the entry to check.\n * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.\n */\nfunction hashHas(key) {\n var data = this.__data__;\n return nativeCreate ? (data[key] !== undefined) : hasOwnProperty.call(data, key);\n}\n\nexport default hashHas;\n","import nativeCreate from './_nativeCreate.js';\n\n/** Used to stand-in for `undefined` hash values. */\nvar HASH_UNDEFINED = '__lodash_hash_undefined__';\n\n/**\n * Sets the hash `key` to `value`.\n *\n * @private\n * @name set\n * @memberOf Hash\n * @param {string} key The key of the value to set.\n * @param {*} value The value to set.\n * @returns {Object} Returns the hash instance.\n */\nfunction hashSet(key, value) {\n var data = this.__data__;\n this.size += this.has(key) ? 0 : 1;\n data[key] = (nativeCreate && value === undefined) ? HASH_UNDEFINED : value;\n return this;\n}\n\nexport default hashSet;\n","import hashClear from './_hashClear.js';\nimport hashDelete from './_hashDelete.js';\nimport hashGet from './_hashGet.js';\nimport hashHas from './_hashHas.js';\nimport hashSet from './_hashSet.js';\n\n/**\n * Creates a hash object.\n *\n * @private\n * @constructor\n * @param {Array} [entries] The key-value pairs to cache.\n */\nfunction Hash(entries) {\n var index = -1,\n length = entries == null ? 0 : entries.length;\n\n this.clear();\n while (++index < length) {\n var entry = entries[index];\n this.set(entry[0], entry[1]);\n }\n}\n\n// Add methods to `Hash`.\nHash.prototype.clear = hashClear;\nHash.prototype['delete'] = hashDelete;\nHash.prototype.get = hashGet;\nHash.prototype.has = hashHas;\nHash.prototype.set = hashSet;\n\nexport default Hash;\n","/**\n * Removes all key-value entries from the list cache.\n *\n * @private\n * @name clear\n * @memberOf ListCache\n */\nfunction listCacheClear() {\n this.__data__ = [];\n this.size = 0;\n}\n\nexport default listCacheClear;\n","import eq from './eq.js';\n\n/**\n * Gets the index at which the `key` is found in `array` of key-value pairs.\n *\n * @private\n * @param {Array} array The array to inspect.\n * @param {*} key The key to search for.\n * @returns {number} Returns the index of the matched value, else `-1`.\n */\nfunction assocIndexOf(array, key) {\n var length = array.length;\n while (length--) {\n if (eq(array[length][0], key)) {\n return length;\n }\n }\n return -1;\n}\n\nexport default assocIndexOf;\n","import assocIndexOf from './_assocIndexOf.js';\n\n/** Used for built-in method references. */\nvar arrayProto = Array.prototype;\n\n/** Built-in value references. */\nvar splice = arrayProto.splice;\n\n/**\n * Removes `key` and its value from the list cache.\n *\n * @private\n * @name delete\n * @memberOf ListCache\n * @param {string} key The key of the value to remove.\n * @returns {boolean} Returns `true` if the entry was removed, else `false`.\n */\nfunction listCacheDelete(key) {\n var data = this.__data__,\n index = assocIndexOf(data, key);\n\n if (index < 0) {\n return false;\n }\n var lastIndex = data.length - 1;\n if (index == lastIndex) {\n data.pop();\n } else {\n splice.call(data, index, 1);\n }\n --this.size;\n return true;\n}\n\nexport default listCacheDelete;\n","import assocIndexOf from './_assocIndexOf.js';\n\n/**\n * Gets the list cache value for `key`.\n *\n * @private\n * @name get\n * @memberOf ListCache\n * @param {string} key The key of the value to get.\n * @returns {*} Returns the entry value.\n */\nfunction listCacheGet(key) {\n var data = this.__data__,\n index = assocIndexOf(data, key);\n\n return index < 0 ? undefined : data[index][1];\n}\n\nexport default listCacheGet;\n","import assocIndexOf from './_assocIndexOf.js';\n\n/**\n * Checks if a list cache value for `key` exists.\n *\n * @private\n * @name has\n * @memberOf ListCache\n * @param {string} key The key of the entry to check.\n * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.\n */\nfunction listCacheHas(key) {\n return assocIndexOf(this.__data__, key) > -1;\n}\n\nexport default listCacheHas;\n","import assocIndexOf from './_assocIndexOf.js';\n\n/**\n * Sets the list cache `key` to `value`.\n *\n * @private\n * @name set\n * @memberOf ListCache\n * @param {string} key The key of the value to set.\n * @param {*} value The value to set.\n * @returns {Object} Returns the list cache instance.\n */\nfunction listCacheSet(key, value) {\n var data = this.__data__,\n index = assocIndexOf(data, key);\n\n if (index < 0) {\n ++this.size;\n data.push([key, value]);\n } else {\n data[index][1] = value;\n }\n return this;\n}\n\nexport default listCacheSet;\n","import listCacheClear from './_listCacheClear.js';\nimport listCacheDelete from './_listCacheDelete.js';\nimport listCacheGet from './_listCacheGet.js';\nimport listCacheHas from './_listCacheHas.js';\nimport listCacheSet from './_listCacheSet.js';\n\n/**\n * Creates an list cache object.\n *\n * @private\n * @constructor\n * @param {Array} [entries] The key-value pairs to cache.\n */\nfunction ListCache(entries) {\n var index = -1,\n length = entries == null ? 0 : entries.length;\n\n this.clear();\n while (++index < length) {\n var entry = entries[index];\n this.set(entry[0], entry[1]);\n }\n}\n\n// Add methods to `ListCache`.\nListCache.prototype.clear = listCacheClear;\nListCache.prototype['delete'] = listCacheDelete;\nListCache.prototype.get = listCacheGet;\nListCache.prototype.has = listCacheHas;\nListCache.prototype.set = listCacheSet;\n\nexport default ListCache;\n","import getNative from './_getNative.js';\nimport root from './_root.js';\n\n/* Built-in method references that are verified to be native. */\nvar Map = getNative(root, 'Map');\n\nexport default Map;\n","import Hash from './_Hash.js';\nimport ListCache from './_ListCache.js';\nimport Map from './_Map.js';\n\n/**\n * Removes all key-value entries from the map.\n *\n * @private\n * @name clear\n * @memberOf MapCache\n */\nfunction mapCacheClear() {\n this.size = 0;\n this.__data__ = {\n 'hash': new Hash,\n 'map': new (Map || ListCache),\n 'string': new Hash\n };\n}\n\nexport default mapCacheClear;\n","/**\n * Checks if `value` is suitable for use as unique object key.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is suitable, else `false`.\n */\nfunction isKeyable(value) {\n var type = typeof value;\n return (type == 'string' || type == 'number' || type == 'symbol' || type == 'boolean')\n ? (value !== '__proto__')\n : (value === null);\n}\n\nexport default isKeyable;\n","import isKeyable from './_isKeyable.js';\n\n/**\n * Gets the data for `map`.\n *\n * @private\n * @param {Object} map The map to query.\n * @param {string} key The reference key.\n * @returns {*} Returns the map data.\n */\nfunction getMapData(map, key) {\n var data = map.__data__;\n return isKeyable(key)\n ? data[typeof key == 'string' ? 'string' : 'hash']\n : data.map;\n}\n\nexport default getMapData;\n","import getMapData from './_getMapData.js';\n\n/**\n * Removes `key` and its value from the map.\n *\n * @private\n * @name delete\n * @memberOf MapCache\n * @param {string} key The key of the value to remove.\n * @returns {boolean} Returns `true` if the entry was removed, else `false`.\n */\nfunction mapCacheDelete(key) {\n var result = getMapData(this, key)['delete'](key);\n this.size -= result ? 1 : 0;\n return result;\n}\n\nexport default mapCacheDelete;\n","import getMapData from './_getMapData.js';\n\n/**\n * Gets the map value for `key`.\n *\n * @private\n * @name get\n * @memberOf MapCache\n * @param {string} key The key of the value to get.\n * @returns {*} Returns the entry value.\n */\nfunction mapCacheGet(key) {\n return getMapData(this, key).get(key);\n}\n\nexport default mapCacheGet;\n","import getMapData from './_getMapData.js';\n\n/**\n * Checks if a map value for `key` exists.\n *\n * @private\n * @name has\n * @memberOf MapCache\n * @param {string} key The key of the entry to check.\n * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.\n */\nfunction mapCacheHas(key) {\n return getMapData(this, key).has(key);\n}\n\nexport default mapCacheHas;\n","import getMapData from './_getMapData.js';\n\n/**\n * Sets the map `key` to `value`.\n *\n * @private\n * @name set\n * @memberOf MapCache\n * @param {string} key The key of the value to set.\n * @param {*} value The value to set.\n * @returns {Object} Returns the map cache instance.\n */\nfunction mapCacheSet(key, value) {\n var data = getMapData(this, key),\n size = data.size;\n\n data.set(key, value);\n this.size += data.size == size ? 0 : 1;\n return this;\n}\n\nexport default mapCacheSet;\n","import mapCacheClear from './_mapCacheClear.js';\nimport mapCacheDelete from './_mapCacheDelete.js';\nimport mapCacheGet from './_mapCacheGet.js';\nimport mapCacheHas from './_mapCacheHas.js';\nimport mapCacheSet from './_mapCacheSet.js';\n\n/**\n * Creates a map cache object to store key-value pairs.\n *\n * @private\n * @constructor\n * @param {Array} [entries] The key-value pairs to cache.\n */\nfunction MapCache(entries) {\n var index = -1,\n length = entries == null ? 0 : entries.length;\n\n this.clear();\n while (++index < length) {\n var entry = entries[index];\n this.set(entry[0], entry[1]);\n }\n}\n\n// Add methods to `MapCache`.\nMapCache.prototype.clear = mapCacheClear;\nMapCache.prototype['delete'] = mapCacheDelete;\nMapCache.prototype.get = mapCacheGet;\nMapCache.prototype.has = mapCacheHas;\nMapCache.prototype.set = mapCacheSet;\n\nexport default MapCache;\n","import MapCache from './_MapCache.js';\n\n/** Error message constants. */\nvar FUNC_ERROR_TEXT = 'Expected a function';\n\n/**\n * Creates a function that memoizes the result of `func`. If `resolver` is\n * provided, it determines the cache key for storing the result based on the\n * arguments provided to the memoized function. By default, the first argument\n * provided to the memoized function is used as the map cache key. The `func`\n * is invoked with the `this` binding of the memoized function.\n *\n * **Note:** The cache is exposed as the `cache` property on the memoized\n * function. Its creation may be customized by replacing the `_.memoize.Cache`\n * constructor with one whose instances implement the\n * [`Map`](http://ecma-international.org/ecma-262/7.0/#sec-properties-of-the-map-prototype-object)\n * method interface of `clear`, `delete`, `get`, `has`, and `set`.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Function\n * @param {Function} func The function to have its output memoized.\n * @param {Function} [resolver] The function to resolve the cache key.\n * @returns {Function} Returns the new memoized function.\n * @example\n *\n * var object = { 'a': 1, 'b': 2 };\n * var other = { 'c': 3, 'd': 4 };\n *\n * var values = _.memoize(_.values);\n * values(object);\n * // => [1, 2]\n *\n * values(other);\n * // => [3, 4]\n *\n * object.a = 2;\n * values(object);\n * // => [1, 2]\n *\n * // Modify the result cache.\n * values.cache.set(object, ['a', 'b']);\n * values(object);\n * // => ['a', 'b']\n *\n * // Replace `_.memoize.Cache`.\n * _.memoize.Cache = WeakMap;\n */\nfunction memoize(func, resolver) {\n if (typeof func != 'function' || (resolver != null && typeof resolver != 'function')) {\n throw new TypeError(FUNC_ERROR_TEXT);\n }\n var memoized = function() {\n var args = arguments,\n key = resolver ? resolver.apply(this, args) : args[0],\n cache = memoized.cache;\n\n if (cache.has(key)) {\n return cache.get(key);\n }\n var result = func.apply(this, args);\n memoized.cache = cache.set(key, result) || cache;\n return result;\n };\n memoized.cache = new (memoize.Cache || MapCache);\n return memoized;\n}\n\n// Expose `MapCache`.\nmemoize.Cache = MapCache;\n\nexport default memoize;\n","import memoize from './memoize.js';\n\n/** Used as the maximum memoize cache size. */\nvar MAX_MEMOIZE_SIZE = 500;\n\n/**\n * A specialized version of `_.memoize` which clears the memoized function's\n * cache when it exceeds `MAX_MEMOIZE_SIZE`.\n *\n * @private\n * @param {Function} func The function to have its output memoized.\n * @returns {Function} Returns the new memoized function.\n */\nfunction memoizeCapped(func) {\n var result = memoize(func, function(key) {\n if (cache.size === MAX_MEMOIZE_SIZE) {\n cache.clear();\n }\n return key;\n });\n\n var cache = result.cache;\n return result;\n}\n\nexport default memoizeCapped;\n","import memoizeCapped from './_memoizeCapped.js';\n\n/** Used to match property names within property paths. */\nvar rePropName = /[^.[\\]]+|\\[(?:(-?\\d+(?:\\.\\d+)?)|([\"'])((?:(?!\\2)[^\\\\]|\\\\.)*?)\\2)\\]|(?=(?:\\.|\\[\\])(?:\\.|\\[\\]|$))/g;\n\n/** Used to match backslashes in property paths. */\nvar reEscapeChar = /\\\\(\\\\)?/g;\n\n/**\n * Converts `string` to a property path array.\n *\n * @private\n * @param {string} string The string to convert.\n * @returns {Array} Returns the property path array.\n */\nvar stringToPath = memoizeCapped(function(string) {\n var result = [];\n if (string.charCodeAt(0) === 46 /* . */) {\n result.push('');\n }\n string.replace(rePropName, function(match, number, quote, subString) {\n result.push(quote ? subString.replace(reEscapeChar, '$1') : (number || match));\n });\n return result;\n});\n\nexport default stringToPath;\n","import baseToString from './_baseToString.js';\n\n/**\n * Converts `value` to a string. An empty string is returned for `null`\n * and `undefined` values. The sign of `-0` is preserved.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to convert.\n * @returns {string} Returns the converted string.\n * @example\n *\n * _.toString(null);\n * // => ''\n *\n * _.toString(-0);\n * // => '-0'\n *\n * _.toString([1, 2, 3]);\n * // => '1,2,3'\n */\nfunction toString(value) {\n return value == null ? '' : baseToString(value);\n}\n\nexport default toString;\n","import isArray from './isArray.js';\nimport isKey from './_isKey.js';\nimport stringToPath from './_stringToPath.js';\nimport toString from './toString.js';\n\n/**\n * Casts `value` to a path array if it's not one.\n *\n * @private\n * @param {*} value The value to inspect.\n * @param {Object} [object] The object to query keys on.\n * @returns {Array} Returns the cast property path array.\n */\nfunction castPath(value, object) {\n if (isArray(value)) {\n return value;\n }\n return isKey(value, object) ? [value] : stringToPath(toString(value));\n}\n\nexport default castPath;\n","import isSymbol from './isSymbol.js';\n\n/** Used as references for various `Number` constants. */\nvar INFINITY = 1 / 0;\n\n/**\n * Converts `value` to a string key if it's not a string or symbol.\n *\n * @private\n * @param {*} value The value to inspect.\n * @returns {string|symbol} Returns the key.\n */\nfunction toKey(value) {\n if (typeof value == 'string' || isSymbol(value)) {\n return value;\n }\n var result = (value + '');\n return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result;\n}\n\nexport default toKey;\n","import castPath from './_castPath.js';\nimport toKey from './_toKey.js';\n\n/**\n * The base implementation of `_.get` without support for default values.\n *\n * @private\n * @param {Object} object The object to query.\n * @param {Array|string} path The path of the property to get.\n * @returns {*} Returns the resolved value.\n */\nfunction baseGet(object, path) {\n path = castPath(path, object);\n\n var index = 0,\n length = path.length;\n\n while (object != null && index < length) {\n object = object[toKey(path[index++])];\n }\n return (index && index == length) ? object : undefined;\n}\n\nexport default baseGet;\n","import baseGet from './_baseGet.js';\n\n/**\n * Gets the value at `path` of `object`. If the resolved value is\n * `undefined`, the `defaultValue` is returned in its place.\n *\n * @static\n * @memberOf _\n * @since 3.7.0\n * @category Object\n * @param {Object} object The object to query.\n * @param {Array|string} path The path of the property to get.\n * @param {*} [defaultValue] The value returned for `undefined` resolved values.\n * @returns {*} Returns the resolved value.\n * @example\n *\n * var object = { 'a': [{ 'b': { 'c': 3 } }] };\n *\n * _.get(object, 'a[0].b.c');\n * // => 3\n *\n * _.get(object, ['a', '0', 'b', 'c']);\n * // => 3\n *\n * _.get(object, 'a.b.c', 'default');\n * // => 'default'\n */\nfunction get(object, path, defaultValue) {\n var result = object == null ? undefined : baseGet(object, path);\n return result === undefined ? defaultValue : result;\n}\n\nexport default get;\n","/**\n * Appends the elements of `values` to `array`.\n *\n * @private\n * @param {Array} array The array to modify.\n * @param {Array} values The values to append.\n * @returns {Array} Returns `array`.\n */\nfunction arrayPush(array, values) {\n var index = -1,\n length = values.length,\n offset = array.length;\n\n while (++index < length) {\n array[offset + index] = values[index];\n }\n return array;\n}\n\nexport default arrayPush;\n","import Symbol from './_Symbol.js';\nimport isArguments from './isArguments.js';\nimport isArray from './isArray.js';\n\n/** Built-in value references. */\nvar spreadableSymbol = Symbol ? Symbol.isConcatSpreadable : undefined;\n\n/**\n * Checks if `value` is a flattenable `arguments` object or array.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is flattenable, else `false`.\n */\nfunction isFlattenable(value) {\n return isArray(value) || isArguments(value) ||\n !!(spreadableSymbol && value && value[spreadableSymbol]);\n}\n\nexport default isFlattenable;\n","import arrayPush from './_arrayPush.js';\nimport isFlattenable from './_isFlattenable.js';\n\n/**\n * The base implementation of `_.flatten` with support for restricting flattening.\n *\n * @private\n * @param {Array} array The array to flatten.\n * @param {number} depth The maximum recursion depth.\n * @param {boolean} [predicate=isFlattenable] The function invoked per iteration.\n * @param {boolean} [isStrict] Restrict to values that pass `predicate` checks.\n * @param {Array} [result=[]] The initial result value.\n * @returns {Array} Returns the new flattened array.\n */\nfunction baseFlatten(array, depth, predicate, isStrict, result) {\n var index = -1,\n length = array.length;\n\n predicate || (predicate = isFlattenable);\n result || (result = []);\n\n while (++index < length) {\n var value = array[index];\n if (depth > 0 && predicate(value)) {\n if (depth > 1) {\n // Recursively flatten arrays (susceptible to call stack limits).\n baseFlatten(value, depth - 1, predicate, isStrict, result);\n } else {\n arrayPush(result, value);\n }\n } else if (!isStrict) {\n result[result.length] = value;\n }\n }\n return result;\n}\n\nexport default baseFlatten;\n","import baseFlatten from './_baseFlatten.js';\n\n/**\n * Flattens `array` a single level deep.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Array\n * @param {Array} array The array to flatten.\n * @returns {Array} Returns the new flattened array.\n * @example\n *\n * _.flatten([1, [2, [3, [4]], 5]]);\n * // => [1, 2, [3, [4]], 5]\n */\nfunction flatten(array) {\n var length = array == null ? 0 : array.length;\n return length ? baseFlatten(array, 1) : [];\n}\n\nexport default flatten;\n","import flatten from './flatten.js';\nimport overRest from './_overRest.js';\nimport setToString from './_setToString.js';\n\n/**\n * A specialized version of `baseRest` which flattens the rest array.\n *\n * @private\n * @param {Function} func The function to apply a rest parameter to.\n * @returns {Function} Returns the new function.\n */\nfunction flatRest(func) {\n return setToString(overRest(func, undefined, flatten), func + '');\n}\n\nexport default flatRest;\n","import overArg from './_overArg.js';\n\n/** Built-in value references. */\nvar getPrototype = overArg(Object.getPrototypeOf, Object);\n\nexport default getPrototype;\n","import baseGetTag from './_baseGetTag.js';\nimport getPrototype from './_getPrototype.js';\nimport isObjectLike from './isObjectLike.js';\n\n/** `Object#toString` result references. */\nvar objectTag = '[object Object]';\n\n/** Used for built-in method references. */\nvar funcProto = Function.prototype,\n objectProto = Object.prototype;\n\n/** Used to resolve the decompiled source of functions. */\nvar funcToString = funcProto.toString;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/** Used to infer the `Object` constructor. */\nvar objectCtorString = funcToString.call(Object);\n\n/**\n * Checks if `value` is a plain object, that is, an object created by the\n * `Object` constructor or one with a `[[Prototype]]` of `null`.\n *\n * @static\n * @memberOf _\n * @since 0.8.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a plain object, else `false`.\n * @example\n *\n * function Foo() {\n * this.a = 1;\n * }\n *\n * _.isPlainObject(new Foo);\n * // => false\n *\n * _.isPlainObject([1, 2, 3]);\n * // => false\n *\n * _.isPlainObject({ 'x': 0, 'y': 0 });\n * // => true\n *\n * _.isPlainObject(Object.create(null));\n * // => true\n */\nfunction isPlainObject(value) {\n if (!isObjectLike(value) || baseGetTag(value) != objectTag) {\n return false;\n }\n var proto = getPrototype(value);\n if (proto === null) {\n return true;\n }\n var Ctor = hasOwnProperty.call(proto, 'constructor') && proto.constructor;\n return typeof Ctor == 'function' && Ctor instanceof Ctor &&\n funcToString.call(Ctor) == objectCtorString;\n}\n\nexport default isPlainObject;\n","import ListCache from './_ListCache.js';\n\n/**\n * Removes all key-value entries from the stack.\n *\n * @private\n * @name clear\n * @memberOf Stack\n */\nfunction stackClear() {\n this.__data__ = new ListCache;\n this.size = 0;\n}\n\nexport default stackClear;\n","/**\n * Removes `key` and its value from the stack.\n *\n * @private\n * @name delete\n * @memberOf Stack\n * @param {string} key The key of the value to remove.\n * @returns {boolean} Returns `true` if the entry was removed, else `false`.\n */\nfunction stackDelete(key) {\n var data = this.__data__,\n result = data['delete'](key);\n\n this.size = data.size;\n return result;\n}\n\nexport default stackDelete;\n","/**\n * Gets the stack value for `key`.\n *\n * @private\n * @name get\n * @memberOf Stack\n * @param {string} key The key of the value to get.\n * @returns {*} Returns the entry value.\n */\nfunction stackGet(key) {\n return this.__data__.get(key);\n}\n\nexport default stackGet;\n","/**\n * Checks if a stack value for `key` exists.\n *\n * @private\n * @name has\n * @memberOf Stack\n * @param {string} key The key of the entry to check.\n * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.\n */\nfunction stackHas(key) {\n return this.__data__.has(key);\n}\n\nexport default stackHas;\n","import ListCache from './_ListCache.js';\nimport Map from './_Map.js';\nimport MapCache from './_MapCache.js';\n\n/** Used as the size to enable large array optimizations. */\nvar LARGE_ARRAY_SIZE = 200;\n\n/**\n * Sets the stack `key` to `value`.\n *\n * @private\n * @name set\n * @memberOf Stack\n * @param {string} key The key of the value to set.\n * @param {*} value The value to set.\n * @returns {Object} Returns the stack cache instance.\n */\nfunction stackSet(key, value) {\n var data = this.__data__;\n if (data instanceof ListCache) {\n var pairs = data.__data__;\n if (!Map || (pairs.length < LARGE_ARRAY_SIZE - 1)) {\n pairs.push([key, value]);\n this.size = ++data.size;\n return this;\n }\n data = this.__data__ = new MapCache(pairs);\n }\n data.set(key, value);\n this.size = data.size;\n return this;\n}\n\nexport default stackSet;\n","import ListCache from './_ListCache.js';\nimport stackClear from './_stackClear.js';\nimport stackDelete from './_stackDelete.js';\nimport stackGet from './_stackGet.js';\nimport stackHas from './_stackHas.js';\nimport stackSet from './_stackSet.js';\n\n/**\n * Creates a stack cache object to store key-value pairs.\n *\n * @private\n * @constructor\n * @param {Array} [entries] The key-value pairs to cache.\n */\nfunction Stack(entries) {\n var data = this.__data__ = new ListCache(entries);\n this.size = data.size;\n}\n\n// Add methods to `Stack`.\nStack.prototype.clear = stackClear;\nStack.prototype['delete'] = stackDelete;\nStack.prototype.get = stackGet;\nStack.prototype.has = stackHas;\nStack.prototype.set = stackSet;\n\nexport default Stack;\n","import root from './_root.js';\n\n/** Detect free variable `exports`. */\nvar freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports;\n\n/** Detect free variable `module`. */\nvar freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module;\n\n/** Detect the popular CommonJS extension `module.exports`. */\nvar moduleExports = freeModule && freeModule.exports === freeExports;\n\n/** Built-in value references. */\nvar Buffer = moduleExports ? root.Buffer : undefined,\n allocUnsafe = Buffer ? Buffer.allocUnsafe : undefined;\n\n/**\n * Creates a clone of `buffer`.\n *\n * @private\n * @param {Buffer} buffer The buffer to clone.\n * @param {boolean} [isDeep] Specify a deep clone.\n * @returns {Buffer} Returns the cloned buffer.\n */\nfunction cloneBuffer(buffer, isDeep) {\n if (isDeep) {\n return buffer.slice();\n }\n var length = buffer.length,\n result = allocUnsafe ? allocUnsafe(length) : new buffer.constructor(length);\n\n buffer.copy(result);\n return result;\n}\n\nexport default cloneBuffer;\n","/**\n * A specialized version of `_.filter` for arrays without support for\n * iteratee shorthands.\n *\n * @private\n * @param {Array} [array] The array to iterate over.\n * @param {Function} predicate The function invoked per iteration.\n * @returns {Array} Returns the new filtered array.\n */\nfunction arrayFilter(array, predicate) {\n var index = -1,\n length = array == null ? 0 : array.length,\n resIndex = 0,\n result = [];\n\n while (++index < length) {\n var value = array[index];\n if (predicate(value, index, array)) {\n result[resIndex++] = value;\n }\n }\n return result;\n}\n\nexport default arrayFilter;\n","/**\n * This method returns a new empty array.\n *\n * @static\n * @memberOf _\n * @since 4.13.0\n * @category Util\n * @returns {Array} Returns the new empty array.\n * @example\n *\n * var arrays = _.times(2, _.stubArray);\n *\n * console.log(arrays);\n * // => [[], []]\n *\n * console.log(arrays[0] === arrays[1]);\n * // => false\n */\nfunction stubArray() {\n return [];\n}\n\nexport default stubArray;\n","import arrayFilter from './_arrayFilter.js';\nimport stubArray from './stubArray.js';\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Built-in value references. */\nvar propertyIsEnumerable = objectProto.propertyIsEnumerable;\n\n/* Built-in method references for those with the same name as other `lodash` methods. */\nvar nativeGetSymbols = Object.getOwnPropertySymbols;\n\n/**\n * Creates an array of the own enumerable symbols of `object`.\n *\n * @private\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of symbols.\n */\nvar getSymbols = !nativeGetSymbols ? stubArray : function(object) {\n if (object == null) {\n return [];\n }\n object = Object(object);\n return arrayFilter(nativeGetSymbols(object), function(symbol) {\n return propertyIsEnumerable.call(object, symbol);\n });\n};\n\nexport default getSymbols;\n","import arrayPush from './_arrayPush.js';\nimport isArray from './isArray.js';\n\n/**\n * The base implementation of `getAllKeys` and `getAllKeysIn` which uses\n * `keysFunc` and `symbolsFunc` to get the enumerable property names and\n * symbols of `object`.\n *\n * @private\n * @param {Object} object The object to query.\n * @param {Function} keysFunc The function to get the keys of `object`.\n * @param {Function} symbolsFunc The function to get the symbols of `object`.\n * @returns {Array} Returns the array of property names and symbols.\n */\nfunction baseGetAllKeys(object, keysFunc, symbolsFunc) {\n var result = keysFunc(object);\n return isArray(object) ? result : arrayPush(result, symbolsFunc(object));\n}\n\nexport default baseGetAllKeys;\n","import baseGetAllKeys from './_baseGetAllKeys.js';\nimport getSymbols from './_getSymbols.js';\nimport keys from './keys.js';\n\n/**\n * Creates an array of own enumerable property names and symbols of `object`.\n *\n * @private\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of property names and symbols.\n */\nfunction getAllKeys(object) {\n return baseGetAllKeys(object, keys, getSymbols);\n}\n\nexport default getAllKeys;\n","import getNative from './_getNative.js';\nimport root from './_root.js';\n\n/* Built-in method references that are verified to be native. */\nvar DataView = getNative(root, 'DataView');\n\nexport default DataView;\n","import getNative from './_getNative.js';\nimport root from './_root.js';\n\n/* Built-in method references that are verified to be native. */\nvar Promise = getNative(root, 'Promise');\n\nexport default Promise;\n","import getNative from './_getNative.js';\nimport root from './_root.js';\n\n/* Built-in method references that are verified to be native. */\nvar Set = getNative(root, 'Set');\n\nexport default Set;\n","import DataView from './_DataView.js';\nimport Map from './_Map.js';\nimport Promise from './_Promise.js';\nimport Set from './_Set.js';\nimport WeakMap from './_WeakMap.js';\nimport baseGetTag from './_baseGetTag.js';\nimport toSource from './_toSource.js';\n\n/** `Object#toString` result references. */\nvar mapTag = '[object Map]',\n objectTag = '[object Object]',\n promiseTag = '[object Promise]',\n setTag = '[object Set]',\n weakMapTag = '[object WeakMap]';\n\nvar dataViewTag = '[object DataView]';\n\n/** Used to detect maps, sets, and weakmaps. */\nvar dataViewCtorString = toSource(DataView),\n mapCtorString = toSource(Map),\n promiseCtorString = toSource(Promise),\n setCtorString = toSource(Set),\n weakMapCtorString = toSource(WeakMap);\n\n/**\n * Gets the `toStringTag` of `value`.\n *\n * @private\n * @param {*} value The value to query.\n * @returns {string} Returns the `toStringTag`.\n */\nvar getTag = baseGetTag;\n\n// Fallback for data views, maps, sets, and weak maps in IE 11 and promises in Node.js < 6.\nif ((DataView && getTag(new DataView(new ArrayBuffer(1))) != dataViewTag) ||\n (Map && getTag(new Map) != mapTag) ||\n (Promise && getTag(Promise.resolve()) != promiseTag) ||\n (Set && getTag(new Set) != setTag) ||\n (WeakMap && getTag(new WeakMap) != weakMapTag)) {\n getTag = function(value) {\n var result = baseGetTag(value),\n Ctor = result == objectTag ? value.constructor : undefined,\n ctorString = Ctor ? toSource(Ctor) : '';\n\n if (ctorString) {\n switch (ctorString) {\n case dataViewCtorString: return dataViewTag;\n case mapCtorString: return mapTag;\n case promiseCtorString: return promiseTag;\n case setCtorString: return setTag;\n case weakMapCtorString: return weakMapTag;\n }\n }\n return result;\n };\n}\n\nexport default getTag;\n","import root from './_root.js';\n\n/** Built-in value references. */\nvar Uint8Array = root.Uint8Array;\n\nexport default Uint8Array;\n","import Uint8Array from './_Uint8Array.js';\n\n/**\n * Creates a clone of `arrayBuffer`.\n *\n * @private\n * @param {ArrayBuffer} arrayBuffer The array buffer to clone.\n * @returns {ArrayBuffer} Returns the cloned array buffer.\n */\nfunction cloneArrayBuffer(arrayBuffer) {\n var result = new arrayBuffer.constructor(arrayBuffer.byteLength);\n new Uint8Array(result).set(new Uint8Array(arrayBuffer));\n return result;\n}\n\nexport default cloneArrayBuffer;\n","import cloneArrayBuffer from './_cloneArrayBuffer.js';\n\n/**\n * Creates a clone of `typedArray`.\n *\n * @private\n * @param {Object} typedArray The typed array to clone.\n * @param {boolean} [isDeep] Specify a deep clone.\n * @returns {Object} Returns the cloned typed array.\n */\nfunction cloneTypedArray(typedArray, isDeep) {\n var buffer = isDeep ? cloneArrayBuffer(typedArray.buffer) : typedArray.buffer;\n return new typedArray.constructor(buffer, typedArray.byteOffset, typedArray.length);\n}\n\nexport default cloneTypedArray;\n","import baseCreate from './_baseCreate.js';\nimport getPrototype from './_getPrototype.js';\nimport isPrototype from './_isPrototype.js';\n\n/**\n * Initializes an object clone.\n *\n * @private\n * @param {Object} object The object to clone.\n * @returns {Object} Returns the initialized clone.\n */\nfunction initCloneObject(object) {\n return (typeof object.constructor == 'function' && !isPrototype(object))\n ? baseCreate(getPrototype(object))\n : {};\n}\n\nexport default initCloneObject;\n","/**\n * Creates an array with all falsey values removed. The values `false`, `null`,\n * `0`, `\"\"`, `undefined`, and `NaN` are falsey.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Array\n * @param {Array} array The array to compact.\n * @returns {Array} Returns the new array of filtered values.\n * @example\n *\n * _.compact([0, 1, false, 2, '', 3]);\n * // => [1, 2, 3]\n */\nfunction compact(array) {\n var index = -1,\n length = array == null ? 0 : array.length,\n resIndex = 0,\n result = [];\n\n while (++index < length) {\n var value = array[index];\n if (value) {\n result[resIndex++] = value;\n }\n }\n return result;\n}\n\nexport default compact;\n","/** Used to stand-in for `undefined` hash values. */\nvar HASH_UNDEFINED = '__lodash_hash_undefined__';\n\n/**\n * Adds `value` to the array cache.\n *\n * @private\n * @name add\n * @memberOf SetCache\n * @alias push\n * @param {*} value The value to cache.\n * @returns {Object} Returns the cache instance.\n */\nfunction setCacheAdd(value) {\n this.__data__.set(value, HASH_UNDEFINED);\n return this;\n}\n\nexport default setCacheAdd;\n","/**\n * Checks if `value` is in the array cache.\n *\n * @private\n * @name has\n * @memberOf SetCache\n * @param {*} value The value to search for.\n * @returns {number} Returns `true` if `value` is found, else `false`.\n */\nfunction setCacheHas(value) {\n return this.__data__.has(value);\n}\n\nexport default setCacheHas;\n","import MapCache from './_MapCache.js';\nimport setCacheAdd from './_setCacheAdd.js';\nimport setCacheHas from './_setCacheHas.js';\n\n/**\n *\n * Creates an array cache object to store unique values.\n *\n * @private\n * @constructor\n * @param {Array} [values] The values to cache.\n */\nfunction SetCache(values) {\n var index = -1,\n length = values == null ? 0 : values.length;\n\n this.__data__ = new MapCache;\n while (++index < length) {\n this.add(values[index]);\n }\n}\n\n// Add methods to `SetCache`.\nSetCache.prototype.add = SetCache.prototype.push = setCacheAdd;\nSetCache.prototype.has = setCacheHas;\n\nexport default SetCache;\n","/**\n * A specialized version of `_.some` for arrays without support for iteratee\n * shorthands.\n *\n * @private\n * @param {Array} [array] The array to iterate over.\n * @param {Function} predicate The function invoked per iteration.\n * @returns {boolean} Returns `true` if any element passes the predicate check,\n * else `false`.\n */\nfunction arraySome(array, predicate) {\n var index = -1,\n length = array == null ? 0 : array.length;\n\n while (++index < length) {\n if (predicate(array[index], index, array)) {\n return true;\n }\n }\n return false;\n}\n\nexport default arraySome;\n","/**\n * Checks if a `cache` value for `key` exists.\n *\n * @private\n * @param {Object} cache The cache to query.\n * @param {string} key The key of the entry to check.\n * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.\n */\nfunction cacheHas(cache, key) {\n return cache.has(key);\n}\n\nexport default cacheHas;\n","import SetCache from './_SetCache.js';\nimport arraySome from './_arraySome.js';\nimport cacheHas from './_cacheHas.js';\n\n/** Used to compose bitmasks for value comparisons. */\nvar COMPARE_PARTIAL_FLAG = 1,\n COMPARE_UNORDERED_FLAG = 2;\n\n/**\n * A specialized version of `baseIsEqualDeep` for arrays with support for\n * partial deep comparisons.\n *\n * @private\n * @param {Array} array The array to compare.\n * @param {Array} other The other array to compare.\n * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.\n * @param {Function} customizer The function to customize comparisons.\n * @param {Function} equalFunc The function to determine equivalents of values.\n * @param {Object} stack Tracks traversed `array` and `other` objects.\n * @returns {boolean} Returns `true` if the arrays are equivalent, else `false`.\n */\nfunction equalArrays(array, other, bitmask, customizer, equalFunc, stack) {\n var isPartial = bitmask & COMPARE_PARTIAL_FLAG,\n arrLength = array.length,\n othLength = other.length;\n\n if (arrLength != othLength && !(isPartial && othLength > arrLength)) {\n return false;\n }\n // Check that cyclic values are equal.\n var arrStacked = stack.get(array);\n var othStacked = stack.get(other);\n if (arrStacked && othStacked) {\n return arrStacked == other && othStacked == array;\n }\n var index = -1,\n result = true,\n seen = (bitmask & COMPARE_UNORDERED_FLAG) ? new SetCache : undefined;\n\n stack.set(array, other);\n stack.set(other, array);\n\n // Ignore non-index properties.\n while (++index < arrLength) {\n var arrValue = array[index],\n othValue = other[index];\n\n if (customizer) {\n var compared = isPartial\n ? customizer(othValue, arrValue, index, other, array, stack)\n : customizer(arrValue, othValue, index, array, other, stack);\n }\n if (compared !== undefined) {\n if (compared) {\n continue;\n }\n result = false;\n break;\n }\n // Recursively compare arrays (susceptible to call stack limits).\n if (seen) {\n if (!arraySome(other, function(othValue, othIndex) {\n if (!cacheHas(seen, othIndex) &&\n (arrValue === othValue || equalFunc(arrValue, othValue, bitmask, customizer, stack))) {\n return seen.push(othIndex);\n }\n })) {\n result = false;\n break;\n }\n } else if (!(\n arrValue === othValue ||\n equalFunc(arrValue, othValue, bitmask, customizer, stack)\n )) {\n result = false;\n break;\n }\n }\n stack['delete'](array);\n stack['delete'](other);\n return result;\n}\n\nexport default equalArrays;\n","/**\n * Converts `map` to its key-value pairs.\n *\n * @private\n * @param {Object} map The map to convert.\n * @returns {Array} Returns the key-value pairs.\n */\nfunction mapToArray(map) {\n var index = -1,\n result = Array(map.size);\n\n map.forEach(function(value, key) {\n result[++index] = [key, value];\n });\n return result;\n}\n\nexport default mapToArray;\n","/**\n * Converts `set` to an array of its values.\n *\n * @private\n * @param {Object} set The set to convert.\n * @returns {Array} Returns the values.\n */\nfunction setToArray(set) {\n var index = -1,\n result = Array(set.size);\n\n set.forEach(function(value) {\n result[++index] = value;\n });\n return result;\n}\n\nexport default setToArray;\n","import Symbol from './_Symbol.js';\nimport Uint8Array from './_Uint8Array.js';\nimport eq from './eq.js';\nimport equalArrays from './_equalArrays.js';\nimport mapToArray from './_mapToArray.js';\nimport setToArray from './_setToArray.js';\n\n/** Used to compose bitmasks for value comparisons. */\nvar COMPARE_PARTIAL_FLAG = 1,\n COMPARE_UNORDERED_FLAG = 2;\n\n/** `Object#toString` result references. */\nvar boolTag = '[object Boolean]',\n dateTag = '[object Date]',\n errorTag = '[object Error]',\n mapTag = '[object Map]',\n numberTag = '[object Number]',\n regexpTag = '[object RegExp]',\n setTag = '[object Set]',\n stringTag = '[object String]',\n symbolTag = '[object Symbol]';\n\nvar arrayBufferTag = '[object ArrayBuffer]',\n dataViewTag = '[object DataView]';\n\n/** Used to convert symbols to primitives and strings. */\nvar symbolProto = Symbol ? Symbol.prototype : undefined,\n symbolValueOf = symbolProto ? symbolProto.valueOf : undefined;\n\n/**\n * A specialized version of `baseIsEqualDeep` for comparing objects of\n * the same `toStringTag`.\n *\n * **Note:** This function only supports comparing values with tags of\n * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`.\n *\n * @private\n * @param {Object} object The object to compare.\n * @param {Object} other The other object to compare.\n * @param {string} tag The `toStringTag` of the objects to compare.\n * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.\n * @param {Function} customizer The function to customize comparisons.\n * @param {Function} equalFunc The function to determine equivalents of values.\n * @param {Object} stack Tracks traversed `object` and `other` objects.\n * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.\n */\nfunction equalByTag(object, other, tag, bitmask, customizer, equalFunc, stack) {\n switch (tag) {\n case dataViewTag:\n if ((object.byteLength != other.byteLength) ||\n (object.byteOffset != other.byteOffset)) {\n return false;\n }\n object = object.buffer;\n other = other.buffer;\n\n case arrayBufferTag:\n if ((object.byteLength != other.byteLength) ||\n !equalFunc(new Uint8Array(object), new Uint8Array(other))) {\n return false;\n }\n return true;\n\n case boolTag:\n case dateTag:\n case numberTag:\n // Coerce booleans to `1` or `0` and dates to milliseconds.\n // Invalid dates are coerced to `NaN`.\n return eq(+object, +other);\n\n case errorTag:\n return object.name == other.name && object.message == other.message;\n\n case regexpTag:\n case stringTag:\n // Coerce regexes to strings and treat strings, primitives and objects,\n // as equal. See http://www.ecma-international.org/ecma-262/7.0/#sec-regexp.prototype.tostring\n // for more details.\n return object == (other + '');\n\n case mapTag:\n var convert = mapToArray;\n\n case setTag:\n var isPartial = bitmask & COMPARE_PARTIAL_FLAG;\n convert || (convert = setToArray);\n\n if (object.size != other.size && !isPartial) {\n return false;\n }\n // Assume cyclic values are equal.\n var stacked = stack.get(object);\n if (stacked) {\n return stacked == other;\n }\n bitmask |= COMPARE_UNORDERED_FLAG;\n\n // Recursively compare objects (susceptible to call stack limits).\n stack.set(object, other);\n var result = equalArrays(convert(object), convert(other), bitmask, customizer, equalFunc, stack);\n stack['delete'](object);\n return result;\n\n case symbolTag:\n if (symbolValueOf) {\n return symbolValueOf.call(object) == symbolValueOf.call(other);\n }\n }\n return false;\n}\n\nexport default equalByTag;\n","import getAllKeys from './_getAllKeys.js';\n\n/** Used to compose bitmasks for value comparisons. */\nvar COMPARE_PARTIAL_FLAG = 1;\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * A specialized version of `baseIsEqualDeep` for objects with support for\n * partial deep comparisons.\n *\n * @private\n * @param {Object} object The object to compare.\n * @param {Object} other The other object to compare.\n * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.\n * @param {Function} customizer The function to customize comparisons.\n * @param {Function} equalFunc The function to determine equivalents of values.\n * @param {Object} stack Tracks traversed `object` and `other` objects.\n * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.\n */\nfunction equalObjects(object, other, bitmask, customizer, equalFunc, stack) {\n var isPartial = bitmask & COMPARE_PARTIAL_FLAG,\n objProps = getAllKeys(object),\n objLength = objProps.length,\n othProps = getAllKeys(other),\n othLength = othProps.length;\n\n if (objLength != othLength && !isPartial) {\n return false;\n }\n var index = objLength;\n while (index--) {\n var key = objProps[index];\n if (!(isPartial ? key in other : hasOwnProperty.call(other, key))) {\n return false;\n }\n }\n // Check that cyclic values are equal.\n var objStacked = stack.get(object);\n var othStacked = stack.get(other);\n if (objStacked && othStacked) {\n return objStacked == other && othStacked == object;\n }\n var result = true;\n stack.set(object, other);\n stack.set(other, object);\n\n var skipCtor = isPartial;\n while (++index < objLength) {\n key = objProps[index];\n var objValue = object[key],\n othValue = other[key];\n\n if (customizer) {\n var compared = isPartial\n ? customizer(othValue, objValue, key, other, object, stack)\n : customizer(objValue, othValue, key, object, other, stack);\n }\n // Recursively compare objects (susceptible to call stack limits).\n if (!(compared === undefined\n ? (objValue === othValue || equalFunc(objValue, othValue, bitmask, customizer, stack))\n : compared\n )) {\n result = false;\n break;\n }\n skipCtor || (skipCtor = key == 'constructor');\n }\n if (result && !skipCtor) {\n var objCtor = object.constructor,\n othCtor = other.constructor;\n\n // Non `Object` object instances with different constructors are not equal.\n if (objCtor != othCtor &&\n ('constructor' in object && 'constructor' in other) &&\n !(typeof objCtor == 'function' && objCtor instanceof objCtor &&\n typeof othCtor == 'function' && othCtor instanceof othCtor)) {\n result = false;\n }\n }\n stack['delete'](object);\n stack['delete'](other);\n return result;\n}\n\nexport default equalObjects;\n","import Stack from './_Stack.js';\nimport equalArrays from './_equalArrays.js';\nimport equalByTag from './_equalByTag.js';\nimport equalObjects from './_equalObjects.js';\nimport getTag from './_getTag.js';\nimport isArray from './isArray.js';\nimport isBuffer from './isBuffer.js';\nimport isTypedArray from './isTypedArray.js';\n\n/** Used to compose bitmasks for value comparisons. */\nvar COMPARE_PARTIAL_FLAG = 1;\n\n/** `Object#toString` result references. */\nvar argsTag = '[object Arguments]',\n arrayTag = '[object Array]',\n objectTag = '[object Object]';\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * A specialized version of `baseIsEqual` for arrays and objects which performs\n * deep comparisons and tracks traversed objects enabling objects with circular\n * references to be compared.\n *\n * @private\n * @param {Object} object The object to compare.\n * @param {Object} other The other object to compare.\n * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.\n * @param {Function} customizer The function to customize comparisons.\n * @param {Function} equalFunc The function to determine equivalents of values.\n * @param {Object} [stack] Tracks traversed `object` and `other` objects.\n * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.\n */\nfunction baseIsEqualDeep(object, other, bitmask, customizer, equalFunc, stack) {\n var objIsArr = isArray(object),\n othIsArr = isArray(other),\n objTag = objIsArr ? arrayTag : getTag(object),\n othTag = othIsArr ? arrayTag : getTag(other);\n\n objTag = objTag == argsTag ? objectTag : objTag;\n othTag = othTag == argsTag ? objectTag : othTag;\n\n var objIsObj = objTag == objectTag,\n othIsObj = othTag == objectTag,\n isSameTag = objTag == othTag;\n\n if (isSameTag && isBuffer(object)) {\n if (!isBuffer(other)) {\n return false;\n }\n objIsArr = true;\n objIsObj = false;\n }\n if (isSameTag && !objIsObj) {\n stack || (stack = new Stack);\n return (objIsArr || isTypedArray(object))\n ? equalArrays(object, other, bitmask, customizer, equalFunc, stack)\n : equalByTag(object, other, objTag, bitmask, customizer, equalFunc, stack);\n }\n if (!(bitmask & COMPARE_PARTIAL_FLAG)) {\n var objIsWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'),\n othIsWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__');\n\n if (objIsWrapped || othIsWrapped) {\n var objUnwrapped = objIsWrapped ? object.value() : object,\n othUnwrapped = othIsWrapped ? other.value() : other;\n\n stack || (stack = new Stack);\n return equalFunc(objUnwrapped, othUnwrapped, bitmask, customizer, stack);\n }\n }\n if (!isSameTag) {\n return false;\n }\n stack || (stack = new Stack);\n return equalObjects(object, other, bitmask, customizer, equalFunc, stack);\n}\n\nexport default baseIsEqualDeep;\n","import baseIsEqualDeep from './_baseIsEqualDeep.js';\nimport isObjectLike from './isObjectLike.js';\n\n/**\n * The base implementation of `_.isEqual` which supports partial comparisons\n * and tracks traversed objects.\n *\n * @private\n * @param {*} value The value to compare.\n * @param {*} other The other value to compare.\n * @param {boolean} bitmask The bitmask flags.\n * 1 - Unordered comparison\n * 2 - Partial comparison\n * @param {Function} [customizer] The function to customize comparisons.\n * @param {Object} [stack] Tracks traversed `value` and `other` objects.\n * @returns {boolean} Returns `true` if the values are equivalent, else `false`.\n */\nfunction baseIsEqual(value, other, bitmask, customizer, stack) {\n if (value === other) {\n return true;\n }\n if (value == null || other == null || (!isObjectLike(value) && !isObjectLike(other))) {\n return value !== value && other !== other;\n }\n return baseIsEqualDeep(value, other, bitmask, customizer, baseIsEqual, stack);\n}\n\nexport default baseIsEqual;\n","import Stack from './_Stack.js';\nimport baseIsEqual from './_baseIsEqual.js';\n\n/** Used to compose bitmasks for value comparisons. */\nvar COMPARE_PARTIAL_FLAG = 1,\n COMPARE_UNORDERED_FLAG = 2;\n\n/**\n * The base implementation of `_.isMatch` without support for iteratee shorthands.\n *\n * @private\n * @param {Object} object The object to inspect.\n * @param {Object} source The object of property values to match.\n * @param {Array} matchData The property names, values, and compare flags to match.\n * @param {Function} [customizer] The function to customize comparisons.\n * @returns {boolean} Returns `true` if `object` is a match, else `false`.\n */\nfunction baseIsMatch(object, source, matchData, customizer) {\n var index = matchData.length,\n length = index,\n noCustomizer = !customizer;\n\n if (object == null) {\n return !length;\n }\n object = Object(object);\n while (index--) {\n var data = matchData[index];\n if ((noCustomizer && data[2])\n ? data[1] !== object[data[0]]\n : !(data[0] in object)\n ) {\n return false;\n }\n }\n while (++index < length) {\n data = matchData[index];\n var key = data[0],\n objValue = object[key],\n srcValue = data[1];\n\n if (noCustomizer && data[2]) {\n if (objValue === undefined && !(key in object)) {\n return false;\n }\n } else {\n var stack = new Stack;\n if (customizer) {\n var result = customizer(objValue, srcValue, key, object, source, stack);\n }\n if (!(result === undefined\n ? baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG, customizer, stack)\n : result\n )) {\n return false;\n }\n }\n }\n return true;\n}\n\nexport default baseIsMatch;\n","import isObject from './isObject.js';\n\n/**\n * Checks if `value` is suitable for strict equality comparisons, i.e. `===`.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` if suitable for strict\n * equality comparisons, else `false`.\n */\nfunction isStrictComparable(value) {\n return value === value && !isObject(value);\n}\n\nexport default isStrictComparable;\n","import isStrictComparable from './_isStrictComparable.js';\nimport keys from './keys.js';\n\n/**\n * Gets the property names, values, and compare flags of `object`.\n *\n * @private\n * @param {Object} object The object to query.\n * @returns {Array} Returns the match data of `object`.\n */\nfunction getMatchData(object) {\n var result = keys(object),\n length = result.length;\n\n while (length--) {\n var key = result[length],\n value = object[key];\n\n result[length] = [key, value, isStrictComparable(value)];\n }\n return result;\n}\n\nexport default getMatchData;\n","/**\n * A specialized version of `matchesProperty` for source values suitable\n * for strict equality comparisons, i.e. `===`.\n *\n * @private\n * @param {string} key The key of the property to get.\n * @param {*} srcValue The value to match.\n * @returns {Function} Returns the new spec function.\n */\nfunction matchesStrictComparable(key, srcValue) {\n return function(object) {\n if (object == null) {\n return false;\n }\n return object[key] === srcValue &&\n (srcValue !== undefined || (key in Object(object)));\n };\n}\n\nexport default matchesStrictComparable;\n","import baseIsMatch from './_baseIsMatch.js';\nimport getMatchData from './_getMatchData.js';\nimport matchesStrictComparable from './_matchesStrictComparable.js';\n\n/**\n * The base implementation of `_.matches` which doesn't clone `source`.\n *\n * @private\n * @param {Object} source The object of property values to match.\n * @returns {Function} Returns the new spec function.\n */\nfunction baseMatches(source) {\n var matchData = getMatchData(source);\n if (matchData.length == 1 && matchData[0][2]) {\n return matchesStrictComparable(matchData[0][0], matchData[0][1]);\n }\n return function(object) {\n return object === source || baseIsMatch(object, source, matchData);\n };\n}\n\nexport default baseMatches;\n","/**\n * The base implementation of `_.hasIn` without support for deep paths.\n *\n * @private\n * @param {Object} [object] The object to query.\n * @param {Array|string} key The key to check.\n * @returns {boolean} Returns `true` if `key` exists, else `false`.\n */\nfunction baseHasIn(object, key) {\n return object != null && key in Object(object);\n}\n\nexport default baseHasIn;\n","import castPath from './_castPath.js';\nimport isArguments from './isArguments.js';\nimport isArray from './isArray.js';\nimport isIndex from './_isIndex.js';\nimport isLength from './isLength.js';\nimport toKey from './_toKey.js';\n\n/**\n * Checks if `path` exists on `object`.\n *\n * @private\n * @param {Object} object The object to query.\n * @param {Array|string} path The path to check.\n * @param {Function} hasFunc The function to check properties.\n * @returns {boolean} Returns `true` if `path` exists, else `false`.\n */\nfunction hasPath(object, path, hasFunc) {\n path = castPath(path, object);\n\n var index = -1,\n length = path.length,\n result = false;\n\n while (++index < length) {\n var key = toKey(path[index]);\n if (!(result = object != null && hasFunc(object, key))) {\n break;\n }\n object = object[key];\n }\n if (result || ++index != length) {\n return result;\n }\n length = object == null ? 0 : object.length;\n return !!length && isLength(length) && isIndex(key, length) &&\n (isArray(object) || isArguments(object));\n}\n\nexport default hasPath;\n","import baseHasIn from './_baseHasIn.js';\nimport hasPath from './_hasPath.js';\n\n/**\n * Checks if `path` is a direct or inherited property of `object`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Object\n * @param {Object} object The object to query.\n * @param {Array|string} path The path to check.\n * @returns {boolean} Returns `true` if `path` exists, else `false`.\n * @example\n *\n * var object = _.create({ 'a': _.create({ 'b': 2 }) });\n *\n * _.hasIn(object, 'a');\n * // => true\n *\n * _.hasIn(object, 'a.b');\n * // => true\n *\n * _.hasIn(object, ['a', 'b']);\n * // => true\n *\n * _.hasIn(object, 'b');\n * // => false\n */\nfunction hasIn(object, path) {\n return object != null && hasPath(object, path, baseHasIn);\n}\n\nexport default hasIn;\n","import baseIsEqual from './_baseIsEqual.js';\nimport get from './get.js';\nimport hasIn from './hasIn.js';\nimport isKey from './_isKey.js';\nimport isStrictComparable from './_isStrictComparable.js';\nimport matchesStrictComparable from './_matchesStrictComparable.js';\nimport toKey from './_toKey.js';\n\n/** Used to compose bitmasks for value comparisons. */\nvar COMPARE_PARTIAL_FLAG = 1,\n COMPARE_UNORDERED_FLAG = 2;\n\n/**\n * The base implementation of `_.matchesProperty` which doesn't clone `srcValue`.\n *\n * @private\n * @param {string} path The path of the property to get.\n * @param {*} srcValue The value to match.\n * @returns {Function} Returns the new spec function.\n */\nfunction baseMatchesProperty(path, srcValue) {\n if (isKey(path) && isStrictComparable(srcValue)) {\n return matchesStrictComparable(toKey(path), srcValue);\n }\n return function(object) {\n var objValue = get(object, path);\n return (objValue === undefined && objValue === srcValue)\n ? hasIn(object, path)\n : baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG);\n };\n}\n\nexport default baseMatchesProperty;\n","/**\n * The base implementation of `_.property` without support for deep paths.\n *\n * @private\n * @param {string} key The key of the property to get.\n * @returns {Function} Returns the new accessor function.\n */\nfunction baseProperty(key) {\n return function(object) {\n return object == null ? undefined : object[key];\n };\n}\n\nexport default baseProperty;\n","import baseGet from './_baseGet.js';\n\n/**\n * A specialized version of `baseProperty` which supports deep paths.\n *\n * @private\n * @param {Array|string} path The path of the property to get.\n * @returns {Function} Returns the new accessor function.\n */\nfunction basePropertyDeep(path) {\n return function(object) {\n return baseGet(object, path);\n };\n}\n\nexport default basePropertyDeep;\n","import baseProperty from './_baseProperty.js';\nimport basePropertyDeep from './_basePropertyDeep.js';\nimport isKey from './_isKey.js';\nimport toKey from './_toKey.js';\n\n/**\n * Creates a function that returns the value at `path` of a given object.\n *\n * @static\n * @memberOf _\n * @since 2.4.0\n * @category Util\n * @param {Array|string} path The path of the property to get.\n * @returns {Function} Returns the new accessor function.\n * @example\n *\n * var objects = [\n * { 'a': { 'b': 2 } },\n * { 'a': { 'b': 1 } }\n * ];\n *\n * _.map(objects, _.property('a.b'));\n * // => [2, 1]\n *\n * _.map(_.sortBy(objects, _.property(['a', 'b'])), 'a.b');\n * // => [1, 2]\n */\nfunction property(path) {\n return isKey(path) ? baseProperty(toKey(path)) : basePropertyDeep(path);\n}\n\nexport default property;\n","import baseMatches from './_baseMatches.js';\nimport baseMatchesProperty from './_baseMatchesProperty.js';\nimport identity from './identity.js';\nimport isArray from './isArray.js';\nimport property from './property.js';\n\n/**\n * The base implementation of `_.iteratee`.\n *\n * @private\n * @param {*} [value=_.identity] The value to convert to an iteratee.\n * @returns {Function} Returns the iteratee.\n */\nfunction baseIteratee(value) {\n // Don't store the `typeof` result in a variable to avoid a JIT bug in Safari 9.\n // See https://bugs.webkit.org/show_bug.cgi?id=156034 for more details.\n if (typeof value == 'function') {\n return value;\n }\n if (value == null) {\n return identity;\n }\n if (typeof value == 'object') {\n return isArray(value)\n ? baseMatchesProperty(value[0], value[1])\n : baseMatches(value);\n }\n return property(value);\n}\n\nexport default baseIteratee;\n","/**\n * Creates a base function for methods like `_.forIn` and `_.forOwn`.\n *\n * @private\n * @param {boolean} [fromRight] Specify iterating from right to left.\n * @returns {Function} Returns the new base function.\n */\nfunction createBaseFor(fromRight) {\n return function(object, iteratee, keysFunc) {\n var index = -1,\n iterable = Object(object),\n props = keysFunc(object),\n length = props.length;\n\n while (length--) {\n var key = props[fromRight ? length : ++index];\n if (iteratee(iterable[key], key, iterable) === false) {\n break;\n }\n }\n return object;\n };\n}\n\nexport default createBaseFor;\n","import createBaseFor from './_createBaseFor.js';\n\n/**\n * The base implementation of `baseForOwn` which iterates over `object`\n * properties returned by `keysFunc` and invokes `iteratee` for each property.\n * Iteratee functions may exit iteration early by explicitly returning `false`.\n *\n * @private\n * @param {Object} object The object to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @param {Function} keysFunc The function to get the keys of `object`.\n * @returns {Object} Returns `object`.\n */\nvar baseFor = createBaseFor();\n\nexport default baseFor;\n","import baseFor from './_baseFor.js';\nimport keys from './keys.js';\n\n/**\n * The base implementation of `_.forOwn` without support for iteratee shorthands.\n *\n * @private\n * @param {Object} object The object to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @returns {Object} Returns `object`.\n */\nfunction baseForOwn(object, iteratee) {\n return object && baseFor(object, iteratee, keys);\n}\n\nexport default baseForOwn;\n","import isArrayLike from './isArrayLike.js';\n\n/**\n * Creates a `baseEach` or `baseEachRight` function.\n *\n * @private\n * @param {Function} eachFunc The function to iterate over a collection.\n * @param {boolean} [fromRight] Specify iterating from right to left.\n * @returns {Function} Returns the new base function.\n */\nfunction createBaseEach(eachFunc, fromRight) {\n return function(collection, iteratee) {\n if (collection == null) {\n return collection;\n }\n if (!isArrayLike(collection)) {\n return eachFunc(collection, iteratee);\n }\n var length = collection.length,\n index = fromRight ? length : -1,\n iterable = Object(collection);\n\n while ((fromRight ? index-- : ++index < length)) {\n if (iteratee(iterable[index], index, iterable) === false) {\n break;\n }\n }\n return collection;\n };\n}\n\nexport default createBaseEach;\n","import baseForOwn from './_baseForOwn.js';\nimport createBaseEach from './_createBaseEach.js';\n\n/**\n * The base implementation of `_.forEach` without support for iteratee shorthands.\n *\n * @private\n * @param {Array|Object} collection The collection to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @returns {Array|Object} Returns `collection`.\n */\nvar baseEach = createBaseEach(baseForOwn);\n\nexport default baseEach;\n","import baseRest from './_baseRest.js';\nimport eq from './eq.js';\nimport isIterateeCall from './_isIterateeCall.js';\nimport keysIn from './keysIn.js';\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * Assigns own and inherited enumerable string keyed properties of source\n * objects to the destination object for all destination properties that\n * resolve to `undefined`. Source objects are applied from left to right.\n * Once a property is set, additional values of the same property are ignored.\n *\n * **Note:** This method mutates `object`.\n *\n * @static\n * @since 0.1.0\n * @memberOf _\n * @category Object\n * @param {Object} object The destination object.\n * @param {...Object} [sources] The source objects.\n * @returns {Object} Returns `object`.\n * @see _.defaultsDeep\n * @example\n *\n * _.defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 });\n * // => { 'a': 1, 'b': 2 }\n */\nvar defaults = baseRest(function(object, sources) {\n object = Object(object);\n\n var index = -1;\n var length = sources.length;\n var guard = length > 2 ? sources[2] : undefined;\n\n if (guard && isIterateeCall(sources[0], sources[1], guard)) {\n length = 1;\n }\n\n while (++index < length) {\n var source = sources[index];\n var props = keysIn(source);\n var propsIndex = -1;\n var propsLength = props.length;\n\n while (++propsIndex < propsLength) {\n var key = props[propsIndex];\n var value = object[key];\n\n if (value === undefined ||\n (eq(value, objectProto[key]) && !hasOwnProperty.call(object, key))) {\n object[key] = source[key];\n }\n }\n }\n\n return object;\n});\n\nexport default defaults;\n","import baseAssignValue from './_baseAssignValue.js';\nimport eq from './eq.js';\n\n/**\n * This function is like `assignValue` except that it doesn't assign\n * `undefined` values.\n *\n * @private\n * @param {Object} object The object to modify.\n * @param {string} key The key of the property to assign.\n * @param {*} value The value to assign.\n */\nfunction assignMergeValue(object, key, value) {\n if ((value !== undefined && !eq(object[key], value)) ||\n (value === undefined && !(key in object))) {\n baseAssignValue(object, key, value);\n }\n}\n\nexport default assignMergeValue;\n","import isArrayLike from './isArrayLike.js';\nimport isObjectLike from './isObjectLike.js';\n\n/**\n * This method is like `_.isArrayLike` except that it also checks if `value`\n * is an object.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an array-like object,\n * else `false`.\n * @example\n *\n * _.isArrayLikeObject([1, 2, 3]);\n * // => true\n *\n * _.isArrayLikeObject(document.body.children);\n * // => true\n *\n * _.isArrayLikeObject('abc');\n * // => false\n *\n * _.isArrayLikeObject(_.noop);\n * // => false\n */\nfunction isArrayLikeObject(value) {\n return isObjectLike(value) && isArrayLike(value);\n}\n\nexport default isArrayLikeObject;\n","/**\n * Gets the value at `key`, unless `key` is \"__proto__\" or \"constructor\".\n *\n * @private\n * @param {Object} object The object to query.\n * @param {string} key The key of the property to get.\n * @returns {*} Returns the property value.\n */\nfunction safeGet(object, key) {\n if (key === 'constructor' && typeof object[key] === 'function') {\n return;\n }\n\n if (key == '__proto__') {\n return;\n }\n\n return object[key];\n}\n\nexport default safeGet;\n","import copyObject from './_copyObject.js';\nimport keysIn from './keysIn.js';\n\n/**\n * Converts `value` to a plain object flattening inherited enumerable string\n * keyed properties of `value` to own properties of the plain object.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Lang\n * @param {*} value The value to convert.\n * @returns {Object} Returns the converted plain object.\n * @example\n *\n * function Foo() {\n * this.b = 2;\n * }\n *\n * Foo.prototype.c = 3;\n *\n * _.assign({ 'a': 1 }, new Foo);\n * // => { 'a': 1, 'b': 2 }\n *\n * _.assign({ 'a': 1 }, _.toPlainObject(new Foo));\n * // => { 'a': 1, 'b': 2, 'c': 3 }\n */\nfunction toPlainObject(value) {\n return copyObject(value, keysIn(value));\n}\n\nexport default toPlainObject;\n","import assignMergeValue from './_assignMergeValue.js';\nimport cloneBuffer from './_cloneBuffer.js';\nimport cloneTypedArray from './_cloneTypedArray.js';\nimport copyArray from './_copyArray.js';\nimport initCloneObject from './_initCloneObject.js';\nimport isArguments from './isArguments.js';\nimport isArray from './isArray.js';\nimport isArrayLikeObject from './isArrayLikeObject.js';\nimport isBuffer from './isBuffer.js';\nimport isFunction from './isFunction.js';\nimport isObject from './isObject.js';\nimport isPlainObject from './isPlainObject.js';\nimport isTypedArray from './isTypedArray.js';\nimport safeGet from './_safeGet.js';\nimport toPlainObject from './toPlainObject.js';\n\n/**\n * A specialized version of `baseMerge` for arrays and objects which performs\n * deep merges and tracks traversed objects enabling objects with circular\n * references to be merged.\n *\n * @private\n * @param {Object} object The destination object.\n * @param {Object} source The source object.\n * @param {string} key The key of the value to merge.\n * @param {number} srcIndex The index of `source`.\n * @param {Function} mergeFunc The function to merge values.\n * @param {Function} [customizer] The function to customize assigned values.\n * @param {Object} [stack] Tracks traversed source values and their merged\n * counterparts.\n */\nfunction baseMergeDeep(object, source, key, srcIndex, mergeFunc, customizer, stack) {\n var objValue = safeGet(object, key),\n srcValue = safeGet(source, key),\n stacked = stack.get(srcValue);\n\n if (stacked) {\n assignMergeValue(object, key, stacked);\n return;\n }\n var newValue = customizer\n ? customizer(objValue, srcValue, (key + ''), object, source, stack)\n : undefined;\n\n var isCommon = newValue === undefined;\n\n if (isCommon) {\n var isArr = isArray(srcValue),\n isBuff = !isArr && isBuffer(srcValue),\n isTyped = !isArr && !isBuff && isTypedArray(srcValue);\n\n newValue = srcValue;\n if (isArr || isBuff || isTyped) {\n if (isArray(objValue)) {\n newValue = objValue;\n }\n else if (isArrayLikeObject(objValue)) {\n newValue = copyArray(objValue);\n }\n else if (isBuff) {\n isCommon = false;\n newValue = cloneBuffer(srcValue, true);\n }\n else if (isTyped) {\n isCommon = false;\n newValue = cloneTypedArray(srcValue, true);\n }\n else {\n newValue = [];\n }\n }\n else if (isPlainObject(srcValue) || isArguments(srcValue)) {\n newValue = objValue;\n if (isArguments(objValue)) {\n newValue = toPlainObject(objValue);\n }\n else if (!isObject(objValue) || isFunction(objValue)) {\n newValue = initCloneObject(srcValue);\n }\n }\n else {\n isCommon = false;\n }\n }\n if (isCommon) {\n // Recursively merge objects and arrays (susceptible to call stack limits).\n stack.set(srcValue, newValue);\n mergeFunc(newValue, srcValue, srcIndex, customizer, stack);\n stack['delete'](srcValue);\n }\n assignMergeValue(object, key, newValue);\n}\n\nexport default baseMergeDeep;\n","import Stack from './_Stack.js';\nimport assignMergeValue from './_assignMergeValue.js';\nimport baseFor from './_baseFor.js';\nimport baseMergeDeep from './_baseMergeDeep.js';\nimport isObject from './isObject.js';\nimport keysIn from './keysIn.js';\nimport safeGet from './_safeGet.js';\n\n/**\n * The base implementation of `_.merge` without support for multiple sources.\n *\n * @private\n * @param {Object} object The destination object.\n * @param {Object} source The source object.\n * @param {number} srcIndex The index of `source`.\n * @param {Function} [customizer] The function to customize merged values.\n * @param {Object} [stack] Tracks traversed source values and their merged\n * counterparts.\n */\nfunction baseMerge(object, source, srcIndex, customizer, stack) {\n if (object === source) {\n return;\n }\n baseFor(source, function(srcValue, key) {\n stack || (stack = new Stack);\n if (isObject(srcValue)) {\n baseMergeDeep(object, source, key, srcIndex, baseMerge, customizer, stack);\n }\n else {\n var newValue = customizer\n ? customizer(safeGet(object, key), srcValue, (key + ''), object, source, stack)\n : undefined;\n\n if (newValue === undefined) {\n newValue = srcValue;\n }\n assignMergeValue(object, key, newValue);\n }\n }, keysIn);\n}\n\nexport default baseMerge;\n","import baseMerge from './_baseMerge.js';\nimport isObject from './isObject.js';\n\n/**\n * Used by `_.defaultsDeep` to customize its `_.merge` use to merge source\n * objects into destination objects that are passed thru.\n *\n * @private\n * @param {*} objValue The destination value.\n * @param {*} srcValue The source value.\n * @param {string} key The key of the property to merge.\n * @param {Object} object The parent object of `objValue`.\n * @param {Object} source The parent object of `srcValue`.\n * @param {Object} [stack] Tracks traversed source values and their merged\n * counterparts.\n * @returns {*} Returns the value to assign.\n */\nfunction customDefaultsMerge(objValue, srcValue, key, object, source, stack) {\n if (isObject(objValue) && isObject(srcValue)) {\n // Recursively merge objects and arrays (susceptible to call stack limits).\n stack.set(srcValue, objValue);\n baseMerge(objValue, srcValue, undefined, customDefaultsMerge, stack);\n stack['delete'](srcValue);\n }\n return objValue;\n}\n\nexport default customDefaultsMerge;\n","import baseMerge from './_baseMerge.js';\nimport createAssigner from './_createAssigner.js';\n\n/**\n * This method is like `_.merge` except that it accepts `customizer` which\n * is invoked to produce the merged values of the destination and source\n * properties. If `customizer` returns `undefined`, merging is handled by the\n * method instead. The `customizer` is invoked with six arguments:\n * (objValue, srcValue, key, object, source, stack).\n *\n * **Note:** This method mutates `object`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Object\n * @param {Object} object The destination object.\n * @param {...Object} sources The source objects.\n * @param {Function} customizer The function to customize assigned values.\n * @returns {Object} Returns `object`.\n * @example\n *\n * function customizer(objValue, srcValue) {\n * if (_.isArray(objValue)) {\n * return objValue.concat(srcValue);\n * }\n * }\n *\n * var object = { 'a': [1], 'b': [2] };\n * var other = { 'a': [3], 'b': [4] };\n *\n * _.mergeWith(object, other, customizer);\n * // => { 'a': [1, 3], 'b': [2, 4] }\n */\nvar mergeWith = createAssigner(function(object, source, srcIndex, customizer) {\n baseMerge(object, source, srcIndex, customizer);\n});\n\nexport default mergeWith;\n","import apply from './_apply.js';\nimport baseRest from './_baseRest.js';\nimport customDefaultsMerge from './_customDefaultsMerge.js';\nimport mergeWith from './mergeWith.js';\n\n/**\n * This method is like `_.defaults` except that it recursively assigns\n * default properties.\n *\n * **Note:** This method mutates `object`.\n *\n * @static\n * @memberOf _\n * @since 3.10.0\n * @category Object\n * @param {Object} object The destination object.\n * @param {...Object} [sources] The source objects.\n * @returns {Object} Returns `object`.\n * @see _.defaults\n * @example\n *\n * _.defaultsDeep({ 'a': { 'b': 2 } }, { 'a': { 'b': 1, 'c': 3 } });\n * // => { 'a': { 'b': 2, 'c': 3 } }\n */\nvar defaultsDeep = baseRest(function(args) {\n args.push(undefined, customDefaultsMerge);\n return apply(mergeWith, undefined, args);\n});\n\nexport default defaultsDeep;\n","/**\n * This function is like `arrayIncludes` except that it accepts a comparator.\n *\n * @private\n * @param {Array} [array] The array to inspect.\n * @param {*} target The value to search for.\n * @param {Function} comparator The comparator invoked per element.\n * @returns {boolean} Returns `true` if `target` is found, else `false`.\n */\nfunction arrayIncludesWith(array, value, comparator) {\n var index = -1,\n length = array == null ? 0 : array.length;\n\n while (++index < length) {\n if (comparator(value, array[index])) {\n return true;\n }\n }\n return false;\n}\n\nexport default arrayIncludesWith;\n","import SetCache from './_SetCache.js';\nimport arrayIncludes from './_arrayIncludes.js';\nimport arrayIncludesWith from './_arrayIncludesWith.js';\nimport arrayMap from './_arrayMap.js';\nimport baseUnary from './_baseUnary.js';\nimport cacheHas from './_cacheHas.js';\n\n/** Used as the size to enable large array optimizations. */\nvar LARGE_ARRAY_SIZE = 200;\n\n/**\n * The base implementation of methods like `_.difference` without support\n * for excluding multiple arrays or iteratee shorthands.\n *\n * @private\n * @param {Array} array The array to inspect.\n * @param {Array} values The values to exclude.\n * @param {Function} [iteratee] The iteratee invoked per element.\n * @param {Function} [comparator] The comparator invoked per element.\n * @returns {Array} Returns the new array of filtered values.\n */\nfunction baseDifference(array, values, iteratee, comparator) {\n var index = -1,\n includes = arrayIncludes,\n isCommon = true,\n length = array.length,\n result = [],\n valuesLength = values.length;\n\n if (!length) {\n return result;\n }\n if (iteratee) {\n values = arrayMap(values, baseUnary(iteratee));\n }\n if (comparator) {\n includes = arrayIncludesWith;\n isCommon = false;\n }\n else if (values.length >= LARGE_ARRAY_SIZE) {\n includes = cacheHas;\n isCommon = false;\n values = new SetCache(values);\n }\n outer:\n while (++index < length) {\n var value = array[index],\n computed = iteratee == null ? value : iteratee(value);\n\n value = (comparator || value !== 0) ? value : 0;\n if (isCommon && computed === computed) {\n var valuesIndex = valuesLength;\n while (valuesIndex--) {\n if (values[valuesIndex] === computed) {\n continue outer;\n }\n }\n result.push(value);\n }\n else if (!includes(values, computed, comparator)) {\n result.push(value);\n }\n }\n return result;\n}\n\nexport default baseDifference;\n","/**\n * Gets the last element of `array`.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Array\n * @param {Array} array The array to query.\n * @returns {*} Returns the last element of `array`.\n * @example\n *\n * _.last([1, 2, 3]);\n * // => 3\n */\nfunction last(array) {\n var length = array == null ? 0 : array.length;\n return length ? array[length - 1] : undefined;\n}\n\nexport default last;\n","import identity from './identity.js';\n\n/**\n * Casts `value` to `identity` if it's not a function.\n *\n * @private\n * @param {*} value The value to inspect.\n * @returns {Function} Returns cast function.\n */\nfunction castFunction(value) {\n return typeof value == 'function' ? value : identity;\n}\n\nexport default castFunction;\n","import arrayEach from './_arrayEach.js';\nimport baseEach from './_baseEach.js';\nimport castFunction from './_castFunction.js';\nimport isArray from './isArray.js';\n\n/**\n * Iterates over elements of `collection` and invokes `iteratee` for each element.\n * The iteratee is invoked with three arguments: (value, index|key, collection).\n * Iteratee functions may exit iteration early by explicitly returning `false`.\n *\n * **Note:** As with other \"Collections\" methods, objects with a \"length\"\n * property are iterated like arrays. To avoid this behavior use `_.forIn`\n * or `_.forOwn` for object iteration.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @alias each\n * @category Collection\n * @param {Array|Object} collection The collection to iterate over.\n * @param {Function} [iteratee=_.identity] The function invoked per iteration.\n * @returns {Array|Object} Returns `collection`.\n * @see _.forEachRight\n * @example\n *\n * _.forEach([1, 2], function(value) {\n * console.log(value);\n * });\n * // => Logs `1` then `2`.\n *\n * _.forEach({ 'a': 1, 'b': 2 }, function(value, key) {\n * console.log(key);\n * });\n * // => Logs 'a' then 'b' (iteration order is not guaranteed).\n */\nfunction forEach(collection, iteratee) {\n var func = isArray(collection) ? arrayEach : baseEach;\n return func(collection, castFunction(iteratee));\n}\n\nexport default forEach;\n","import baseEach from './_baseEach.js';\nimport isArrayLike from './isArrayLike.js';\n\n/**\n * The base implementation of `_.map` without support for iteratee shorthands.\n *\n * @private\n * @param {Array|Object} collection The collection to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @returns {Array} Returns the new mapped array.\n */\nfunction baseMap(collection, iteratee) {\n var index = -1,\n result = isArrayLike(collection) ? Array(collection.length) : [];\n\n baseEach(collection, function(value, key, collection) {\n result[++index] = iteratee(value, key, collection);\n });\n return result;\n}\n\nexport default baseMap;\n","import baseFlatten from './_baseFlatten.js';\n\n/** Used as references for various `Number` constants. */\nvar INFINITY = 1 / 0;\n\n/**\n * Recursively flattens `array`.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Array\n * @param {Array} array The array to flatten.\n * @returns {Array} Returns the new flattened array.\n * @example\n *\n * _.flattenDeep([1, [2, [3, [4]], 5]]);\n * // => [1, 2, 3, 4, 5]\n */\nfunction flattenDeep(array) {\n var length = array == null ? 0 : array.length;\n return length ? baseFlatten(array, INFINITY) : [];\n}\n\nexport default flattenDeep;\n","import SetCache from './_SetCache.js';\nimport arrayIncludes from './_arrayIncludes.js';\nimport arrayIncludesWith from './_arrayIncludesWith.js';\nimport arrayMap from './_arrayMap.js';\nimport baseUnary from './_baseUnary.js';\nimport cacheHas from './_cacheHas.js';\n\n/* Built-in method references for those with the same name as other `lodash` methods. */\nvar nativeMin = Math.min;\n\n/**\n * The base implementation of methods like `_.intersection`, without support\n * for iteratee shorthands, that accepts an array of arrays to inspect.\n *\n * @private\n * @param {Array} arrays The arrays to inspect.\n * @param {Function} [iteratee] The iteratee invoked per element.\n * @param {Function} [comparator] The comparator invoked per element.\n * @returns {Array} Returns the new array of shared values.\n */\nfunction baseIntersection(arrays, iteratee, comparator) {\n var includes = comparator ? arrayIncludesWith : arrayIncludes,\n length = arrays[0].length,\n othLength = arrays.length,\n othIndex = othLength,\n caches = Array(othLength),\n maxLength = Infinity,\n result = [];\n\n while (othIndex--) {\n var array = arrays[othIndex];\n if (othIndex && iteratee) {\n array = arrayMap(array, baseUnary(iteratee));\n }\n maxLength = nativeMin(array.length, maxLength);\n caches[othIndex] = !comparator && (iteratee || (length >= 120 && array.length >= 120))\n ? new SetCache(othIndex && array)\n : undefined;\n }\n array = arrays[0];\n\n var index = -1,\n seen = caches[0];\n\n outer:\n while (++index < length && result.length < maxLength) {\n var value = array[index],\n computed = iteratee ? iteratee(value) : value;\n\n value = (comparator || value !== 0) ? value : 0;\n if (!(seen\n ? cacheHas(seen, computed)\n : includes(result, computed, comparator)\n )) {\n othIndex = othLength;\n while (--othIndex) {\n var cache = caches[othIndex];\n if (!(cache\n ? cacheHas(cache, computed)\n : includes(arrays[othIndex], computed, comparator))\n ) {\n continue outer;\n }\n }\n if (seen) {\n seen.push(computed);\n }\n result.push(value);\n }\n }\n return result;\n}\n\nexport default baseIntersection;\n","import isArrayLikeObject from './isArrayLikeObject.js';\n\n/**\n * Casts `value` to an empty array if it's not an array like object.\n *\n * @private\n * @param {*} value The value to inspect.\n * @returns {Array|Object} Returns the cast array-like object.\n */\nfunction castArrayLikeObject(value) {\n return isArrayLikeObject(value) ? value : [];\n}\n\nexport default castArrayLikeObject;\n","import arrayMap from './_arrayMap.js';\nimport baseIntersection from './_baseIntersection.js';\nimport baseRest from './_baseRest.js';\nimport castArrayLikeObject from './_castArrayLikeObject.js';\n\n/**\n * Creates an array of unique values that are included in all given arrays\n * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)\n * for equality comparisons. The order and references of result values are\n * determined by the first array.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Array\n * @param {...Array} [arrays] The arrays to inspect.\n * @returns {Array} Returns the new array of intersecting values.\n * @example\n *\n * _.intersection([2, 1], [2, 3]);\n * // => [2]\n */\nvar intersection = baseRest(function(arrays) {\n var mapped = arrayMap(arrays, castArrayLikeObject);\n return (mapped.length && mapped[0] === arrays[0])\n ? baseIntersection(mapped)\n : [];\n});\n\nexport default intersection;\n","import arrayMap from './_arrayMap.js';\nimport baseIntersection from './_baseIntersection.js';\nimport baseRest from './_baseRest.js';\nimport castArrayLikeObject from './_castArrayLikeObject.js';\nimport last from './last.js';\n\n/**\n * This method is like `_.intersection` except that it accepts `comparator`\n * which is invoked to compare elements of `arrays`. The order and references\n * of result values are determined by the first array. The comparator is\n * invoked with two arguments: (arrVal, othVal).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Array\n * @param {...Array} [arrays] The arrays to inspect.\n * @param {Function} [comparator] The comparator invoked per element.\n * @returns {Array} Returns the new array of intersecting values.\n * @example\n *\n * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];\n * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }];\n *\n * _.intersectionWith(objects, others, _.isEqual);\n * // => [{ 'x': 1, 'y': 2 }]\n */\nvar intersectionWith = baseRest(function(arrays) {\n var comparator = last(arrays),\n mapped = arrayMap(arrays, castArrayLikeObject);\n\n comparator = typeof comparator == 'function' ? comparator : undefined;\n if (comparator) {\n mapped.pop();\n }\n return (mapped.length && mapped[0] === arrays[0])\n ? baseIntersection(mapped, undefined, comparator)\n : [];\n});\n\nexport default intersectionWith;\n","import baseGetTag from './_baseGetTag.js';\nimport isObjectLike from './isObjectLike.js';\n\n/** `Object#toString` result references. */\nvar boolTag = '[object Boolean]';\n\n/**\n * Checks if `value` is classified as a boolean primitive or object.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a boolean, else `false`.\n * @example\n *\n * _.isBoolean(false);\n * // => true\n *\n * _.isBoolean(null);\n * // => false\n */\nfunction isBoolean(value) {\n return value === true || value === false ||\n (isObjectLike(value) && baseGetTag(value) == boolTag);\n}\n\nexport default isBoolean;\n","import baseIsEqual from './_baseIsEqual.js';\n\n/**\n * Performs a deep comparison between two values to determine if they are\n * equivalent.\n *\n * **Note:** This method supports comparing arrays, array buffers, booleans,\n * date objects, error objects, maps, numbers, `Object` objects, regexes,\n * sets, strings, symbols, and typed arrays. `Object` objects are compared\n * by their own, not inherited, enumerable properties. Functions and DOM\n * nodes are compared by strict equality, i.e. `===`.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to compare.\n * @param {*} other The other value to compare.\n * @returns {boolean} Returns `true` if the values are equivalent, else `false`.\n * @example\n *\n * var object = { 'a': 1 };\n * var other = { 'a': 1 };\n *\n * _.isEqual(object, other);\n * // => true\n *\n * object === other;\n * // => false\n */\nfunction isEqual(value, other) {\n return baseIsEqual(value, other);\n}\n\nexport default isEqual;\n","import assignValue from './_assignValue.js';\nimport castPath from './_castPath.js';\nimport isIndex from './_isIndex.js';\nimport isObject from './isObject.js';\nimport toKey from './_toKey.js';\n\n/**\n * The base implementation of `_.set`.\n *\n * @private\n * @param {Object} object The object to modify.\n * @param {Array|string} path The path of the property to set.\n * @param {*} value The value to set.\n * @param {Function} [customizer] The function to customize path creation.\n * @returns {Object} Returns `object`.\n */\nfunction baseSet(object, path, value, customizer) {\n if (!isObject(object)) {\n return object;\n }\n path = castPath(path, object);\n\n var index = -1,\n length = path.length,\n lastIndex = length - 1,\n nested = object;\n\n while (nested != null && ++index < length) {\n var key = toKey(path[index]),\n newValue = value;\n\n if (key === '__proto__' || key === 'constructor' || key === 'prototype') {\n return object;\n }\n\n if (index != lastIndex) {\n var objValue = nested[key];\n newValue = customizer ? customizer(objValue, key, nested) : undefined;\n if (newValue === undefined) {\n newValue = isObject(objValue)\n ? objValue\n : (isIndex(path[index + 1]) ? [] : {});\n }\n }\n assignValue(nested, key, newValue);\n nested = nested[key];\n }\n return object;\n}\n\nexport default baseSet;\n","import baseGet from './_baseGet.js';\nimport baseSet from './_baseSet.js';\nimport castPath from './_castPath.js';\n\n/**\n * The base implementation of `_.pickBy` without support for iteratee shorthands.\n *\n * @private\n * @param {Object} object The source object.\n * @param {string[]} paths The property paths to pick.\n * @param {Function} predicate The function invoked per property.\n * @returns {Object} Returns the new object.\n */\nfunction basePickBy(object, paths, predicate) {\n var index = -1,\n length = paths.length,\n result = {};\n\n while (++index < length) {\n var path = paths[index],\n value = baseGet(object, path);\n\n if (predicate(value, path)) {\n baseSet(result, castPath(path, object), value);\n }\n }\n return result;\n}\n\nexport default basePickBy;\n","/**\n * The base implementation of `_.sortBy` which uses `comparer` to define the\n * sort order of `array` and replaces criteria objects with their corresponding\n * values.\n *\n * @private\n * @param {Array} array The array to sort.\n * @param {Function} comparer The function to define sort order.\n * @returns {Array} Returns `array`.\n */\nfunction baseSortBy(array, comparer) {\n var length = array.length;\n\n array.sort(comparer);\n while (length--) {\n array[length] = array[length].value;\n }\n return array;\n}\n\nexport default baseSortBy;\n","import isSymbol from './isSymbol.js';\n\n/**\n * Compares values to sort them in ascending order.\n *\n * @private\n * @param {*} value The value to compare.\n * @param {*} other The other value to compare.\n * @returns {number} Returns the sort order indicator for `value`.\n */\nfunction compareAscending(value, other) {\n if (value !== other) {\n var valIsDefined = value !== undefined,\n valIsNull = value === null,\n valIsReflexive = value === value,\n valIsSymbol = isSymbol(value);\n\n var othIsDefined = other !== undefined,\n othIsNull = other === null,\n othIsReflexive = other === other,\n othIsSymbol = isSymbol(other);\n\n if ((!othIsNull && !othIsSymbol && !valIsSymbol && value > other) ||\n (valIsSymbol && othIsDefined && othIsReflexive && !othIsNull && !othIsSymbol) ||\n (valIsNull && othIsDefined && othIsReflexive) ||\n (!valIsDefined && othIsReflexive) ||\n !valIsReflexive) {\n return 1;\n }\n if ((!valIsNull && !valIsSymbol && !othIsSymbol && value < other) ||\n (othIsSymbol && valIsDefined && valIsReflexive && !valIsNull && !valIsSymbol) ||\n (othIsNull && valIsDefined && valIsReflexive) ||\n (!othIsDefined && valIsReflexive) ||\n !othIsReflexive) {\n return -1;\n }\n }\n return 0;\n}\n\nexport default compareAscending;\n","import compareAscending from './_compareAscending.js';\n\n/**\n * Used by `_.orderBy` to compare multiple properties of a value to another\n * and stable sort them.\n *\n * If `orders` is unspecified, all values are sorted in ascending order. Otherwise,\n * specify an order of \"desc\" for descending or \"asc\" for ascending sort order\n * of corresponding values.\n *\n * @private\n * @param {Object} object The object to compare.\n * @param {Object} other The other object to compare.\n * @param {boolean[]|string[]} orders The order to sort by for each property.\n * @returns {number} Returns the sort order indicator for `object`.\n */\nfunction compareMultiple(object, other, orders) {\n var index = -1,\n objCriteria = object.criteria,\n othCriteria = other.criteria,\n length = objCriteria.length,\n ordersLength = orders.length;\n\n while (++index < length) {\n var result = compareAscending(objCriteria[index], othCriteria[index]);\n if (result) {\n if (index >= ordersLength) {\n return result;\n }\n var order = orders[index];\n return result * (order == 'desc' ? -1 : 1);\n }\n }\n // Fixes an `Array#sort` bug in the JS engine embedded in Adobe applications\n // that causes it, under certain circumstances, to provide the same value for\n // `object` and `other`. See https://github.com/jashkenas/underscore/pull/1247\n // for more details.\n //\n // This also ensures a stable sort in V8 and other engines.\n // See https://bugs.chromium.org/p/v8/issues/detail?id=90 for more details.\n return object.index - other.index;\n}\n\nexport default compareMultiple;\n","import arrayMap from './_arrayMap.js';\nimport baseGet from './_baseGet.js';\nimport baseIteratee from './_baseIteratee.js';\nimport baseMap from './_baseMap.js';\nimport baseSortBy from './_baseSortBy.js';\nimport baseUnary from './_baseUnary.js';\nimport compareMultiple from './_compareMultiple.js';\nimport identity from './identity.js';\nimport isArray from './isArray.js';\n\n/**\n * The base implementation of `_.orderBy` without param guards.\n *\n * @private\n * @param {Array|Object} collection The collection to iterate over.\n * @param {Function[]|Object[]|string[]} iteratees The iteratees to sort by.\n * @param {string[]} orders The sort orders of `iteratees`.\n * @returns {Array} Returns the new sorted array.\n */\nfunction baseOrderBy(collection, iteratees, orders) {\n if (iteratees.length) {\n iteratees = arrayMap(iteratees, function(iteratee) {\n if (isArray(iteratee)) {\n return function(value) {\n return baseGet(value, iteratee.length === 1 ? iteratee[0] : iteratee);\n }\n }\n return iteratee;\n });\n } else {\n iteratees = [identity];\n }\n\n var index = -1;\n iteratees = arrayMap(iteratees, baseUnary(baseIteratee));\n\n var result = baseMap(collection, function(value, key, collection) {\n var criteria = arrayMap(iteratees, function(iteratee) {\n return iteratee(value);\n });\n return { 'criteria': criteria, 'index': ++index, 'value': value };\n });\n\n return baseSortBy(result, function(object, other) {\n return compareMultiple(object, other, orders);\n });\n}\n\nexport default baseOrderBy;\n","import basePickBy from './_basePickBy.js';\nimport hasIn from './hasIn.js';\n\n/**\n * The base implementation of `_.pick` without support for individual\n * property identifiers.\n *\n * @private\n * @param {Object} object The source object.\n * @param {string[]} paths The property paths to pick.\n * @returns {Object} Returns the new object.\n */\nfunction basePick(object, paths) {\n return basePickBy(object, paths, function(value, path) {\n return hasIn(object, path);\n });\n}\n\nexport default basePick;\n","import basePick from './_basePick.js';\nimport flatRest from './_flatRest.js';\n\n/**\n * Creates an object composed of the picked `object` properties.\n *\n * @static\n * @since 0.1.0\n * @memberOf _\n * @category Object\n * @param {Object} object The source object.\n * @param {...(string|string[])} [paths] The property paths to pick.\n * @returns {Object} Returns the new object.\n * @example\n *\n * var object = { 'a': 1, 'b': '2', 'c': 3 };\n *\n * _.pick(object, ['a', 'c']);\n * // => { 'a': 1, 'c': 3 }\n */\nvar pick = flatRest(function(object, paths) {\n return object == null ? {} : basePick(object, paths);\n});\n\nexport default pick;\n","/**\n * This function is like `baseIndexOf` except that it accepts a comparator.\n *\n * @private\n * @param {Array} array The array to inspect.\n * @param {*} value The value to search for.\n * @param {number} fromIndex The index to search from.\n * @param {Function} comparator The comparator invoked per element.\n * @returns {number} Returns the index of the matched value, else `-1`.\n */\nfunction baseIndexOfWith(array, value, fromIndex, comparator) {\n var index = fromIndex - 1,\n length = array.length;\n\n while (++index < length) {\n if (comparator(array[index], value)) {\n return index;\n }\n }\n return -1;\n}\n\nexport default baseIndexOfWith;\n","import arrayMap from './_arrayMap.js';\nimport baseIndexOf from './_baseIndexOf.js';\nimport baseIndexOfWith from './_baseIndexOfWith.js';\nimport baseUnary from './_baseUnary.js';\nimport copyArray from './_copyArray.js';\n\n/** Used for built-in method references. */\nvar arrayProto = Array.prototype;\n\n/** Built-in value references. */\nvar splice = arrayProto.splice;\n\n/**\n * The base implementation of `_.pullAllBy` without support for iteratee\n * shorthands.\n *\n * @private\n * @param {Array} array The array to modify.\n * @param {Array} values The values to remove.\n * @param {Function} [iteratee] The iteratee invoked per element.\n * @param {Function} [comparator] The comparator invoked per element.\n * @returns {Array} Returns `array`.\n */\nfunction basePullAll(array, values, iteratee, comparator) {\n var indexOf = comparator ? baseIndexOfWith : baseIndexOf,\n index = -1,\n length = values.length,\n seen = array;\n\n if (array === values) {\n values = copyArray(values);\n }\n if (iteratee) {\n seen = arrayMap(array, baseUnary(iteratee));\n }\n while (++index < length) {\n var fromIndex = 0,\n value = values[index],\n computed = iteratee ? iteratee(value) : value;\n\n while ((fromIndex = indexOf(seen, computed, fromIndex, comparator)) > -1) {\n if (seen !== array) {\n splice.call(seen, fromIndex, 1);\n }\n splice.call(array, fromIndex, 1);\n }\n }\n return array;\n}\n\nexport default basePullAll;\n","import basePullAll from './_basePullAll.js';\n\n/**\n * This method is like `_.pull` except that it accepts an array of values to remove.\n *\n * **Note:** Unlike `_.difference`, this method mutates `array`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Array\n * @param {Array} array The array to modify.\n * @param {Array} values The values to remove.\n * @returns {Array} Returns `array`.\n * @example\n *\n * var array = ['a', 'b', 'c', 'a', 'b', 'c'];\n *\n * _.pullAll(array, ['a', 'c']);\n * console.log(array);\n * // => ['b', 'b']\n */\nfunction pullAll(array, values) {\n return (array && array.length && values && values.length)\n ? basePullAll(array, values)\n : array;\n}\n\nexport default pullAll;\n","import baseFlatten from './_baseFlatten.js';\nimport baseOrderBy from './_baseOrderBy.js';\nimport baseRest from './_baseRest.js';\nimport isIterateeCall from './_isIterateeCall.js';\n\n/**\n * Creates an array of elements, sorted in ascending order by the results of\n * running each element in a collection thru each iteratee. This method\n * performs a stable sort, that is, it preserves the original sort order of\n * equal elements. The iteratees are invoked with one argument: (value).\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Collection\n * @param {Array|Object} collection The collection to iterate over.\n * @param {...(Function|Function[])} [iteratees=[_.identity]]\n * The iteratees to sort by.\n * @returns {Array} Returns the new sorted array.\n * @example\n *\n * var users = [\n * { 'user': 'fred', 'age': 48 },\n * { 'user': 'barney', 'age': 36 },\n * { 'user': 'fred', 'age': 30 },\n * { 'user': 'barney', 'age': 34 }\n * ];\n *\n * _.sortBy(users, [function(o) { return o.user; }]);\n * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 30]]\n *\n * _.sortBy(users, ['user', 'age']);\n * // => objects for [['barney', 34], ['barney', 36], ['fred', 30], ['fred', 48]]\n */\nvar sortBy = baseRest(function(collection, iteratees) {\n if (collection == null) {\n return [];\n }\n var length = iteratees.length;\n if (length > 1 && isIterateeCall(collection, iteratees[0], iteratees[1])) {\n iteratees = [];\n } else if (length > 2 && isIterateeCall(iteratees[0], iteratees[1], iteratees[2])) {\n iteratees = [iteratees[0]];\n }\n return baseOrderBy(collection, baseFlatten(iteratees, 1), []);\n});\n\nexport default sortBy;\n","import Set from './_Set.js';\nimport noop from './noop.js';\nimport setToArray from './_setToArray.js';\n\n/** Used as references for various `Number` constants. */\nvar INFINITY = 1 / 0;\n\n/**\n * Creates a set object of `values`.\n *\n * @private\n * @param {Array} values The values to add to the set.\n * @returns {Object} Returns the new set.\n */\nvar createSet = !(Set && (1 / setToArray(new Set([,-0]))[1]) == INFINITY) ? noop : function(values) {\n return new Set(values);\n};\n\nexport default createSet;\n","import SetCache from './_SetCache.js';\nimport arrayIncludes from './_arrayIncludes.js';\nimport arrayIncludesWith from './_arrayIncludesWith.js';\nimport cacheHas from './_cacheHas.js';\nimport createSet from './_createSet.js';\nimport setToArray from './_setToArray.js';\n\n/** Used as the size to enable large array optimizations. */\nvar LARGE_ARRAY_SIZE = 200;\n\n/**\n * The base implementation of `_.uniqBy` without support for iteratee shorthands.\n *\n * @private\n * @param {Array} array The array to inspect.\n * @param {Function} [iteratee] The iteratee invoked per element.\n * @param {Function} [comparator] The comparator invoked per element.\n * @returns {Array} Returns the new duplicate free array.\n */\nfunction baseUniq(array, iteratee, comparator) {\n var index = -1,\n includes = arrayIncludes,\n length = array.length,\n isCommon = true,\n result = [],\n seen = result;\n\n if (comparator) {\n isCommon = false;\n includes = arrayIncludesWith;\n }\n else if (length >= LARGE_ARRAY_SIZE) {\n var set = iteratee ? null : createSet(array);\n if (set) {\n return setToArray(set);\n }\n isCommon = false;\n includes = cacheHas;\n seen = new SetCache;\n }\n else {\n seen = iteratee ? [] : result;\n }\n outer:\n while (++index < length) {\n var value = array[index],\n computed = iteratee ? iteratee(value) : value;\n\n value = (comparator || value !== 0) ? value : 0;\n if (isCommon && computed === computed) {\n var seenIndex = seen.length;\n while (seenIndex--) {\n if (seen[seenIndex] === computed) {\n continue outer;\n }\n }\n if (iteratee) {\n seen.push(computed);\n }\n result.push(value);\n }\n else if (!includes(seen, computed, comparator)) {\n if (seen !== result) {\n seen.push(computed);\n }\n result.push(value);\n }\n }\n return result;\n}\n\nexport default baseUniq;\n","import baseUniq from './_baseUniq.js';\n\n/**\n * Creates a duplicate-free version of an array, using\n * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)\n * for equality comparisons, in which only the first occurrence of each element\n * is kept. The order of result values is determined by the order they occur\n * in the array.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Array\n * @param {Array} array The array to inspect.\n * @returns {Array} Returns the new duplicate free array.\n * @example\n *\n * _.uniq([2, 1, 2]);\n * // => [2, 1]\n */\nfunction uniq(array) {\n return (array && array.length) ? baseUniq(array) : [];\n}\n\nexport default uniq;\n","import baseUniq from './_baseUniq.js';\n\n/**\n * This method is like `_.uniq` except that it accepts `comparator` which\n * is invoked to compare elements of `array`. The order of result values is\n * determined by the order they occur in the array.The comparator is invoked\n * with two arguments: (arrVal, othVal).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Array\n * @param {Array} array The array to inspect.\n * @param {Function} [comparator] The comparator invoked per element.\n * @returns {Array} Returns the new duplicate free array.\n * @example\n *\n * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 2 }];\n *\n * _.uniqWith(objects, _.isEqual);\n * // => [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }]\n */\nfunction uniqWith(array, comparator) {\n comparator = typeof comparator == 'function' ? comparator : undefined;\n return (array && array.length) ? baseUniq(array, undefined, comparator) : [];\n}\n\nexport default uniqWith;\n","import baseDifference from './_baseDifference.js';\nimport baseRest from './_baseRest.js';\nimport isArrayLikeObject from './isArrayLikeObject.js';\n\n/**\n * Creates an array excluding all given values using\n * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)\n * for equality comparisons.\n *\n * **Note:** Unlike `_.pull`, this method returns a new array.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Array\n * @param {Array} array The array to inspect.\n * @param {...*} [values] The values to exclude.\n * @returns {Array} Returns the new array of filtered values.\n * @see _.difference, _.xor\n * @example\n *\n * _.without([2, 1, 2, 3], 1, 2);\n * // => [3]\n */\nvar without = baseRest(function(array, values) {\n return isArrayLikeObject(array)\n ? baseDifference(array, values)\n : [];\n});\n\nexport default without;\n","'use strict'\n\nmodule.exports = stringify\n\nvar indentation = ''\n// eslint-disable-next-line\nconst strEscapeSequencesRegExp = /[\\x00-\\x1f\\x22\\x5c]/\n// eslint-disable-next-line\nconst strEscapeSequencesReplacer = /[\\x00-\\x1f\\x22\\x5c]/g\n\n// Escaped special characters. Use empty strings to fill up unused entries.\nconst meta = [\n '\\\\u0000', '\\\\u0001', '\\\\u0002', '\\\\u0003', '\\\\u0004',\n '\\\\u0005', '\\\\u0006', '\\\\u0007', '\\\\b', '\\\\t',\n '\\\\n', '\\\\u000b', '\\\\f', '\\\\r', '\\\\u000e',\n '\\\\u000f', '\\\\u0010', '\\\\u0011', '\\\\u0012', '\\\\u0013',\n '\\\\u0014', '\\\\u0015', '\\\\u0016', '\\\\u0017', '\\\\u0018',\n '\\\\u0019', '\\\\u001a', '\\\\u001b', '\\\\u001c', '\\\\u001d',\n '\\\\u001e', '\\\\u001f', '', '', '\\\\\"',\n '', '', '', '', '', '', '', '', '', '',\n '', '', '', '', '', '', '', '', '', '',\n '', '', '', '', '', '', '', '', '', '',\n '', '', '', '', '', '', '', '', '', '',\n '', '', '', '', '', '', '', '', '', '',\n '', '', '', '', '', '', '', '\\\\\\\\'\n]\n\nfunction escapeFn (str) {\n return meta[str.charCodeAt(0)]\n}\n\n// Escape control characters, double quotes and the backslash.\n// Note: it is faster to run this only once for a big string instead of only for\n// the parts that it is necessary for. But this is only true if we do not add\n// extra indentation to the string before.\nfunction strEscape (str) {\n // Some magic numbers that worked out fine while benchmarking with v8 6.0\n if (str.length < 5000 && !strEscapeSequencesRegExp.test(str)) {\n return str\n }\n if (str.length > 100) {\n return str.replace(strEscapeSequencesReplacer, escapeFn)\n }\n var result = ''\n var last = 0\n for (var i = 0; i < str.length; i++) {\n const point = str.charCodeAt(i)\n if (point === 34 || point === 92 || point < 32) {\n if (last === i) {\n result += meta[point]\n } else {\n result += `${str.slice(last, i)}${meta[point]}`\n }\n last = i + 1\n }\n }\n if (last === 0) {\n result = str\n } else if (last !== i) {\n result += str.slice(last)\n }\n return result\n}\n\n// Full version: supports all options\nfunction stringifyFullFn (key, parent, stack, replacer, indent) {\n var i, res, join\n const originalIndentation = indentation\n var value = parent[key]\n\n if (typeof value === 'object' && value !== null && typeof value.toJSON === 'function') {\n value = value.toJSON(key)\n }\n value = replacer.call(parent, key, value)\n\n switch (typeof value) {\n case 'object':\n if (value === null) {\n return 'null'\n }\n for (i = 0; i < stack.length; i++) {\n if (stack[i] === value) {\n return '\"[Circular]\"'\n }\n }\n if (Array.isArray(value)) {\n if (value.length === 0) {\n return '[]'\n }\n stack.push(value)\n res = '['\n indentation += indent\n res += `\\n${indentation}`\n join = `,\\n${indentation}`\n // Use null as placeholder for non-JSON values.\n for (i = 0; i < value.length - 1; i++) {\n const tmp = stringifyFullFn(i, value, stack, replacer, indent)\n res += tmp !== undefined ? tmp : 'null'\n res += join\n }\n const tmp = stringifyFullFn(i, value, stack, replacer, indent)\n res += tmp !== undefined ? tmp : 'null'\n if (indentation !== '') {\n res += `\\n${originalIndentation}`\n }\n res += ']'\n stack.pop()\n indentation = originalIndentation\n return res\n }\n\n var keys = insertSort(Object.keys(value))\n if (keys.length === 0) {\n return '{}'\n }\n stack.push(value)\n res = '{'\n indentation += indent\n res += `\\n${indentation}`\n join = `,\\n${indentation}`\n var separator = ''\n for (i = 0; i < keys.length; i++) {\n key = keys[i]\n const tmp = stringifyFullFn(key, value, stack, replacer, indent)\n if (tmp !== undefined) {\n res += `${separator}\"${strEscape(key)}\": ${tmp}`\n separator = join\n }\n }\n if (separator !== '') {\n res += `\\n${originalIndentation}`\n } else {\n res = '{'\n }\n res += '}'\n stack.pop()\n indentation = originalIndentation\n return res\n case 'string':\n return `\"${strEscape(value)}\"`\n case 'number':\n // JSON numbers must be finite. Encode non-finite numbers as null.\n return isFinite(value) ? String(value) : 'null'\n case 'boolean':\n return value === true ? 'true' : 'false'\n }\n}\n\nfunction stringifyFullArr (key, value, stack, replacer, indent) {\n var i, res, join\n const originalIndentation = indentation\n\n if (typeof value === 'object' && value !== null && typeof value.toJSON === 'function') {\n value = value.toJSON(key)\n }\n\n switch (typeof value) {\n case 'object':\n if (value === null) {\n return 'null'\n }\n for (i = 0; i < stack.length; i++) {\n if (stack[i] === value) {\n return '\"[Circular]\"'\n }\n }\n if (Array.isArray(value)) {\n if (value.length === 0) {\n return '[]'\n }\n stack.push(value)\n res = '['\n indentation += indent\n res += `\\n${indentation}`\n join = `,\\n${indentation}`\n // Use null as placeholder for non-JSON values.\n for (i = 0; i < value.length - 1; i++) {\n const tmp = stringifyFullArr(i, value[i], stack, replacer, indent)\n res += tmp !== undefined ? tmp : 'null'\n res += join\n }\n const tmp = stringifyFullArr(i, value[i], stack, replacer, indent)\n res += tmp !== undefined ? tmp : 'null'\n if (indentation !== '') {\n res += `\\n${originalIndentation}`\n }\n res += ']'\n stack.pop()\n indentation = originalIndentation\n return res\n }\n\n if (replacer.length === 0) {\n return '{}'\n }\n stack.push(value)\n res = '{'\n indentation += indent\n res += `\\n${indentation}`\n join = `,\\n${indentation}`\n var separator = ''\n for (i = 0; i < replacer.length; i++) {\n if (typeof replacer[i] === 'string' || typeof replacer[i] === 'number') {\n key = replacer[i]\n const tmp = stringifyFullArr(key, value[key], stack, replacer, indent)\n if (tmp !== undefined) {\n res += `${separator}\"${strEscape(key)}\": ${tmp}`\n separator = join\n }\n }\n }\n if (separator !== '') {\n res += `\\n${originalIndentation}`\n } else {\n res = '{'\n }\n res += '}'\n stack.pop()\n indentation = originalIndentation\n return res\n case 'string':\n return `\"${strEscape(value)}\"`\n case 'number':\n // JSON numbers must be finite. Encode non-finite numbers as null.\n return isFinite(value) ? String(value) : 'null'\n case 'boolean':\n return value === true ? 'true' : 'false'\n }\n}\n\n// Supports only the spacer option\nfunction stringifyIndent (key, value, stack, indent) {\n var i, res, join\n const originalIndentation = indentation\n\n switch (typeof value) {\n case 'object':\n if (value === null) {\n return 'null'\n }\n if (typeof value.toJSON === 'function') {\n value = value.toJSON(key)\n // Prevent calling `toJSON` again.\n if (typeof value !== 'object') {\n return stringifyIndent(key, value, stack, indent)\n }\n if (value === null) {\n return 'null'\n }\n }\n for (i = 0; i < stack.length; i++) {\n if (stack[i] === value) {\n return '\"[Circular]\"'\n }\n }\n\n if (Array.isArray(value)) {\n if (value.length === 0) {\n return '[]'\n }\n stack.push(value)\n res = '['\n indentation += indent\n res += `\\n${indentation}`\n join = `,\\n${indentation}`\n // Use null as placeholder for non-JSON values.\n for (i = 0; i < value.length - 1; i++) {\n const tmp = stringifyIndent(i, value[i], stack, indent)\n res += tmp !== undefined ? tmp : 'null'\n res += join\n }\n const tmp = stringifyIndent(i, value[i], stack, indent)\n res += tmp !== undefined ? tmp : 'null'\n if (indentation !== '') {\n res += `\\n${originalIndentation}`\n }\n res += ']'\n stack.pop()\n indentation = originalIndentation\n return res\n }\n\n var keys = insertSort(Object.keys(value))\n if (keys.length === 0) {\n return '{}'\n }\n stack.push(value)\n res = '{'\n indentation += indent\n res += `\\n${indentation}`\n join = `,\\n${indentation}`\n var separator = ''\n for (i = 0; i < keys.length; i++) {\n key = keys[i]\n const tmp = stringifyIndent(key, value[key], stack, indent)\n if (tmp !== undefined) {\n res += `${separator}\"${strEscape(key)}\": ${tmp}`\n separator = join\n }\n }\n if (separator !== '') {\n res += `\\n${originalIndentation}`\n } else {\n res = '{'\n }\n res += '}'\n stack.pop()\n indentation = originalIndentation\n return res\n case 'string':\n return `\"${strEscape(value)}\"`\n case 'number':\n // JSON numbers must be finite. Encode non-finite numbers as null.\n return isFinite(value) ? String(value) : 'null'\n case 'boolean':\n return value === true ? 'true' : 'false'\n }\n}\n\n// Supports only the replacer option\nfunction stringifyReplacerArr (key, value, stack, replacer) {\n var i, res\n // If the value has a toJSON method, call it to obtain a replacement value.\n if (typeof value === 'object' && value !== null && typeof value.toJSON === 'function') {\n value = value.toJSON(key)\n }\n\n switch (typeof value) {\n case 'object':\n if (value === null) {\n return 'null'\n }\n for (i = 0; i < stack.length; i++) {\n if (stack[i] === value) {\n return '\"[Circular]\"'\n }\n }\n if (Array.isArray(value)) {\n if (value.length === 0) {\n return '[]'\n }\n stack.push(value)\n res = '['\n // Use null as placeholder for non-JSON values.\n for (i = 0; i < value.length - 1; i++) {\n const tmp = stringifyReplacerArr(i, value[i], stack, replacer)\n res += tmp !== undefined ? tmp : 'null'\n res += ','\n }\n const tmp = stringifyReplacerArr(i, value[i], stack, replacer)\n res += tmp !== undefined ? tmp : 'null'\n res += ']'\n stack.pop()\n return res\n }\n\n if (replacer.length === 0) {\n return '{}'\n }\n stack.push(value)\n res = '{'\n var separator = ''\n for (i = 0; i < replacer.length; i++) {\n if (typeof replacer[i] === 'string' || typeof replacer[i] === 'number') {\n key = replacer[i]\n const tmp = stringifyReplacerArr(key, value[key], stack, replacer)\n if (tmp !== undefined) {\n res += `${separator}\"${strEscape(key)}\":${tmp}`\n separator = ','\n }\n }\n }\n res += '}'\n stack.pop()\n return res\n case 'string':\n return `\"${strEscape(value)}\"`\n case 'number':\n // JSON numbers must be finite. Encode non-finite numbers as null.\n return isFinite(value) ? String(value) : 'null'\n case 'boolean':\n return value === true ? 'true' : 'false'\n }\n}\n\nfunction stringifyReplacerFn (key, parent, stack, replacer) {\n var i, res\n var value = parent[key]\n // If the value has a toJSON method, call it to obtain a replacement value.\n if (typeof value === 'object' && value !== null && typeof value.toJSON === 'function') {\n value = value.toJSON(key)\n }\n value = replacer.call(parent, key, value)\n\n switch (typeof value) {\n case 'object':\n if (value === null) {\n return 'null'\n }\n for (i = 0; i < stack.length; i++) {\n if (stack[i] === value) {\n return '\"[Circular]\"'\n }\n }\n if (Array.isArray(value)) {\n if (value.length === 0) {\n return '[]'\n }\n stack.push(value)\n res = '['\n // Use null as placeholder for non-JSON values.\n for (i = 0; i < value.length - 1; i++) {\n const tmp = stringifyReplacerFn(i, value, stack, replacer)\n res += tmp !== undefined ? tmp : 'null'\n res += ','\n }\n const tmp = stringifyReplacerFn(i, value, stack, replacer)\n res += tmp !== undefined ? tmp : 'null'\n res += ']'\n stack.pop()\n return res\n }\n\n var keys = insertSort(Object.keys(value))\n if (keys.length === 0) {\n return '{}'\n }\n stack.push(value)\n res = '{'\n var separator = ''\n for (i = 0; i < keys.length; i++) {\n key = keys[i]\n const tmp = stringifyReplacerFn(key, value, stack, replacer)\n if (tmp !== undefined) {\n res += `${separator}\"${strEscape(key)}\":${tmp}`\n separator = ','\n }\n }\n res += '}'\n stack.pop()\n return res\n case 'string':\n return `\"${strEscape(value)}\"`\n case 'number':\n // JSON numbers must be finite. Encode non-finite numbers as null.\n return isFinite(value) ? String(value) : 'null'\n case 'boolean':\n return value === true ? 'true' : 'false'\n }\n}\n\n// Simple without any options\nfunction stringifySimple (key, value, stack) {\n var i, res\n switch (typeof value) {\n case 'object':\n if (value === null) {\n return 'null'\n }\n if (typeof value.toJSON === 'function') {\n value = value.toJSON(key)\n // Prevent calling `toJSON` again\n if (typeof value !== 'object') {\n return stringifySimple(key, value, stack)\n }\n if (value === null) {\n return 'null'\n }\n }\n for (i = 0; i < stack.length; i++) {\n if (stack[i] === value) {\n return '\"[Circular]\"'\n }\n }\n\n if (Array.isArray(value)) {\n if (value.length === 0) {\n return '[]'\n }\n stack.push(value)\n res = '['\n // Use null as placeholder for non-JSON values.\n for (i = 0; i < value.length - 1; i++) {\n const tmp = stringifySimple(i, value[i], stack)\n res += tmp !== undefined ? tmp : 'null'\n res += ','\n }\n const tmp = stringifySimple(i, value[i], stack)\n res += tmp !== undefined ? tmp : 'null'\n res += ']'\n stack.pop()\n return res\n }\n\n var keys = insertSort(Object.keys(value))\n if (keys.length === 0) {\n return '{}'\n }\n stack.push(value)\n var separator = ''\n res = '{'\n for (i = 0; i < keys.length; i++) {\n key = keys[i]\n const tmp = stringifySimple(key, value[key], stack)\n if (tmp !== undefined) {\n res += `${separator}\"${strEscape(key)}\":${tmp}`\n separator = ','\n }\n }\n res += '}'\n stack.pop()\n return res\n case 'string':\n return `\"${strEscape(value)}\"`\n case 'number':\n // JSON numbers must be finite. Encode non-finite numbers as null.\n // Convert the numbers implicit to a string instead of explicit.\n return isFinite(value) ? String(value) : 'null'\n case 'boolean':\n return value === true ? 'true' : 'false'\n }\n}\n\nfunction insertSort (arr) {\n for (var i = 1; i < arr.length; i++) {\n const tmp = arr[i]\n var j = i\n while (j !== 0 && arr[j - 1] > tmp) {\n arr[j] = arr[j - 1]\n j--\n }\n arr[j] = tmp\n }\n\n return arr\n}\n\nfunction stringify (value, replacer, spacer) {\n var i\n var indent = ''\n indentation = ''\n\n if (arguments.length > 1) {\n // If the spacer parameter is a number, make an indent string containing that\n // many spaces.\n if (typeof spacer === 'number') {\n for (i = 0; i < spacer; i += 1) {\n indent += ' '\n }\n // If the spacer parameter is a string, it will be used as the indent string.\n } else if (typeof spacer === 'string') {\n indent = spacer\n }\n if (indent !== '') {\n if (replacer !== undefined && replacer !== null) {\n if (typeof replacer === 'function') {\n return stringifyFullFn('', { '': value }, [], replacer, indent)\n }\n if (Array.isArray(replacer)) {\n return stringifyFullArr('', value, [], replacer, indent)\n }\n }\n return stringifyIndent('', value, [], indent)\n }\n if (typeof replacer === 'function') {\n return stringifyReplacerFn('', { '': value }, [], replacer)\n }\n if (Array.isArray(replacer)) {\n return stringifyReplacerArr('', value, [], replacer)\n }\n }\n return stringifySimple('', value, [])\n}\n","'use strict'\n\nconst stringify = require('./stable')\n\nmodule.exports = stringify\nstringify.default = stringify\n","/******************************************************************************\nCopyright (c) Microsoft Corporation.\n\nPermission to use, copy, modify, and/or distribute this software for any\npurpose with or without fee is hereby granted.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH\nREGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY\nAND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,\nINDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM\nLOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR\nOTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR\nPERFORMANCE OF THIS SOFTWARE.\n***************************************************************************** */\n/* global Reflect, Promise, SuppressedError, Symbol, Iterator */\n\nvar extendStatics = function(d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };\n return extendStatics(d, b);\n};\n\nexport function __extends(d, b) {\n if (typeof b !== \"function\" && b !== null)\n throw new TypeError(\"Class extends value \" + String(b) + \" is not a constructor or null\");\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n}\n\nexport var __assign = function() {\n __assign = Object.assign || function __assign(t) {\n for (var s, i = 1, n = arguments.length; i < n; i++) {\n s = arguments[i];\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];\n }\n return t;\n }\n return __assign.apply(this, arguments);\n}\n\nexport function __rest(s, e) {\n var t = {};\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)\n t[p] = s[p];\n if (s != null && typeof Object.getOwnPropertySymbols === \"function\")\n for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {\n if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))\n t[p[i]] = s[p[i]];\n }\n return t;\n}\n\nexport function __decorate(decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n}\n\nexport function __param(paramIndex, decorator) {\n return function (target, key) { decorator(target, key, paramIndex); }\n}\n\nexport function __esDecorate(ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {\n function accept(f) { if (f !== void 0 && typeof f !== \"function\") throw new TypeError(\"Function expected\"); return f; }\n var kind = contextIn.kind, key = kind === \"getter\" ? \"get\" : kind === \"setter\" ? \"set\" : \"value\";\n var target = !descriptorIn && ctor ? contextIn[\"static\"] ? ctor : ctor.prototype : null;\n var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});\n var _, done = false;\n for (var i = decorators.length - 1; i >= 0; i--) {\n var context = {};\n for (var p in contextIn) context[p] = p === \"access\" ? {} : contextIn[p];\n for (var p in contextIn.access) context.access[p] = contextIn.access[p];\n context.addInitializer = function (f) { if (done) throw new TypeError(\"Cannot add initializers after decoration has completed\"); extraInitializers.push(accept(f || null)); };\n var result = (0, decorators[i])(kind === \"accessor\" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);\n if (kind === \"accessor\") {\n if (result === void 0) continue;\n if (result === null || typeof result !== \"object\") throw new TypeError(\"Object expected\");\n if (_ = accept(result.get)) descriptor.get = _;\n if (_ = accept(result.set)) descriptor.set = _;\n if (_ = accept(result.init)) initializers.unshift(_);\n }\n else if (_ = accept(result)) {\n if (kind === \"field\") initializers.unshift(_);\n else descriptor[key] = _;\n }\n }\n if (target) Object.defineProperty(target, contextIn.name, descriptor);\n done = true;\n};\n\nexport function __runInitializers(thisArg, initializers, value) {\n var useValue = arguments.length > 2;\n for (var i = 0; i < initializers.length; i++) {\n value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);\n }\n return useValue ? value : void 0;\n};\n\nexport function __propKey(x) {\n return typeof x === \"symbol\" ? x : \"\".concat(x);\n};\n\nexport function __setFunctionName(f, name, prefix) {\n if (typeof name === \"symbol\") name = name.description ? \"[\".concat(name.description, \"]\") : \"\";\n return Object.defineProperty(f, \"name\", { configurable: true, value: prefix ? \"\".concat(prefix, \" \", name) : name });\n};\n\nexport function __metadata(metadataKey, metadataValue) {\n if (typeof Reflect === \"object\" && typeof Reflect.metadata === \"function\") return Reflect.metadata(metadataKey, metadataValue);\n}\n\nexport function __awaiter(thisArg, _arguments, P, generator) {\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n step((generator = generator.apply(thisArg, _arguments || [])).next());\n });\n}\n\nexport function __generator(thisArg, body) {\n var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === \"function\" ? Iterator : Object).prototype);\n return g.next = verb(0), g[\"throw\"] = verb(1), g[\"return\"] = verb(2), typeof Symbol === \"function\" && (g[Symbol.iterator] = function() { return this; }), g;\n function verb(n) { return function (v) { return step([n, v]); }; }\n function step(op) {\n if (f) throw new TypeError(\"Generator is already executing.\");\n while (g && (g = 0, op[0] && (_ = 0)), _) try {\n if (f = 1, y && (t = op[0] & 2 ? y[\"return\"] : op[0] ? y[\"throw\"] || ((t = y[\"return\"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;\n if (y = 0, t) op = [op[0] & 2, t.value];\n switch (op[0]) {\n case 0: case 1: t = op; break;\n case 4: _.label++; return { value: op[1], done: false };\n case 5: _.label++; y = op[1]; op = [0]; continue;\n case 7: op = _.ops.pop(); _.trys.pop(); continue;\n default:\n if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }\n if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }\n if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }\n if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }\n if (t[2]) _.ops.pop();\n _.trys.pop(); continue;\n }\n op = body.call(thisArg, _);\n } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }\n if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };\n }\n}\n\nexport var __createBinding = Object.create ? (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n var desc = Object.getOwnPropertyDescriptor(m, k);\n if (!desc || (\"get\" in desc ? !m.__esModule : desc.writable || desc.configurable)) {\n desc = { enumerable: true, get: function() { return m[k]; } };\n }\n Object.defineProperty(o, k2, desc);\n}) : (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n o[k2] = m[k];\n});\n\nexport function __exportStar(m, o) {\n for (var p in m) if (p !== \"default\" && !Object.prototype.hasOwnProperty.call(o, p)) __createBinding(o, m, p);\n}\n\nexport function __values(o) {\n var s = typeof Symbol === \"function\" && Symbol.iterator, m = s && o[s], i = 0;\n if (m) return m.call(o);\n if (o && typeof o.length === \"number\") return {\n next: function () {\n if (o && i >= o.length) o = void 0;\n return { value: o && o[i++], done: !o };\n }\n };\n throw new TypeError(s ? \"Object is not iterable.\" : \"Symbol.iterator is not defined.\");\n}\n\nexport function __read(o, n) {\n var m = typeof Symbol === \"function\" && o[Symbol.iterator];\n if (!m) return o;\n var i = m.call(o), r, ar = [], e;\n try {\n while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);\n }\n catch (error) { e = { error: error }; }\n finally {\n try {\n if (r && !r.done && (m = i[\"return\"])) m.call(i);\n }\n finally { if (e) throw e.error; }\n }\n return ar;\n}\n\n/** @deprecated */\nexport function __spread() {\n for (var ar = [], i = 0; i < arguments.length; i++)\n ar = ar.concat(__read(arguments[i]));\n return ar;\n}\n\n/** @deprecated */\nexport function __spreadArrays() {\n for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;\n for (var r = Array(s), k = 0, i = 0; i < il; i++)\n for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)\n r[k] = a[j];\n return r;\n}\n\nexport function __spreadArray(to, from, pack) {\n if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {\n if (ar || !(i in from)) {\n if (!ar) ar = Array.prototype.slice.call(from, 0, i);\n ar[i] = from[i];\n }\n }\n return to.concat(ar || Array.prototype.slice.call(from));\n}\n\nexport function __await(v) {\n return this instanceof __await ? (this.v = v, this) : new __await(v);\n}\n\nexport function __asyncGenerator(thisArg, _arguments, generator) {\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\n var g = generator.apply(thisArg, _arguments || []), i, q = [];\n return i = Object.create((typeof AsyncIterator === \"function\" ? AsyncIterator : Object).prototype), verb(\"next\"), verb(\"throw\"), verb(\"return\", awaitReturn), i[Symbol.asyncIterator] = function () { return this; }, i;\n function awaitReturn(f) { return function (v) { return Promise.resolve(v).then(f, reject); }; }\n function verb(n, f) { if (g[n]) { i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; if (f) i[n] = f(i[n]); } }\n function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }\n function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }\n function fulfill(value) { resume(\"next\", value); }\n function reject(value) { resume(\"throw\", value); }\n function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }\n}\n\nexport function __asyncDelegator(o) {\n var i, p;\n return i = {}, verb(\"next\"), verb(\"throw\", function (e) { throw e; }), verb(\"return\"), i[Symbol.iterator] = function () { return this; }, i;\n function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: false } : f ? f(v) : v; } : f; }\n}\n\nexport function __asyncValues(o) {\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\n var m = o[Symbol.asyncIterator], i;\n return m ? m.call(o) : (o = typeof __values === \"function\" ? __values(o) : o[Symbol.iterator](), i = {}, verb(\"next\"), verb(\"throw\"), verb(\"return\"), i[Symbol.asyncIterator] = function () { return this; }, i);\n function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }\n function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }\n}\n\nexport function __makeTemplateObject(cooked, raw) {\n if (Object.defineProperty) { Object.defineProperty(cooked, \"raw\", { value: raw }); } else { cooked.raw = raw; }\n return cooked;\n};\n\nvar __setModuleDefault = Object.create ? (function(o, v) {\n Object.defineProperty(o, \"default\", { enumerable: true, value: v });\n}) : function(o, v) {\n o[\"default\"] = v;\n};\n\nvar ownKeys = function(o) {\n ownKeys = Object.getOwnPropertyNames || function (o) {\n var ar = [];\n for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;\n return ar;\n };\n return ownKeys(o);\n};\n\nexport function __importStar(mod) {\n if (mod && mod.__esModule) return mod;\n var result = {};\n if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== \"default\") __createBinding(result, mod, k[i]);\n __setModuleDefault(result, mod);\n return result;\n}\n\nexport function __importDefault(mod) {\n return (mod && mod.__esModule) ? mod : { default: mod };\n}\n\nexport function __classPrivateFieldGet(receiver, state, kind, f) {\n if (kind === \"a\" && !f) throw new TypeError(\"Private accessor was defined without a getter\");\n if (typeof state === \"function\" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError(\"Cannot read private member from an object whose class did not declare it\");\n return kind === \"m\" ? f : kind === \"a\" ? f.call(receiver) : f ? f.value : state.get(receiver);\n}\n\nexport function __classPrivateFieldSet(receiver, state, value, kind, f) {\n if (kind === \"m\") throw new TypeError(\"Private method is not writable\");\n if (kind === \"a\" && !f) throw new TypeError(\"Private accessor was defined without a setter\");\n if (typeof state === \"function\" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError(\"Cannot write private member to an object whose class did not declare it\");\n return (kind === \"a\" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;\n}\n\nexport function __classPrivateFieldIn(state, receiver) {\n if (receiver === null || (typeof receiver !== \"object\" && typeof receiver !== \"function\")) throw new TypeError(\"Cannot use 'in' operator on non-object\");\n return typeof state === \"function\" ? receiver === state : state.has(receiver);\n}\n\nexport function __addDisposableResource(env, value, async) {\n if (value !== null && value !== void 0) {\n if (typeof value !== \"object\" && typeof value !== \"function\") throw new TypeError(\"Object expected.\");\n var dispose, inner;\n if (async) {\n if (!Symbol.asyncDispose) throw new TypeError(\"Symbol.asyncDispose is not defined.\");\n dispose = value[Symbol.asyncDispose];\n }\n if (dispose === void 0) {\n if (!Symbol.dispose) throw new TypeError(\"Symbol.dispose is not defined.\");\n dispose = value[Symbol.dispose];\n if (async) inner = dispose;\n }\n if (typeof dispose !== \"function\") throw new TypeError(\"Object not disposable.\");\n if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };\n env.stack.push({ value: value, dispose: dispose, async: async });\n }\n else if (async) {\n env.stack.push({ async: true });\n }\n return value;\n}\n\nvar _SuppressedError = typeof SuppressedError === \"function\" ? SuppressedError : function (error, suppressed, message) {\n var e = new Error(message);\n return e.name = \"SuppressedError\", e.error = error, e.suppressed = suppressed, e;\n};\n\nexport function __disposeResources(env) {\n function fail(e) {\n env.error = env.hasError ? new _SuppressedError(e, env.error, \"An error was suppressed during disposal.\") : e;\n env.hasError = true;\n }\n var r, s = 0;\n function next() {\n while (r = env.stack.pop()) {\n try {\n if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next);\n if (r.dispose) {\n var result = r.dispose.call(r.value);\n if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) { fail(e); return next(); });\n }\n else s |= 1;\n }\n catch (e) {\n fail(e);\n }\n }\n if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve();\n if (env.hasError) throw env.error;\n }\n return next();\n}\n\nexport function __rewriteRelativeImportExtension(path, preserveJsx) {\n if (typeof path === \"string\" && /^\\.\\.?\\//.test(path)) {\n return path.replace(/\\.(tsx)$|((?:\\.d)?)((?:\\.[^./]+?)?)\\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {\n return tsx ? preserveJsx ? \".jsx\" : \".js\" : d && (!ext || !cm) ? m : (d + ext + \".\" + cm.toLowerCase() + \"js\");\n });\n }\n return path;\n}\n\nexport default {\n __extends,\n __assign,\n __rest,\n __decorate,\n __param,\n __esDecorate,\n __runInitializers,\n __propKey,\n __setFunctionName,\n __metadata,\n __awaiter,\n __generator,\n __createBinding,\n __exportStar,\n __values,\n __read,\n __spread,\n __spreadArrays,\n __spreadArray,\n __await,\n __asyncGenerator,\n __asyncDelegator,\n __asyncValues,\n __makeTemplateObject,\n __importStar,\n __importDefault,\n __classPrivateFieldGet,\n __classPrivateFieldSet,\n __classPrivateFieldIn,\n __addDisposableResource,\n __disposeResources,\n __rewriteRelativeImportExtension,\n};\n",null,null,null,null,null,null,null,null,null,"/*!\n * EventEmitter v5.2.9 - git.io/ee\n * Unlicense - http://unlicense.org/\n * Oliver Caldwell - https://oli.me.uk/\n * @preserve\n */\n\n;(function (exports) {\n 'use strict';\n\n /**\n * Class for managing events.\n * Can be extended to provide event functionality in other classes.\n *\n * @class EventEmitter Manages event registering and emitting.\n */\n function EventEmitter() {}\n\n // Shortcuts to improve speed and size\n var proto = EventEmitter.prototype;\n var originalGlobalValue = exports.EventEmitter;\n\n /**\n * Finds the index of the listener for the event in its storage array.\n *\n * @param {Function[]} listeners Array of listeners to search through.\n * @param {Function} listener Method to look for.\n * @return {Number} Index of the specified listener, -1 if not found\n * @api private\n */\n function indexOfListener(listeners, listener) {\n var i = listeners.length;\n while (i--) {\n if (listeners[i].listener === listener) {\n return i;\n }\n }\n\n return -1;\n }\n\n /**\n * Alias a method while keeping the context correct, to allow for overwriting of target method.\n *\n * @param {String} name The name of the target method.\n * @return {Function} The aliased method\n * @api private\n */\n function alias(name) {\n return function aliasClosure() {\n return this[name].apply(this, arguments);\n };\n }\n\n /**\n * Returns the listener array for the specified event.\n * Will initialise the event object and listener arrays if required.\n * Will return an object if you use a regex search. The object contains keys for each matched event. So /ba[rz]/ might return an object containing bar and baz. But only if you have either defined them with defineEvent or added some listeners to them.\n * Each property in the object response is an array of listener functions.\n *\n * @param {String|RegExp} evt Name of the event to return the listeners from.\n * @return {Function[]|Object} All listener functions for the event.\n */\n proto.getListeners = function getListeners(evt) {\n var events = this._getEvents();\n var response;\n var key;\n\n // Return a concatenated array of all matching events if\n // the selector is a regular expression.\n if (evt instanceof RegExp) {\n response = {};\n for (key in events) {\n if (events.hasOwnProperty(key) && evt.test(key)) {\n response[key] = events[key];\n }\n }\n }\n else {\n response = events[evt] || (events[evt] = []);\n }\n\n return response;\n };\n\n /**\n * Takes a list of listener objects and flattens it into a list of listener functions.\n *\n * @param {Object[]} listeners Raw listener objects.\n * @return {Function[]} Just the listener functions.\n */\n proto.flattenListeners = function flattenListeners(listeners) {\n var flatListeners = [];\n var i;\n\n for (i = 0; i < listeners.length; i += 1) {\n flatListeners.push(listeners[i].listener);\n }\n\n return flatListeners;\n };\n\n /**\n * Fetches the requested listeners via getListeners but will always return the results inside an object. This is mainly for internal use but others may find it useful.\n *\n * @param {String|RegExp} evt Name of the event to return the listeners from.\n * @return {Object} All listener functions for an event in an object.\n */\n proto.getListenersAsObject = function getListenersAsObject(evt) {\n var listeners = this.getListeners(evt);\n var response;\n\n if (listeners instanceof Array) {\n response = {};\n response[evt] = listeners;\n }\n\n return response || listeners;\n };\n\n function isValidListener (listener) {\n if (typeof listener === 'function' || listener instanceof RegExp) {\n return true\n } else if (listener && typeof listener === 'object') {\n return isValidListener(listener.listener)\n } else {\n return false\n }\n }\n\n /**\n * Adds a listener function to the specified event.\n * The listener will not be added if it is a duplicate.\n * If the listener returns true then it will be removed after it is called.\n * If you pass a regular expression as the event name then the listener will be added to all events that match it.\n *\n * @param {String|RegExp} evt Name of the event to attach the listener to.\n * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling.\n * @return {Object} Current instance of EventEmitter for chaining.\n */\n proto.addListener = function addListener(evt, listener) {\n if (!isValidListener(listener)) {\n throw new TypeError('listener must be a function');\n }\n\n var listeners = this.getListenersAsObject(evt);\n var listenerIsWrapped = typeof listener === 'object';\n var key;\n\n for (key in listeners) {\n if (listeners.hasOwnProperty(key) && indexOfListener(listeners[key], listener) === -1) {\n listeners[key].push(listenerIsWrapped ? listener : {\n listener: listener,\n once: false\n });\n }\n }\n\n return this;\n };\n\n /**\n * Alias of addListener\n */\n proto.on = alias('addListener');\n\n /**\n * Semi-alias of addListener. It will add a listener that will be\n * automatically removed after its first execution.\n *\n * @param {String|RegExp} evt Name of the event to attach the listener to.\n * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling.\n * @return {Object} Current instance of EventEmitter for chaining.\n */\n proto.addOnceListener = function addOnceListener(evt, listener) {\n return this.addListener(evt, {\n listener: listener,\n once: true\n });\n };\n\n /**\n * Alias of addOnceListener.\n */\n proto.once = alias('addOnceListener');\n\n /**\n * Defines an event name. This is required if you want to use a regex to add a listener to multiple events at once. If you don't do this then how do you expect it to know what event to add to? Should it just add to every possible match for a regex? No. That is scary and bad.\n * You need to tell it what event names should be matched by a regex.\n *\n * @param {String} evt Name of the event to create.\n * @return {Object} Current instance of EventEmitter for chaining.\n */\n proto.defineEvent = function defineEvent(evt) {\n this.getListeners(evt);\n return this;\n };\n\n /**\n * Uses defineEvent to define multiple events.\n *\n * @param {String[]} evts An array of event names to define.\n * @return {Object} Current instance of EventEmitter for chaining.\n */\n proto.defineEvents = function defineEvents(evts) {\n for (var i = 0; i < evts.length; i += 1) {\n this.defineEvent(evts[i]);\n }\n return this;\n };\n\n /**\n * Removes a listener function from the specified event.\n * When passed a regular expression as the event name, it will remove the listener from all events that match it.\n *\n * @param {String|RegExp} evt Name of the event to remove the listener from.\n * @param {Function} listener Method to remove from the event.\n * @return {Object} Current instance of EventEmitter for chaining.\n */\n proto.removeListener = function removeListener(evt, listener) {\n var listeners = this.getListenersAsObject(evt);\n var index;\n var key;\n\n for (key in listeners) {\n if (listeners.hasOwnProperty(key)) {\n index = indexOfListener(listeners[key], listener);\n\n if (index !== -1) {\n listeners[key].splice(index, 1);\n }\n }\n }\n\n return this;\n };\n\n /**\n * Alias of removeListener\n */\n proto.off = alias('removeListener');\n\n /**\n * Adds listeners in bulk using the manipulateListeners method.\n * If you pass an object as the first argument you can add to multiple events at once. The object should contain key value pairs of events and listeners or listener arrays. You can also pass it an event name and an array of listeners to be added.\n * You can also pass it a regular expression to add the array of listeners to all events that match it.\n * Yeah, this function does quite a bit. That's probably a bad thing.\n *\n * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to add to multiple events at once.\n * @param {Function[]} [listeners] An optional array of listener functions to add.\n * @return {Object} Current instance of EventEmitter for chaining.\n */\n proto.addListeners = function addListeners(evt, listeners) {\n // Pass through to manipulateListeners\n return this.manipulateListeners(false, evt, listeners);\n };\n\n /**\n * Removes listeners in bulk using the manipulateListeners method.\n * If you pass an object as the first argument you can remove from multiple events at once. The object should contain key value pairs of events and listeners or listener arrays.\n * You can also pass it an event name and an array of listeners to be removed.\n * You can also pass it a regular expression to remove the listeners from all events that match it.\n *\n * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to remove from multiple events at once.\n * @param {Function[]} [listeners] An optional array of listener functions to remove.\n * @return {Object} Current instance of EventEmitter for chaining.\n */\n proto.removeListeners = function removeListeners(evt, listeners) {\n // Pass through to manipulateListeners\n return this.manipulateListeners(true, evt, listeners);\n };\n\n /**\n * Edits listeners in bulk. The addListeners and removeListeners methods both use this to do their job. You should really use those instead, this is a little lower level.\n * The first argument will determine if the listeners are removed (true) or added (false).\n * If you pass an object as the second argument you can add/remove from multiple events at once. The object should contain key value pairs of events and listeners or listener arrays.\n * You can also pass it an event name and an array of listeners to be added/removed.\n * You can also pass it a regular expression to manipulate the listeners of all events that match it.\n *\n * @param {Boolean} remove True if you want to remove listeners, false if you want to add.\n * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to add/remove from multiple events at once.\n * @param {Function[]} [listeners] An optional array of listener functions to add/remove.\n * @return {Object} Current instance of EventEmitter for chaining.\n */\n proto.manipulateListeners = function manipulateListeners(remove, evt, listeners) {\n var i;\n var value;\n var single = remove ? this.removeListener : this.addListener;\n var multiple = remove ? this.removeListeners : this.addListeners;\n\n // If evt is an object then pass each of its properties to this method\n if (typeof evt === 'object' && !(evt instanceof RegExp)) {\n for (i in evt) {\n if (evt.hasOwnProperty(i) && (value = evt[i])) {\n // Pass the single listener straight through to the singular method\n if (typeof value === 'function') {\n single.call(this, i, value);\n }\n else {\n // Otherwise pass back to the multiple function\n multiple.call(this, i, value);\n }\n }\n }\n }\n else {\n // So evt must be a string\n // And listeners must be an array of listeners\n // Loop over it and pass each one to the multiple method\n i = listeners.length;\n while (i--) {\n single.call(this, evt, listeners[i]);\n }\n }\n\n return this;\n };\n\n /**\n * Removes all listeners from a specified event.\n * If you do not specify an event then all listeners will be removed.\n * That means every event will be emptied.\n * You can also pass a regex to remove all events that match it.\n *\n * @param {String|RegExp} [evt] Optional name of the event to remove all listeners for. Will remove from every event if not passed.\n * @return {Object} Current instance of EventEmitter for chaining.\n */\n proto.removeEvent = function removeEvent(evt) {\n var type = typeof evt;\n var events = this._getEvents();\n var key;\n\n // Remove different things depending on the state of evt\n if (type === 'string') {\n // Remove all listeners for the specified event\n delete events[evt];\n }\n else if (evt instanceof RegExp) {\n // Remove all events matching the regex.\n for (key in events) {\n if (events.hasOwnProperty(key) && evt.test(key)) {\n delete events[key];\n }\n }\n }\n else {\n // Remove all listeners in all events\n delete this._events;\n }\n\n return this;\n };\n\n /**\n * Alias of removeEvent.\n *\n * Added to mirror the node API.\n */\n proto.removeAllListeners = alias('removeEvent');\n\n /**\n * Emits an event of your choice.\n * When emitted, every listener attached to that event will be executed.\n * If you pass the optional argument array then those arguments will be passed to every listener upon execution.\n * Because it uses `apply`, your array of arguments will be passed as if you wrote them out separately.\n * So they will not arrive within the array on the other side, they will be separate.\n * You can also pass a regular expression to emit to all events that match it.\n *\n * @param {String|RegExp} evt Name of the event to emit and execute listeners for.\n * @param {Array} [args] Optional array of arguments to be passed to each listener.\n * @return {Object} Current instance of EventEmitter for chaining.\n */\n proto.emitEvent = function emitEvent(evt, args) {\n var listenersMap = this.getListenersAsObject(evt);\n var listeners;\n var listener;\n var i;\n var key;\n var response;\n\n for (key in listenersMap) {\n if (listenersMap.hasOwnProperty(key)) {\n listeners = listenersMap[key].slice(0);\n\n for (i = 0; i < listeners.length; i++) {\n // If the listener returns true then it shall be removed from the event\n // The function is executed either with a basic call or an apply if there is an args array\n listener = listeners[i];\n\n if (listener.once === true) {\n this.removeListener(evt, listener.listener);\n }\n\n response = listener.listener.apply(this, args || []);\n\n if (response === this._getOnceReturnValue()) {\n this.removeListener(evt, listener.listener);\n }\n }\n }\n }\n\n return this;\n };\n\n /**\n * Alias of emitEvent\n */\n proto.trigger = alias('emitEvent');\n\n /**\n * Subtly different from emitEvent in that it will pass its arguments on to the listeners, as opposed to taking a single array of arguments to pass on.\n * As with emitEvent, you can pass a regex in place of the event name to emit to all events that match it.\n *\n * @param {String|RegExp} evt Name of the event to emit and execute listeners for.\n * @param {...*} Optional additional arguments to be passed to each listener.\n * @return {Object} Current instance of EventEmitter for chaining.\n */\n proto.emit = function emit(evt) {\n var args = Array.prototype.slice.call(arguments, 1);\n return this.emitEvent(evt, args);\n };\n\n /**\n * Sets the current value to check against when executing listeners. If a\n * listeners return value matches the one set here then it will be removed\n * after execution. This value defaults to true.\n *\n * @param {*} value The new value to check for when executing listeners.\n * @return {Object} Current instance of EventEmitter for chaining.\n */\n proto.setOnceReturnValue = function setOnceReturnValue(value) {\n this._onceReturnValue = value;\n return this;\n };\n\n /**\n * Fetches the current value to check against when executing listeners. If\n * the listeners return value matches this one then it should be removed\n * automatically. It will return true by default.\n *\n * @return {*|Boolean} The current value to check for or the default, true.\n * @api private\n */\n proto._getOnceReturnValue = function _getOnceReturnValue() {\n if (this.hasOwnProperty('_onceReturnValue')) {\n return this._onceReturnValue;\n }\n else {\n return true;\n }\n };\n\n /**\n * Fetches the events object and creates one if required.\n *\n * @return {Object} The events storage object.\n * @api private\n */\n proto._getEvents = function _getEvents() {\n return this._events || (this._events = {});\n };\n\n /**\n * Reverts the global {@link EventEmitter} to its previous value and returns a reference to this version.\n *\n * @return {Function} Non conflicting EventEmitter class.\n */\n EventEmitter.noConflict = function noConflict() {\n exports.EventEmitter = originalGlobalValue;\n return EventEmitter;\n };\n\n // Expose the class either via AMD, CommonJS or the global object\n if (typeof define === 'function' && define.amd) {\n define(function () {\n return EventEmitter;\n });\n }\n else if (typeof module === 'object' && module.exports){\n module.exports = EventEmitter;\n }\n else {\n exports.EventEmitter = EventEmitter;\n }\n}(typeof window !== 'undefined' ? window : this || {}));\n",null,null,null,"var isEqual = require('lodash/isEqual')\nvar sortBy = require('lodash/sortBy')\nvar uniq = require('lodash/uniq')\nvar uniqWith = require('lodash/uniqWith')\nvar defaults = require('lodash/defaults')\nvar intersectionWith = require('lodash/intersectionWith')\nvar isPlainObject = require('lodash/isPlainObject')\nvar isBoolean = require('lodash/isBoolean')\n\nvar normalizeArray = val => Array.isArray(val)\n ? val : [val]\nvar undef = val => val === undefined\nvar keys = obj => isPlainObject(obj) || Array.isArray(obj) ? Object.keys(obj) : []\nvar has = (obj, key) => obj.hasOwnProperty(key)\nvar stringArray = arr => sortBy(uniq(arr))\nvar undefEmpty = val => undef(val) || (Array.isArray(val) && val.length === 0)\nvar keyValEqual = (a, b, key, compare) => b && has(b, key) && a && has(a, key) && compare(a[key], b[key])\nvar undefAndZero = (a, b) => (undef(a) && b === 0) || (undef(b) && a === 0) || isEqual(a, b)\nvar falseUndefined = (a, b) => (undef(a) && b === false) || (undef(b) && a === false) || isEqual(a, b)\nvar emptySchema = schema => undef(schema) || isEqual(schema, {}) || schema === true\nvar emptyObjUndef = schema => undef(schema) || isEqual(schema, {})\nvar isSchema = val => undef(val) || isPlainObject(val) || val === true || val === false\n\nfunction undefArrayEqual(a, b) {\n if (undefEmpty(a) && undefEmpty(b)) {\n return true\n } else {\n return isEqual(stringArray(a), stringArray(b))\n }\n}\n\nfunction unsortedNormalizedArray(a, b) {\n a = normalizeArray(a)\n b = normalizeArray(b)\n return isEqual(stringArray(a), stringArray(b))\n}\n\nfunction schemaGroup(a, b, key, compare) {\n var allProps = uniq(keys(a).concat(keys(b)))\n if (emptyObjUndef(a) && emptyObjUndef(b)) {\n return true\n } else if (emptyObjUndef(a) && keys(b).length) {\n return false\n } else if (emptyObjUndef(b) && keys(a).length) {\n return false\n }\n\n return allProps.every(function(key) {\n var aVal = a[key]\n var bVal = b[key]\n if (Array.isArray(aVal) && Array.isArray(bVal)) {\n return isEqual(stringArray(a), stringArray(b))\n } else if (Array.isArray(aVal) && !Array.isArray(bVal)) {\n return false\n } else if (Array.isArray(bVal) && !Array.isArray(aVal)) {\n return false\n }\n return keyValEqual(a, b, key, compare)\n })\n}\n\nfunction items(a, b, key, compare) {\n if (isPlainObject(a) && isPlainObject(b)) {\n return compare(a, b)\n } else if (Array.isArray(a) && Array.isArray(b)) {\n return schemaGroup(a, b, key, compare)\n } else {\n return isEqual(a, b)\n }\n}\n\nfunction unsortedArray(a, b, key, compare) {\n var uniqueA = uniqWith(a, compare)\n var uniqueB = uniqWith(b, compare)\n var inter = intersectionWith(uniqueA, uniqueB, compare)\n return inter.length === Math.max(uniqueA.length, uniqueB.length)\n}\n\nvar comparers = {\n title: isEqual,\n uniqueItems: falseUndefined,\n minLength: undefAndZero,\n minItems: undefAndZero,\n minProperties: undefAndZero,\n required: undefArrayEqual,\n enum: undefArrayEqual,\n type: unsortedNormalizedArray,\n items: items,\n anyOf: unsortedArray,\n allOf: unsortedArray,\n oneOf: unsortedArray,\n properties: schemaGroup,\n patternProperties: schemaGroup,\n dependencies: schemaGroup\n}\n\nvar acceptsUndefined = [\n 'properties',\n 'patternProperties',\n 'dependencies',\n 'uniqueItems',\n 'minLength',\n 'minItems',\n 'minProperties',\n 'required'\n]\n\nvar schemaProps = ['additionalProperties', 'additionalItems', 'contains', 'propertyNames', 'not']\n\nfunction compare(a, b, options) {\n options = defaults(options, {\n ignore: []\n })\n\n if (emptySchema(a) && emptySchema(b)) {\n return true\n }\n\n if (!isSchema(a) || !isSchema(b)) {\n throw new Error('Either of the values are not a JSON schema.')\n }\n if (a === b) {\n return true\n }\n\n if (isBoolean(a) && isBoolean(b)) {\n return a === b\n }\n\n if ((a === undefined && b === false) || (b === undefined && a === false)) {\n return false\n }\n\n if ((undef(a) && !undef(b)) || (!undef(a) && undef(b))) {\n return false\n }\n\n var allKeys = uniq(Object.keys(a).concat(Object.keys(b)))\n\n if (options.ignore.length) {\n allKeys = allKeys.filter(k => options.ignore.indexOf(k) === -1)\n }\n\n if (!allKeys.length) {\n return true\n }\n\n function innerCompare(a, b) {\n return compare(a, b, options)\n }\n\n return allKeys.every(function(key) {\n var aValue = a[key]\n var bValue = b[key]\n\n if (schemaProps.indexOf(key) !== -1) {\n return compare(aValue, bValue, options)\n }\n\n var comparer = comparers[key]\n if (!comparer) {\n comparer = isEqual\n }\n\n // do simple lodash check first\n if (isEqual(aValue, bValue)) {\n return true\n }\n\n if (acceptsUndefined.indexOf(key) === -1) {\n if ((!has(a, key) && has(b, key)) || (has(a, key) && !has(b, key))) {\n return aValue === bValue\n }\n }\n\n var result = comparer(aValue, bValue, key, innerCompare)\n if (!isBoolean(result)) {\n throw new Error('Comparer must return true or false')\n }\n return result\n })\n}\n\nmodule.exports = compare\n","'use strict';\n\n/**\n* FUNCTION: isArray( value )\n*\tValidates if a value is an array.\n*\n* @param {*} value - value to be validated\n* @returns {Boolean} boolean indicating whether value is an array\n*/\nfunction isArray( value ) {\n\treturn Object.prototype.toString.call( value ) === '[object Array]';\n} // end FUNCTION isArray()\n\n// EXPORTS //\n\nmodule.exports = Array.isArray || isArray;\n","/**\n*\n*\tVALIDATE: number\n*\n*\n*\tDESCRIPTION:\n*\t\t- Validates if a value is a number.\n*\n*\n*\tNOTES:\n*\t\t[1]\n*\n*\n*\tTODO:\n*\t\t[1]\n*\n*\n*\tLICENSE:\n*\t\tMIT\n*\n*\tCopyright (c) 2014. Athan Reines.\n*\n*\n*\tAUTHOR:\n*\t\tAthan Reines. kgryte@gmail.com. 2014.\n*\n*/\n\n'use strict';\n\n/**\n* FUNCTION: isNumber( value )\n*\tValidates if a value is a number.\n*\n* @param {*} value - value to be validated\n* @returns {Boolean} boolean indicating whether value is a number\n*/\nfunction isNumber( value ) {\n\treturn ( typeof value === 'number' || Object.prototype.toString.call( value ) === '[object Number]' ) && value.valueOf() === value.valueOf();\n} // end FUNCTION isNumber()\n\n\n// EXPORTS //\n\nmodule.exports = isNumber;\n","/**\n*\n*\tVALIDATE: integer\n*\n*\n*\tDESCRIPTION:\n*\t\t- Validates if a value is an integer.\n*\n*\n*\tNOTES:\n*\t\t[1]\n*\n*\n*\tTODO:\n*\t\t[1]\n*\n*\n*\tLICENSE:\n*\t\tMIT\n*\n*\tCopyright (c) 2014. Athan Reines.\n*\n*\n*\tAUTHOR:\n*\t\tAthan Reines. kgryte@gmail.com. 2014.\n*\n*/\n\n'use strict';\n\n// MODULES //\n\nvar isNumber = require( 'validate.io-number' );\n\n\n// ISINTEGER //\n\n/**\n* FUNCTION: isInteger( value )\n*\tValidates if a value is an integer.\n*\n* @param {Number} value - value to be validated\n* @returns {Boolean} boolean indicating whether value is an integer\n*/\nfunction isInteger( value ) {\n\treturn isNumber( value ) && value%1 === 0;\n} // end FUNCTION isInteger()\n\n\n// EXPORTS //\n\nmodule.exports = isInteger;\n","/**\n*\n*\tVALIDATE: integer-array\n*\n*\n*\tDESCRIPTION:\n*\t\t- Validates if a value is an integer array.\n*\n*\n*\tNOTES:\n*\t\t[1]\n*\n*\n*\tTODO:\n*\t\t[1]\n*\n*\n*\tLICENSE:\n*\t\tMIT\n*\n*\tCopyright (c) 2015. Athan Reines.\n*\n*\n*\tAUTHOR:\n*\t\tAthan Reines. kgryte@gmail.com. 2015.\n*\n*/\n\n'use strict';\n\n// MODULES //\n\nvar isArray = require( 'validate.io-array' ),\n\tisInteger = require( 'validate.io-integer' );\n\n\n// IS INTEGER ARRAY //\n\n/**\n* FUNCTION: isIntegerArray( value )\n*\tValidates if a value is an integer array.\n*\n* @param {*} value - value to be validated\n* @returns {Boolean} boolean indicating if a value is an integer array\n*/\nfunction isIntegerArray( value ) {\n\tvar len;\n\tif ( !isArray( value ) ) {\n\t\treturn false;\n\t}\n\tlen = value.length;\n\tif ( !len ) {\n\t\treturn false;\n\t}\n\tfor ( var i = 0; i < len; i++ ) {\n\t\tif ( !isInteger( value[i] ) ) {\n\t\t\treturn false;\n\t\t}\n\t}\n\treturn true;\n} // end FUNCTION isIntegerArray()\n\n\n// EXPORTS //\n\nmodule.exports = isIntegerArray;\n","/**\n*\n*\tVALIDATE: function\n*\n*\n*\tDESCRIPTION:\n*\t\t- Validates if a value is a function.\n*\n*\n*\tNOTES:\n*\t\t[1]\n*\n*\n*\tTODO:\n*\t\t[1]\n*\n*\n*\tLICENSE:\n*\t\tMIT\n*\n*\tCopyright (c) 2014. Athan Reines.\n*\n*\n*\tAUTHOR:\n*\t\tAthan Reines. kgryte@gmail.com. 2014.\n*\n*/\n\n'use strict';\n\n/**\n* FUNCTION: isFunction( value )\n*\tValidates if a value is a function.\n*\n* @param {*} value - value to be validated\n* @returns {Boolean} boolean indicating whether value is a function\n*/\nfunction isFunction( value ) {\n\treturn ( typeof value === 'function' );\n} // end FUNCTION isFunction()\n\n\n// EXPORTS //\n\nmodule.exports = isFunction;\n","'use strict';\n\n// MODULES //\n\nvar isArray = require( 'validate.io-array' ),\n\tisIntegerArray = require( 'validate.io-integer-array' ),\n\tisFunction = require( 'validate.io-function' );\n\n\n// VARIABLES //\n\nvar MAXINT = Math.pow( 2, 31 ) - 1;\n\n\n// FUNCTIONS //\n\n/**\n* FUNCTION: gcd( a, b )\n*\tComputes the greatest common divisor of two integers `a` and `b`, using the binary GCD algorithm.\n*\n* @param {Number} a - integer\n* @param {Number} b - integer\n* @returns {Number} greatest common divisor\n*/\nfunction gcd( a, b ) {\n\tvar k = 1,\n\t\tt;\n\t// Simple cases:\n\tif ( a === 0 ) {\n\t\treturn b;\n\t}\n\tif ( b === 0 ) {\n\t\treturn a;\n\t}\n\t// Reduce `a` and/or `b` to odd numbers and keep track of the greatest power of 2 dividing both `a` and `b`...\n\twhile ( a%2 === 0 && b%2 === 0 ) {\n\t\ta = a / 2; // right shift\n\t\tb = b / 2; // right shift\n\t\tk = k * 2; // left shift\n\t}\n\t// Reduce `a` to an odd number...\n\twhile ( a%2 === 0 ) {\n\t\ta = a / 2; // right shift\n\t}\n\t// Henceforth, `a` is always odd...\n\twhile ( b ) {\n\t\t// Remove all factors of 2 in `b`, as they are not common...\n\t\twhile ( b%2 === 0 ) {\n\t\t\tb = b / 2; // right shift\n\t\t}\n\t\t// `a` and `b` are both odd. Swap values such that `b` is the larger of the two values, and then set `b` to the difference (which is even)...\n\t\tif ( a > b ) {\n\t\t\tt = b;\n\t\t\tb = a;\n\t\t\ta = t;\n\t\t}\n\t\tb = b - a; // b=0 iff b=a\n\t}\n\t// Restore common factors of 2...\n\treturn k * a;\n} // end FUNCTION gcd()\n\n/**\n* FUNCTION: bitwise( a, b )\n*\tComputes the greatest common divisor of two integers `a` and `b`, using the binary GCD algorithm and bitwise operations.\n*\n* @param {Number} a - safe integer\n* @param {Number} b - safe integer\n* @returns {Number} greatest common divisor\n*/\nfunction bitwise( a, b ) {\n\tvar k = 0,\n\t\tt;\n\t// Simple cases:\n\tif ( a === 0 ) {\n\t\treturn b;\n\t}\n\tif ( b === 0 ) {\n\t\treturn a;\n\t}\n\t// Reduce `a` and/or `b` to odd numbers and keep track of the greatest power of 2 dividing both `a` and `b`...\n\twhile ( (a & 1) === 0 && (b & 1) === 0 ) {\n\t\ta >>>= 1; // right shift\n\t\tb >>>= 1; // right shift\n\t\tk++;\n\t}\n\t// Reduce `a` to an odd number...\n\twhile ( (a & 1) === 0 ) {\n\t\ta >>>= 1; // right shift\n\t}\n\t// Henceforth, `a` is always odd...\n\twhile ( b ) {\n\t\t// Remove all factors of 2 in `b`, as they are not common...\n\t\twhile ( (b & 1) === 0 ) {\n\t\t\tb >>>= 1; // right shift\n\t\t}\n\t\t// `a` and `b` are both odd. Swap values such that `b` is the larger of the two values, and then set `b` to the difference (which is even)...\n\t\tif ( a > b ) {\n\t\t\tt = b;\n\t\t\tb = a;\n\t\t\ta = t;\n\t\t}\n\t\tb = b - a; // b=0 iff b=a\n\t}\n\t// Restore common factors of 2...\n\treturn a << k;\n} // end FUNCTION bitwise()\n\n\n// GREATEST COMMON DIVISOR //\n\n/**\n* FUNCTION: compute( arr[, clbk] )\n*\tComputes the greatest common divisor.\n*\n* @param {Number[]|Number} arr - input array of integers\n* @param {Function|Number} [clbk] - accessor function for accessing array values\n* @returns {Number|Null} greatest common divisor or null\n*/\nfunction compute() {\n\tvar nargs = arguments.length,\n\t\targs,\n\t\tclbk,\n\t\tarr,\n\t\tlen,\n\t\ta, b,\n\t\ti;\n\n\t// Copy the input arguments to an array...\n\targs = new Array( nargs );\n\tfor ( i = 0; i < nargs; i++ ) {\n\t\targs[ i ] = arguments[ i ];\n\t}\n\t// Have we been provided with integer arguments?\n\tif ( isIntegerArray( args ) ) {\n\t\tif ( nargs === 2 ) {\n\t\t\ta = args[ 0 ];\n\t\t\tb = args[ 1 ];\n\t\t\tif ( a < 0 ) {\n\t\t\t\ta = -a;\n\t\t\t}\n\t\t\tif ( b < 0 ) {\n\t\t\t\tb = -b;\n\t\t\t}\n\t\t\tif ( a <= MAXINT && b <= MAXINT ) {\n\t\t\t\treturn bitwise( a, b );\n\t\t\t} else {\n\t\t\t\treturn gcd( a, b );\n\t\t\t}\n\t\t}\n\t\tarr = args;\n\t}\n\t// If not integers, ensure the first argument is an array...\n\telse if ( !isArray( args[ 0 ] ) ) {\n\t\tthrow new TypeError( 'gcd()::invalid input argument. Must provide an array of integers. Value: `' + args[ 0 ] + '`.' );\n\t}\n\t// Have we been provided with more than one argument? If so, ensure that the accessor argument is a function...\n\telse if ( nargs > 1 ) {\n\t\tarr = args[ 0 ];\n\t\tclbk = args[ 1 ];\n\t\tif ( !isFunction( clbk ) ) {\n\t\t\tthrow new TypeError( 'gcd()::invalid input argument. Accessor must be a function. Value: `' + clbk + '`.' );\n\t\t}\n\t}\n\t// We have been provided an array...\n\telse {\n\t\tarr = args[ 0 ];\n\t}\n\tlen = arr.length;\n\n\t// Check if a sufficient number of values have been provided...\n\tif ( len < 2 ) {\n\t\treturn null;\n\t}\n\t// If an accessor is provided, extract the array values...\n\tif ( clbk ) {\n\t\ta = new Array( len );\n\t\tfor ( i = 0; i < len; i++ ) {\n\t\t\ta[ i ] = clbk( arr[ i ], i );\n\t\t}\n\t\tarr = a;\n\t}\n\t// Given an input array, ensure all array values are integers...\n\tif ( nargs < 3 ) {\n\t\tif ( !isIntegerArray( arr ) ) {\n\t\t\tthrow new TypeError( 'gcd()::invalid input argument. Accessed array values must be integers. Value: `' + arr + '`.' );\n\t\t}\n\t}\n\t// Convert any negative integers to positive integers...\n\tfor ( i = 0; i < len; i++ ) {\n\t\ta = arr[ i ];\n\t\tif ( a < 0 ) {\n\t\t\tarr[ i ] = -a;\n\t\t}\n\t}\n\t// Exploit the fact that the gcd is an associative function...\n\ta = arr[ 0 ];\n\tfor ( i = 1; i < len; i++ ) {\n\t\tb = arr[ i ];\n\t\tif ( b <= MAXINT && a <= MAXINT ) {\n\t\t\ta = bitwise( a, b );\n\t\t} else {\n\t\t\ta = gcd( a, b );\n\t\t}\n\t}\n\treturn a;\n} // end FUNCTION compute()\n\n\n// EXPORTS //\n\nmodule.exports = compute;\n","'use strict';\n\n// MODULES //\n\nvar gcd = require( 'compute-gcd' ),\n\tisArray = require( 'validate.io-array' ),\n\tisIntegerArray = require( 'validate.io-integer-array' ),\n\tisFunction = require( 'validate.io-function' );\n\n\n// LEAST COMMON MULTIPLE //\n\n/**\n* FUNCTION: lcm( arr[, clbk] )\n*\tComputes the least common multiple (lcm).\n*\n* @param {Number[]|Number} arr - input array of integers\n* @param {Function|Number} [accessor] - accessor function for accessing array values\n* @returns {Number|Null} least common multiple or null\n*/\nfunction lcm() {\n\tvar nargs = arguments.length,\n\t\targs,\n\t\tclbk,\n\t\tarr,\n\t\tlen,\n\t\ta, b,\n\t\ti;\n\n\t// Copy the input arguments to an array...\n\targs = new Array( nargs );\n\tfor ( i = 0; i < nargs; i++ ) {\n\t\targs[ i ] = arguments[ i ];\n\t}\n\t// Have we been provided with integer arguments?\n\tif ( isIntegerArray( args ) ) {\n\t\tif ( nargs === 2 ) {\n\t\t\ta = args[ 0 ];\n\t\t\tb = args[ 1 ];\n\t\t\tif ( a < 0 ) {\n\t\t\t\ta = -a;\n\t\t\t}\n\t\t\tif ( b < 0 ) {\n\t\t\t\tb = -b;\n\t\t\t}\n\t\t\tif ( a === 0 || b === 0 ) {\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t\treturn ( a/gcd(a,b) ) * b;\n\t\t}\n\t\tarr = args;\n\t}\n\t// If not integers, ensure that the first argument is an array...\n\telse if ( !isArray( args[ 0 ] ) ) {\n\t\tthrow new TypeError( 'lcm()::invalid input argument. Must provide an array of integers. Value: `' + args[ 0 ] + '`.' );\n\t}\n\t// Have we been provided with more than one argument? If so, ensure that the accessor argument is a function...\n\telse if ( nargs > 1 ) {\n\t\tarr = args[ 0 ];\n\t\tclbk = args[ 1 ];\n\t\tif ( !isFunction( clbk ) ) {\n\t\t\tthrow new TypeError( 'lcm()::invalid input argument. Accessor must be a function. Value: `' + clbk + '`.' );\n\t\t}\n\t}\n\t// We have been provided an array...\n\telse {\n\t\tarr = args[ 0 ];\n\t}\n\tlen = arr.length;\n\n\t// Check if a sufficient number of values have been provided...\n\tif ( len < 2 ) {\n\t\treturn null;\n\t}\n\t// If an accessor is provided, extract the array values...\n\tif ( clbk ) {\n\t\ta = new Array( len );\n\t\tfor ( i = 0; i < len; i++ ) {\n\t\t\ta[ i ] = clbk( arr[ i ], i );\n\t\t}\n\t\tarr = a;\n\t}\n\t// Given an input array, ensure all array values are integers...\n\tif ( nargs < 3 ) {\n\t\tif ( !isIntegerArray( arr ) ) {\n\t\t\tthrow new TypeError( 'lcm()::invalid input argument. Accessed array values must be integers. Value: `' + arr + '`.' );\n\t\t}\n\t}\n\t// Convert any negative integers to positive integers...\n\tfor ( i = 0; i < len; i++ ) {\n\t\ta = arr[ i ];\n\t\tif ( a < 0 ) {\n\t\t\tarr[ i ] = -a;\n\t\t}\n\t}\n\t// Exploit the fact that the lcm is an associative function...\n\ta = arr[ 0 ];\n\tfor ( i = 1; i < len; i++ ) {\n\t\tb = arr[ i ];\n\t\tif ( a === 0 || b === 0 ) {\n\t\t\treturn 0;\n\t\t}\n\t\ta = ( a/gcd(a,b) ) * b;\n\t}\n\treturn a;\n} // end FUNCTION lcm()\n\n\n// EXPORTS //\n\nmodule.exports = lcm;\n","'use strict'\nvar compact = require('lodash/compact')\nvar compare = require('json-schema-compare')\nvar computeLcm = require('compute-lcm')\nvar defaultsDeep = require('lodash/defaultsDeep')\nvar flatten = require('lodash/flatten')\nvar flattenDeep = require('lodash/flattenDeep')\nvar intersection = require('lodash/intersection')\nvar intersectionWith = require('lodash/intersectionWith')\nvar isEqual = require('lodash/isEqual')\nvar isPlainObject = require('lodash/isPlainObject')\nvar pullAll = require('lodash/pullAll')\nvar pick = require('lodash/pick')\nvar sortBy = require('lodash/sortBy')\nvar forEach = require('lodash/forEach')\nvar uniq = require('lodash/uniq')\nvar uniqWith = require('lodash/uniqWith')\nvar without = require('lodash/without')\n\nvar withoutArr = (arr, ...rest) => without.apply(null, [arr].concat(flatten(rest)))\nvar isPropertyRelated = (key) => contains(propertyRelated, key)\nvar isItemsRelated = (key) => contains(itemsRelated, key)\nvar contains = (arr, val) => arr.indexOf(val) !== -1\nvar isEmptySchema = (obj) => (!keys(obj).length) && obj !== false && obj !== true\nvar isSchema = (val) => isPlainObject(val) || val === true || val === false\nvar isFalse = (val) => val === false\nvar isTrue = (val) => val === true\nvar isNotNull = (val) => val !== null\nvar schemaResolver = (compacted, key, mergeSchemas) => mergeSchemas(compacted)\nvar stringArray = (values) => sortBy(uniq(flattenDeep(values)))\nvar notUndefined = (val) => val !== undefined\nvar allUniqueKeys = (arr) => uniq(flattenDeep(arr.map(keys)))\nvar hasInThis = function (annotation) {\n return annotation in this\n}\n\n// resolvers\nvar first = compacted => compacted[0]\nvar last = compacted => compacted[compacted.length - 1]\nvar required = compacted => stringArray(compacted)\nvar maximumValue = compacted => Math.max.apply(Math, compacted)\nvar minimumValue = compacted => Math.min.apply(Math, compacted)\nvar uniqueItems = compacted => compacted.some(isTrue)\nvar examples = compacted => uniqWith(flatten(compacted), isEqual)\n\nfunction compareProp(key) {\n return function(a, b) {\n return compare({\n [key]: a\n }, {[key]: b})\n }\n}\n\nfunction getAllOf(schema) {\n let { allOf, ...copy } = schema\n copy = isPlainObject(schema) ? copy : schema // if schema is boolean\n if (Array.isArray(allOf)) {\n if (annotationProps.some(hasInThis, copy)) {\n return [copy, ...allOf.filter(isNotNull).map(getAllOf), pick(copy, annotationProps)]\n }\n\n return [copy, ...allOf.filter(isNotNull).map(getAllOf)]\n }\n\n return [copy]\n}\n\nfunction getValues(schemas, key) {\n return schemas.map(schema => schema && schema[key])\n}\n\nfunction getItemSchemas(subSchemas, key) {\n return subSchemas.map(function(sub) {\n if (!sub) {\n return\n }\n\n if (Array.isArray(sub.items)) {\n var schemaAtPos = sub.items[key]\n if (isSchema(schemaAtPos)) {\n return schemaAtPos\n } else if (sub.hasOwnProperty('additionalItems')) {\n return sub.additionalItems\n }\n } else {\n return sub.items\n }\n })\n}\n\nfunction tryMergeSchemaGroups(schemaGroups, mergeSchemas) {\n return schemaGroups.map(function(schemas, index) {\n try {\n return mergeSchemas(schemas, index)\n } catch (e) {\n return undefined\n }\n }).filter(notUndefined)\n}\n\nfunction getAdditionalSchemas(subSchemas) {\n return subSchemas.map(function(sub) {\n if (!sub) {\n return\n }\n if (Array.isArray(sub.items)) {\n return sub.additionalItems\n }\n return sub.items\n })\n}\n\nfunction keys(obj) {\n if (isPlainObject(obj) || Array.isArray(obj)) {\n return Object.keys(obj)\n } else {\n return []\n }\n}\n\nfunction getAnyOfCombinations(arrOfArrays, combinations) {\n combinations = combinations || []\n if (!arrOfArrays.length) {\n return combinations\n }\n\n var values = arrOfArrays.slice(0).shift()\n var rest = arrOfArrays.slice(1)\n if (combinations.length) {\n return getAnyOfCombinations(rest, flatten(combinations.map(combination => values.map(item => ([item].concat(combination))))))\n }\n return getAnyOfCombinations(rest, values.map(item => (item)))\n}\n\nfunction mergeWithArray(base, newItems) {\n if (Array.isArray(base)) {\n base.splice.apply(base, [0, 0].concat(newItems))\n return base\n } else {\n return newItems\n }\n}\n\nfunction throwIncompatible(values, paths) {\n var asJSON\n try {\n asJSON = values.map(function(val) {\n return JSON.stringify(val, null, 2)\n }).join('\\n')\n } catch (variable) {\n asJSON = values.join(', ')\n }\n throw new Error('Could not resolve values for path:\"' + paths.join('.') + '\". They are probably incompatible. Values: \\n' + asJSON)\n}\n\nfunction cleanupReturnValue(returnObject) {\n // cleanup empty\n for (var prop in returnObject) {\n if (returnObject.hasOwnProperty(prop) && isEmptySchema(returnObject[prop])) {\n delete returnObject[prop]\n }\n }\n return returnObject\n}\n\nfunction applyOverrides(originalValue, newValue) {\n if (\n isPlainObject(newValue) &&\n isPlainObject(originalValue) &&\n ('summary' in originalValue || 'description' in originalValue)\n ) {\n return {\n ...newValue,\n ...('description' in originalValue\n ? { description: originalValue.description }\n : null),\n ...('summary' in originalValue\n ? { summary: originalValue.summary }\n : null)\n }\n }\n\n return newValue\n}\n\nfunction createRequiredSubMerger(mergeSchemas, key, parents) {\n return function(schemas, subKey) {\n if (subKey === undefined) {\n throw new Error('You need to call merger with a key for the property name or index if array.')\n }\n subKey = String(subKey)\n return mergeSchemas(schemas, null, parents.concat(key, subKey))\n }\n}\n\nfunction callGroupResolver(keys, resolverName, schemas, mergeSchemas, options, parents) {\n if (keys.length) {\n var resolver = options.resolvers[resolverName]\n if (!resolver) {\n throw new Error('No resolver found for ' + resolverName)\n }\n\n var compacted = uniqWith(schemas.map(function(schema) {\n return keys.reduce(function(all, key) {\n if (schema[key] !== undefined) {\n all[key] = schema[key]\n }\n return all\n }, {})\n }).filter(notUndefined), compare)\n\n var related = resolverName === 'properties'\n ? propertyRelated\n : itemsRelated\n\n var mergers = related.reduce(function(all, key) {\n if (contains(schemaGroupProps, key)) {\n all[key] = createRequiredSubMerger(mergeSchemas, key, parents)\n } else {\n all[key] = function(schemas) {\n return mergeSchemas(schemas, null, parents.concat(key))\n }\n }\n return all\n }, {})\n\n if (resolverName === 'items') {\n mergers.itemsArray = createRequiredSubMerger(mergeSchemas, 'items', parents)\n mergers.items = function(schemas) {\n return mergeSchemas(schemas, null, parents.concat('items'))\n }\n }\n\n var result = resolver(compacted, parents.concat(resolverName), mergers, options)\n\n if (!isPlainObject(result)) {\n throwIncompatible(compacted, parents.concat(resolverName))\n }\n\n return cleanupReturnValue(result)\n }\n}\n\n// Provide source when array\nfunction mergeSchemaGroup(group, mergeSchemas, source) {\n var allKeys = allUniqueKeys(source || group)\n var extractor = source\n ? getItemSchemas\n : getValues\n return allKeys.reduce(function(all, key) {\n var schemas = extractor(group, key)\n var compacted = uniqWith(schemas.filter(notUndefined), compare)\n all[key] = mergeSchemas(compacted, key)\n return all\n }, source\n ? []\n : {})\n}\n\nfunction removeFalseSchemas(target) {\n forEach(target, function(schema, prop) {\n if (schema === false) {\n delete target[prop]\n }\n })\n}\n\nfunction removeFalseSchemasFromArray(target) {\n forEach(target, function(schema, index) {\n if (schema === false) {\n target.splice(index, 1)\n }\n })\n}\n\nfunction createRequiredMetaArray(arr) {\n return {required: arr}\n}\n\nfunction default$RefResolver(reference) {\n return {$ref: reference}\n}\n\nfunction inferType(schema) {\n if (!isPlainObject(schema)) return\n if ('type' in schema) return typeof schema.type === 'string' ? schema.type : undefined\n\n var types = Object.keys(implicitTypes).filter(type => implicitTypes[type].some(prop => prop in schema))\n if (types.length > 0) return types\n}\n\nvar propertyRelated = ['properties', 'patternProperties', 'additionalProperties']\nvar itemsRelated = ['items', 'additionalItems']\nvar schemaGroupProps = ['properties', 'patternProperties', 'definitions', 'dependencies']\nvar schemaArrays = ['anyOf', 'oneOf']\nvar schemaProps = [\n 'additionalProperties',\n 'additionalItems',\n 'contains',\n 'propertyNames',\n 'not',\n 'items'\n]\nvar annotationProps = ['title', 'description']\n\nvar implicitTypes = {\n object: [...propertyRelated, 'required'],\n array: [...itemsRelated, 'contains', 'uniqueItems', 'minContains', 'maxContains'],\n number: ['multipleOf', 'minimum', 'maximum', 'exclusiveMinimum', 'exclusiveMaximum'],\n get integer() { return this.number },\n string: ['pattern', 'minLength', 'maxLength']\n}\n\nvar defaultResolvers = {\n type(compacted) {\n if (compacted.some(Array.isArray)) {\n var normalized = compacted.map(function(val) {\n return Array.isArray(val)\n ? val\n : [val]\n })\n var common = intersection.apply(null, normalized)\n\n if (common.length === 1) {\n return common[0]\n } else if (common.length > 1) {\n return uniq(common)\n }\n }\n },\n properties(values, key, mergers, options) {\n // first get rid of all non permitted properties\n if (!options.ignoreAdditionalProperties) {\n values.forEach(function(subSchema) {\n var otherSubSchemas = values.filter(s => s !== subSchema)\n var ownKeys = keys(subSchema.properties)\n var ownPatternKeys = keys(subSchema.patternProperties)\n var ownPatterns = ownPatternKeys.map(k => new RegExp(k))\n otherSubSchemas.forEach(function(other) {\n var allOtherKeys = keys(other.properties)\n var keysMatchingPattern = allOtherKeys.filter(k => ownPatterns.some(pk => pk.test(k)))\n var additionalKeys = withoutArr(allOtherKeys, ownKeys, keysMatchingPattern)\n other.properties = Object.assign({}, other.properties)\n additionalKeys.forEach(function(key) {\n other.properties[key] = mergers.properties([\n other.properties[key], subSchema.additionalProperties\n ], key)\n })\n })\n })\n\n // remove disallowed patternProperties\n values.forEach(function(subSchema) {\n var otherSubSchemas = values.filter(s => s !== subSchema)\n var ownPatternKeys = keys(subSchema.patternProperties)\n if (subSchema.additionalProperties === false) {\n otherSubSchemas.forEach(function(other) {\n other.patternProperties = Object.assign({}, other.patternProperties)\n var allOtherPatterns = keys(other.patternProperties)\n var additionalPatternKeys = withoutArr(allOtherPatterns, ownPatternKeys)\n additionalPatternKeys.forEach(key => delete other.patternProperties[key])\n })\n }\n })\n }\n\n var returnObject = {\n additionalProperties: mergers.additionalProperties(values.map(s => s.additionalProperties)),\n patternProperties: mergeSchemaGroup(values.map(s => s.patternProperties), mergers.patternProperties),\n properties: mergeSchemaGroup(values.map(s => s.properties), mergers.properties)\n }\n\n if (returnObject.additionalProperties === false) {\n removeFalseSchemas(returnObject.properties)\n }\n\n return returnObject\n },\n dependencies(compacted, paths, mergeSchemas) {\n var allChildren = allUniqueKeys(compacted)\n\n return allChildren.reduce(function(all, childKey) {\n var childSchemas = getValues(compacted, childKey)\n var innerCompacted = uniqWith(childSchemas.filter(notUndefined), isEqual)\n\n // to support dependencies\n var innerArrays = innerCompacted.filter(Array.isArray)\n\n if (innerArrays.length) {\n if (innerArrays.length === innerCompacted.length) {\n all[childKey] = stringArray(innerCompacted)\n } else {\n var innerSchemas = innerCompacted.filter(isSchema)\n var arrayMetaScheams = innerArrays.map(createRequiredMetaArray)\n all[childKey] = mergeSchemas(innerSchemas.concat(arrayMetaScheams), childKey)\n }\n return all\n }\n\n innerCompacted = uniqWith(innerCompacted, compare)\n\n all[childKey] = mergeSchemas(innerCompacted, childKey)\n return all\n }, {})\n },\n items(values, paths, mergers) {\n var items = values.map(s => s.items)\n var itemsCompacted = items.filter(notUndefined)\n var returnObject = {}\n\n if (itemsCompacted.every(isSchema)) {\n returnObject.items = mergers.items(items)\n } else {\n returnObject.items = mergeSchemaGroup(values, mergers.itemsArray, items)\n }\n\n var schemasAtLastPos\n if (itemsCompacted.every(Array.isArray)) {\n schemasAtLastPos = values.map(s => s.additionalItems)\n } else if (itemsCompacted.some(Array.isArray)) {\n schemasAtLastPos = getAdditionalSchemas(values)\n }\n\n if (schemasAtLastPos) {\n returnObject.additionalItems = mergers.additionalItems(schemasAtLastPos)\n }\n\n if (returnObject.additionalItems === false && Array.isArray(returnObject.items)) {\n removeFalseSchemasFromArray(returnObject.items)\n }\n\n return returnObject\n },\n oneOf(compacted, paths, mergeSchemas) {\n var combinations = getAnyOfCombinations(compacted)\n var result = tryMergeSchemaGroups(combinations, mergeSchemas)\n var unique = uniqWith(result, compare)\n\n if (unique.length) {\n return unique\n }\n },\n not(compacted) {\n return {anyOf: compacted}\n },\n pattern(compacted) {\n return compacted.map(r => '(?=' + r + ')').join('')\n },\n multipleOf(compacted) {\n var integers = compacted.slice(0)\n var factor = 1\n while (integers.some(n => !Number.isInteger(n))) {\n integers = integers.map(n => n * 10)\n factor = factor * 10\n }\n return computeLcm(integers) / factor\n },\n enum(compacted) {\n var enums = intersectionWith.apply(null, compacted.concat(isEqual))\n if (enums.length) {\n return sortBy(enums)\n }\n }\n}\n\ndefaultResolvers.$id = first\ndefaultResolvers.$ref = first\ndefaultResolvers.$schema = first\ndefaultResolvers.additionalItems = schemaResolver\ndefaultResolvers.additionalProperties = schemaResolver\ndefaultResolvers.anyOf = defaultResolvers.oneOf\ndefaultResolvers.contains = schemaResolver\ndefaultResolvers.default = last\ndefaultResolvers.definitions = defaultResolvers.dependencies\ndefaultResolvers.description = last\ndefaultResolvers.examples = examples\ndefaultResolvers.exclusiveMaximum = minimumValue\ndefaultResolvers.exclusiveMinimum = maximumValue\ndefaultResolvers.maximum = minimumValue\ndefaultResolvers.maxItems = minimumValue\ndefaultResolvers.maxLength = minimumValue\ndefaultResolvers.maxProperties = minimumValue\ndefaultResolvers.minimum = maximumValue\ndefaultResolvers.minItems = maximumValue\ndefaultResolvers.minLength = maximumValue\ndefaultResolvers.minProperties = maximumValue\ndefaultResolvers.propertyNames = schemaResolver\ndefaultResolvers.required = required\ndefaultResolvers.title = last\ndefaultResolvers.uniqueItems = uniqueItems\n\nfunction merger(rootSchema, options, totalSchemas) {\n totalSchemas = totalSchemas || []\n options = defaultsDeep(options, {\n ignoreAdditionalProperties: false,\n resolvers: defaultResolvers,\n deep: true,\n $refResolver: default$RefResolver\n })\n\n function mergeSchemas(schemas, base, parents) {\n schemas = schemas.filter(notUndefined)\n parents = parents || []\n var merged = isPlainObject(base)\n ? Object.assign({}, base)\n : {}\n\n // return undefined, an empty schema\n if (!schemas.length) {\n return\n }\n\n if (schemas.some(isFalse)) {\n return false\n }\n\n if (schemas.every(isTrue)) {\n return true\n }\n\n // there are no false and we don't need the true ones as they accept everything\n schemas = schemas.filter(isPlainObject)\n\n schemas = schemas.map(schema => '$ref' in schema ? applyOverrides(\n schema,\n options.$refResolver(schema.$ref)\n ) : Object.assign({}, schema))\n\n var types = schemas.map(schema => inferType(schema)).filter(notUndefined)\n\n if (types.length > 1) {\n let first = Array.isArray(types[0]) ? types[0] : [types[0]]\n types.slice(1).forEach(function (type) {\n if (Array.isArray(type) ? !intersection(first, type).length : !first.includes(type)) {\n throwIncompatible(types, parents.concat('type'))\n }\n })\n }\n\n var allKeys = allUniqueKeys(schemas)\n\n if (options.deep && contains(allKeys, 'allOf')) {\n return merger({\n allOf: schemas\n }, options, totalSchemas)\n }\n\n var propertyKeys = allKeys.filter(isPropertyRelated)\n pullAll(allKeys, propertyKeys)\n\n var itemKeys = allKeys.filter(isItemsRelated)\n pullAll(allKeys, itemKeys)\n\n allKeys.forEach(function(key) {\n var values = getValues(schemas, key).filter(notUndefined)\n var compacted = annotationProps.includes(key) ? values : uniqWith(values, compareProp(key))\n\n // arrayprops like anyOf and oneOf must be merged first, as they contains schemas\n // allOf is treated differently alltogether\n if (compacted.length === 1 && contains(schemaArrays, key)) {\n merged[key] = compacted[0].map(function(schema) {\n return mergeSchemas([schema], schema)\n })\n // prop groups must always be resolved\n } else if (compacted.length === 1 && !contains(schemaGroupProps, key) && !contains(schemaProps, key)) {\n merged[key] = compacted[0]\n } else {\n var resolver = options.resolvers[key] || options.resolvers.defaultResolver\n\n if (!resolver) {\n throw new Error('No resolver found for key ' + key + '. You can provide a resolver for this keyword in the options, or provide a default resolver.')\n }\n\n var merger\n // get custom merger for groups\n if (contains(schemaGroupProps, key) || contains(schemaArrays, key)) {\n merger = createRequiredSubMerger(mergeSchemas, key, parents)\n } else {\n merger = function(schemas) {\n return mergeSchemas(schemas, null, parents.concat(key))\n }\n }\n\n var calledWithArray = false\n merged[key] = resolver(compacted, parents.concat(key), merger, options, function(unresolvedSchemas) {\n calledWithArray = Array.isArray(unresolvedSchemas)\n return addToAllOf(unresolvedSchemas)\n })\n\n if (merged[key] === undefined && !calledWithArray) {\n throwIncompatible(compacted, parents.concat(key))\n } else if (merged[key] === undefined) {\n delete merged[key]\n }\n }\n })\n\n Object.assign(merged, callGroupResolver(propertyKeys, 'properties', schemas, mergeSchemas, options, parents))\n Object.assign(merged, callGroupResolver(itemKeys, 'items', schemas, mergeSchemas, options, parents))\n\n function addToAllOf(unresolvedSchemas) {\n merged.allOf = mergeWithArray(merged.allOf, unresolvedSchemas)\n }\n\n return merged\n }\n\n var allSchemas = flattenDeep(getAllOf(rootSchema))\n var merged = mergeSchemas(allSchemas)\n\n return merged\n}\n\nmerger.options = {\n resolvers: defaultResolvers\n}\n\nmerger.stoplightResolvers = {\n defaultResolver(values) {\n if (Array.isArray(values)) {\n return values\n }\n\n return Object.assign({}, ...Object(values))\n },\n example(values) {\n return defaultResolvers.enum(values) || null\n },\n enum(values) {\n return defaultResolvers.enum(compact(values)) || []\n },\n $ref(values) {\n return {}\n }\n}\n\nmodule.exports = merger\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n'use strict';\nimport { createScanner } from './scanner';\nvar ParseOptions;\n(function (ParseOptions) {\n ParseOptions.DEFAULT = {\n allowTrailingComma: false\n };\n})(ParseOptions || (ParseOptions = {}));\n/**\n * For a given offset, evaluate the location in the JSON document. Each segment in the location path is either a property name or an array index.\n */\nexport function getLocation(text, position) {\n var segments = []; // strings or numbers\n var earlyReturnException = new Object();\n var previousNode = undefined;\n var previousNodeInst = {\n value: {},\n offset: 0,\n length: 0,\n type: 'object',\n parent: undefined\n };\n var isAtPropertyKey = false;\n function setPreviousNode(value, offset, length, type) {\n previousNodeInst.value = value;\n previousNodeInst.offset = offset;\n previousNodeInst.length = length;\n previousNodeInst.type = type;\n previousNodeInst.colonOffset = undefined;\n previousNode = previousNodeInst;\n }\n try {\n visit(text, {\n onObjectBegin: function (offset, length) {\n if (position <= offset) {\n throw earlyReturnException;\n }\n previousNode = undefined;\n isAtPropertyKey = position > offset;\n segments.push(''); // push a placeholder (will be replaced)\n },\n onObjectProperty: function (name, offset, length) {\n if (position < offset) {\n throw earlyReturnException;\n }\n setPreviousNode(name, offset, length, 'property');\n segments[segments.length - 1] = name;\n if (position <= offset + length) {\n throw earlyReturnException;\n }\n },\n onObjectEnd: function (offset, length) {\n if (position <= offset) {\n throw earlyReturnException;\n }\n previousNode = undefined;\n segments.pop();\n },\n onArrayBegin: function (offset, length) {\n if (position <= offset) {\n throw earlyReturnException;\n }\n previousNode = undefined;\n segments.push(0);\n },\n onArrayEnd: function (offset, length) {\n if (position <= offset) {\n throw earlyReturnException;\n }\n previousNode = undefined;\n segments.pop();\n },\n onLiteralValue: function (value, offset, length) {\n if (position < offset) {\n throw earlyReturnException;\n }\n setPreviousNode(value, offset, length, getNodeType(value));\n if (position <= offset + length) {\n throw earlyReturnException;\n }\n },\n onSeparator: function (sep, offset, length) {\n if (position <= offset) {\n throw earlyReturnException;\n }\n if (sep === ':' && previousNode && previousNode.type === 'property') {\n previousNode.colonOffset = offset;\n isAtPropertyKey = false;\n previousNode = undefined;\n }\n else if (sep === ',') {\n var last = segments[segments.length - 1];\n if (typeof last === 'number') {\n segments[segments.length - 1] = last + 1;\n }\n else {\n isAtPropertyKey = true;\n segments[segments.length - 1] = '';\n }\n previousNode = undefined;\n }\n }\n });\n }\n catch (e) {\n if (e !== earlyReturnException) {\n throw e;\n }\n }\n return {\n path: segments,\n previousNode: previousNode,\n isAtPropertyKey: isAtPropertyKey,\n matches: function (pattern) {\n var k = 0;\n for (var i = 0; k < pattern.length && i < segments.length; i++) {\n if (pattern[k] === segments[i] || pattern[k] === '*') {\n k++;\n }\n else if (pattern[k] !== '**') {\n return false;\n }\n }\n return k === pattern.length;\n }\n };\n}\n/**\n * Parses the given text and returns the object the JSON content represents. On invalid input, the parser tries to be as fault tolerant as possible, but still return a result.\n * Therefore always check the errors list to find out if the input was valid.\n */\nexport function parse(text, errors, options) {\n if (errors === void 0) { errors = []; }\n if (options === void 0) { options = ParseOptions.DEFAULT; }\n var currentProperty = null;\n var currentParent = [];\n var previousParents = [];\n function onValue(value) {\n if (Array.isArray(currentParent)) {\n currentParent.push(value);\n }\n else if (currentProperty !== null) {\n currentParent[currentProperty] = value;\n }\n }\n var visitor = {\n onObjectBegin: function () {\n var object = {};\n onValue(object);\n previousParents.push(currentParent);\n currentParent = object;\n currentProperty = null;\n },\n onObjectProperty: function (name) {\n currentProperty = name;\n },\n onObjectEnd: function () {\n currentParent = previousParents.pop();\n },\n onArrayBegin: function () {\n var array = [];\n onValue(array);\n previousParents.push(currentParent);\n currentParent = array;\n currentProperty = null;\n },\n onArrayEnd: function () {\n currentParent = previousParents.pop();\n },\n onLiteralValue: onValue,\n onError: function (error, offset, length) {\n errors.push({ error: error, offset: offset, length: length });\n }\n };\n visit(text, visitor, options);\n return currentParent[0];\n}\n/**\n * Parses the given text and returns a tree representation the JSON content. On invalid input, the parser tries to be as fault tolerant as possible, but still return a result.\n */\nexport function parseTree(text, errors, options) {\n if (errors === void 0) { errors = []; }\n if (options === void 0) { options = ParseOptions.DEFAULT; }\n var currentParent = { type: 'array', offset: -1, length: -1, children: [], parent: undefined }; // artificial root\n function ensurePropertyComplete(endOffset) {\n if (currentParent.type === 'property') {\n currentParent.length = endOffset - currentParent.offset;\n currentParent = currentParent.parent;\n }\n }\n function onValue(valueNode) {\n currentParent.children.push(valueNode);\n return valueNode;\n }\n var visitor = {\n onObjectBegin: function (offset) {\n currentParent = onValue({ type: 'object', offset: offset, length: -1, parent: currentParent, children: [] });\n },\n onObjectProperty: function (name, offset, length) {\n currentParent = onValue({ type: 'property', offset: offset, length: -1, parent: currentParent, children: [] });\n currentParent.children.push({ type: 'string', value: name, offset: offset, length: length, parent: currentParent });\n },\n onObjectEnd: function (offset, length) {\n ensurePropertyComplete(offset + length); // in case of a missing value for a property: make sure property is complete\n currentParent.length = offset + length - currentParent.offset;\n currentParent = currentParent.parent;\n ensurePropertyComplete(offset + length);\n },\n onArrayBegin: function (offset, length) {\n currentParent = onValue({ type: 'array', offset: offset, length: -1, parent: currentParent, children: [] });\n },\n onArrayEnd: function (offset, length) {\n currentParent.length = offset + length - currentParent.offset;\n currentParent = currentParent.parent;\n ensurePropertyComplete(offset + length);\n },\n onLiteralValue: function (value, offset, length) {\n onValue({ type: getNodeType(value), offset: offset, length: length, parent: currentParent, value: value });\n ensurePropertyComplete(offset + length);\n },\n onSeparator: function (sep, offset, length) {\n if (currentParent.type === 'property') {\n if (sep === ':') {\n currentParent.colonOffset = offset;\n }\n else if (sep === ',') {\n ensurePropertyComplete(offset);\n }\n }\n },\n onError: function (error, offset, length) {\n errors.push({ error: error, offset: offset, length: length });\n }\n };\n visit(text, visitor, options);\n var result = currentParent.children[0];\n if (result) {\n delete result.parent;\n }\n return result;\n}\n/**\n * Finds the node at the given path in a JSON DOM.\n */\nexport function findNodeAtLocation(root, path) {\n if (!root) {\n return undefined;\n }\n var node = root;\n for (var _i = 0, path_1 = path; _i < path_1.length; _i++) {\n var segment = path_1[_i];\n if (typeof segment === 'string') {\n if (node.type !== 'object' || !Array.isArray(node.children)) {\n return undefined;\n }\n var found = false;\n for (var _a = 0, _b = node.children; _a < _b.length; _a++) {\n var propertyNode = _b[_a];\n if (Array.isArray(propertyNode.children) && propertyNode.children[0].value === segment) {\n node = propertyNode.children[1];\n found = true;\n break;\n }\n }\n if (!found) {\n return undefined;\n }\n }\n else {\n var index = segment;\n if (node.type !== 'array' || index < 0 || !Array.isArray(node.children) || index >= node.children.length) {\n return undefined;\n }\n node = node.children[index];\n }\n }\n return node;\n}\n/**\n * Gets the JSON path of the given JSON DOM node\n */\nexport function getNodePath(node) {\n if (!node.parent || !node.parent.children) {\n return [];\n }\n var path = getNodePath(node.parent);\n if (node.parent.type === 'property') {\n var key = node.parent.children[0].value;\n path.push(key);\n }\n else if (node.parent.type === 'array') {\n var index = node.parent.children.indexOf(node);\n if (index !== -1) {\n path.push(index);\n }\n }\n return path;\n}\n/**\n * Evaluates the JavaScript object of the given JSON DOM node\n */\nexport function getNodeValue(node) {\n switch (node.type) {\n case 'array':\n return node.children.map(getNodeValue);\n case 'object':\n var obj = Object.create(null);\n for (var _i = 0, _a = node.children; _i < _a.length; _i++) {\n var prop = _a[_i];\n var valueNode = prop.children[1];\n if (valueNode) {\n obj[prop.children[0].value] = getNodeValue(valueNode);\n }\n }\n return obj;\n case 'null':\n case 'string':\n case 'number':\n case 'boolean':\n return node.value;\n default:\n return undefined;\n }\n}\nexport function contains(node, offset, includeRightBound) {\n if (includeRightBound === void 0) { includeRightBound = false; }\n return (offset >= node.offset && offset < (node.offset + node.length)) || includeRightBound && (offset === (node.offset + node.length));\n}\n/**\n * Finds the most inner node at the given offset. If includeRightBound is set, also finds nodes that end at the given offset.\n */\nexport function findNodeAtOffset(node, offset, includeRightBound) {\n if (includeRightBound === void 0) { includeRightBound = false; }\n if (contains(node, offset, includeRightBound)) {\n var children = node.children;\n if (Array.isArray(children)) {\n for (var i = 0; i < children.length && children[i].offset <= offset; i++) {\n var item = findNodeAtOffset(children[i], offset, includeRightBound);\n if (item) {\n return item;\n }\n }\n }\n return node;\n }\n return undefined;\n}\n/**\n * Parses the given text and invokes the visitor functions for each object, array and literal reached.\n */\nexport function visit(text, visitor, options) {\n if (options === void 0) { options = ParseOptions.DEFAULT; }\n var _scanner = createScanner(text, false);\n function toNoArgVisit(visitFunction) {\n return visitFunction ? function () { return visitFunction(_scanner.getTokenOffset(), _scanner.getTokenLength(), _scanner.getTokenStartLine(), _scanner.getTokenStartCharacter()); } : function () { return true; };\n }\n function toOneArgVisit(visitFunction) {\n return visitFunction ? function (arg) { return visitFunction(arg, _scanner.getTokenOffset(), _scanner.getTokenLength(), _scanner.getTokenStartLine(), _scanner.getTokenStartCharacter()); } : function () { return true; };\n }\n var onObjectBegin = toNoArgVisit(visitor.onObjectBegin), onObjectProperty = toOneArgVisit(visitor.onObjectProperty), onObjectEnd = toNoArgVisit(visitor.onObjectEnd), onArrayBegin = toNoArgVisit(visitor.onArrayBegin), onArrayEnd = toNoArgVisit(visitor.onArrayEnd), onLiteralValue = toOneArgVisit(visitor.onLiteralValue), onSeparator = toOneArgVisit(visitor.onSeparator), onComment = toNoArgVisit(visitor.onComment), onError = toOneArgVisit(visitor.onError);\n var disallowComments = options && options.disallowComments;\n var allowTrailingComma = options && options.allowTrailingComma;\n function scanNext() {\n while (true) {\n var token = _scanner.scan();\n switch (_scanner.getTokenError()) {\n case 4 /* InvalidUnicode */:\n handleError(14 /* InvalidUnicode */);\n break;\n case 5 /* InvalidEscapeCharacter */:\n handleError(15 /* InvalidEscapeCharacter */);\n break;\n case 3 /* UnexpectedEndOfNumber */:\n handleError(13 /* UnexpectedEndOfNumber */);\n break;\n case 1 /* UnexpectedEndOfComment */:\n if (!disallowComments) {\n handleError(11 /* UnexpectedEndOfComment */);\n }\n break;\n case 2 /* UnexpectedEndOfString */:\n handleError(12 /* UnexpectedEndOfString */);\n break;\n case 6 /* InvalidCharacter */:\n handleError(16 /* InvalidCharacter */);\n break;\n }\n switch (token) {\n case 12 /* LineCommentTrivia */:\n case 13 /* BlockCommentTrivia */:\n if (disallowComments) {\n handleError(10 /* InvalidCommentToken */);\n }\n else {\n onComment();\n }\n break;\n case 16 /* Unknown */:\n handleError(1 /* InvalidSymbol */);\n break;\n case 15 /* Trivia */:\n case 14 /* LineBreakTrivia */:\n break;\n default:\n return token;\n }\n }\n }\n function handleError(error, skipUntilAfter, skipUntil) {\n if (skipUntilAfter === void 0) { skipUntilAfter = []; }\n if (skipUntil === void 0) { skipUntil = []; }\n onError(error);\n if (skipUntilAfter.length + skipUntil.length > 0) {\n var token = _scanner.getToken();\n while (token !== 17 /* EOF */) {\n if (skipUntilAfter.indexOf(token) !== -1) {\n scanNext();\n break;\n }\n else if (skipUntil.indexOf(token) !== -1) {\n break;\n }\n token = scanNext();\n }\n }\n }\n function parseString(isValue) {\n var value = _scanner.getTokenValue();\n if (isValue) {\n onLiteralValue(value);\n }\n else {\n onObjectProperty(value);\n }\n scanNext();\n return true;\n }\n function parseLiteral() {\n switch (_scanner.getToken()) {\n case 11 /* NumericLiteral */:\n var value = 0;\n try {\n value = JSON.parse(_scanner.getTokenValue());\n if (typeof value !== 'number') {\n handleError(2 /* InvalidNumberFormat */);\n value = 0;\n }\n }\n catch (e) {\n handleError(2 /* InvalidNumberFormat */);\n }\n onLiteralValue(value);\n break;\n case 7 /* NullKeyword */:\n onLiteralValue(null);\n break;\n case 8 /* TrueKeyword */:\n onLiteralValue(true);\n break;\n case 9 /* FalseKeyword */:\n onLiteralValue(false);\n break;\n default:\n return false;\n }\n scanNext();\n return true;\n }\n function parseProperty() {\n if (_scanner.getToken() !== 10 /* StringLiteral */) {\n handleError(3 /* PropertyNameExpected */, [], [2 /* CloseBraceToken */, 5 /* CommaToken */]);\n return false;\n }\n parseString(false);\n if (_scanner.getToken() === 6 /* ColonToken */) {\n onSeparator(':');\n scanNext(); // consume colon\n if (!parseValue()) {\n handleError(4 /* ValueExpected */, [], [2 /* CloseBraceToken */, 5 /* CommaToken */]);\n }\n }\n else {\n handleError(5 /* ColonExpected */, [], [2 /* CloseBraceToken */, 5 /* CommaToken */]);\n }\n return true;\n }\n function parseObject() {\n onObjectBegin();\n scanNext(); // consume open brace\n var needsComma = false;\n while (_scanner.getToken() !== 2 /* CloseBraceToken */ && _scanner.getToken() !== 17 /* EOF */) {\n if (_scanner.getToken() === 5 /* CommaToken */) {\n if (!needsComma) {\n handleError(4 /* ValueExpected */, [], []);\n }\n onSeparator(',');\n scanNext(); // consume comma\n if (_scanner.getToken() === 2 /* CloseBraceToken */ && allowTrailingComma) {\n break;\n }\n }\n else if (needsComma) {\n handleError(6 /* CommaExpected */, [], []);\n }\n if (!parseProperty()) {\n handleError(4 /* ValueExpected */, [], [2 /* CloseBraceToken */, 5 /* CommaToken */]);\n }\n needsComma = true;\n }\n onObjectEnd();\n if (_scanner.getToken() !== 2 /* CloseBraceToken */) {\n handleError(7 /* CloseBraceExpected */, [2 /* CloseBraceToken */], []);\n }\n else {\n scanNext(); // consume close brace\n }\n return true;\n }\n function parseArray() {\n onArrayBegin();\n scanNext(); // consume open bracket\n var needsComma = false;\n while (_scanner.getToken() !== 4 /* CloseBracketToken */ && _scanner.getToken() !== 17 /* EOF */) {\n if (_scanner.getToken() === 5 /* CommaToken */) {\n if (!needsComma) {\n handleError(4 /* ValueExpected */, [], []);\n }\n onSeparator(',');\n scanNext(); // consume comma\n if (_scanner.getToken() === 4 /* CloseBracketToken */ && allowTrailingComma) {\n break;\n }\n }\n else if (needsComma) {\n handleError(6 /* CommaExpected */, [], []);\n }\n if (!parseValue()) {\n handleError(4 /* ValueExpected */, [], [4 /* CloseBracketToken */, 5 /* CommaToken */]);\n }\n needsComma = true;\n }\n onArrayEnd();\n if (_scanner.getToken() !== 4 /* CloseBracketToken */) {\n handleError(8 /* CloseBracketExpected */, [4 /* CloseBracketToken */], []);\n }\n else {\n scanNext(); // consume close bracket\n }\n return true;\n }\n function parseValue() {\n switch (_scanner.getToken()) {\n case 3 /* OpenBracketToken */:\n return parseArray();\n case 1 /* OpenBraceToken */:\n return parseObject();\n case 10 /* StringLiteral */:\n return parseString(true);\n default:\n return parseLiteral();\n }\n }\n scanNext();\n if (_scanner.getToken() === 17 /* EOF */) {\n if (options.allowEmptyContent) {\n return true;\n }\n handleError(4 /* ValueExpected */, [], []);\n return false;\n }\n if (!parseValue()) {\n handleError(4 /* ValueExpected */, [], []);\n return false;\n }\n if (_scanner.getToken() !== 17 /* EOF */) {\n handleError(9 /* EndOfFileExpected */, [], []);\n }\n return true;\n}\n/**\n * Takes JSON with JavaScript-style comments and remove\n * them. Optionally replaces every none-newline character\n * of comments with a replaceCharacter\n */\nexport function stripComments(text, replaceCh) {\n var _scanner = createScanner(text), parts = [], kind, offset = 0, pos;\n do {\n pos = _scanner.getPosition();\n kind = _scanner.scan();\n switch (kind) {\n case 12 /* LineCommentTrivia */:\n case 13 /* BlockCommentTrivia */:\n case 17 /* EOF */:\n if (offset !== pos) {\n parts.push(text.substring(offset, pos));\n }\n if (replaceCh !== undefined) {\n parts.push(_scanner.getTokenValue().replace(/[^\\r\\n]/g, replaceCh));\n }\n offset = _scanner.getPosition();\n break;\n }\n } while (kind !== 17 /* EOF */);\n return parts.join('');\n}\nexport function getNodeType(value) {\n switch (typeof value) {\n case 'boolean': return 'boolean';\n case 'number': return 'number';\n case 'string': return 'string';\n case 'object': {\n if (!value) {\n return 'null';\n }\n else if (Array.isArray(value)) {\n return 'array';\n }\n return 'object';\n }\n default: return 'null';\n }\n}\n","import{cloneDeep as e,get as t,set as r,has as n,setWith as o,omit as i,trimStart as a}from\"lodash\";import{isAbsolute as s,join as c,dirname as u}from\"@stoplight/path\";import{createScanner as l,findNodeAtOffset as f,getNodePath as p,visit as h,printParseErrorCode as y}from\"jsonc-parser\";import g,{getOrder as d,ORDER_KEY_ID as m}from\"@stoplight/ordered-object-literal\";import{DiagnosticSeverity as v}from\"@stoplight/types\";import b from\"safe-stable-stringify\";function w(e){if(\"object\"!=typeof e||null===e)return!1;const t=Object.getPrototypeOf(e);return null===t||t===Object.prototype||\"function\"==typeof e.constructor&&Function.toString.call(Object)===Function.toString.call(e.constructor)}function O(e,t,r){if(!w(e)&&!Array.isArray(e)||!(t in e))throw new ReferenceError(`Could not resolve '${r}'`)}function j(e){if(\"string\"!=typeof e.$ref)throw new TypeError(\"$ref should be a string\")}const A=e=>w(e)&&\"$ref\"in e,$=e=>A(e)&&\"string\"==typeof e.$ref,E=e=>e.length>0&&(\"#\"===e||/^#\\S*$/.test(e)),S=(e,t,r)=>{const n=e.toString();let o=\"\",i=n,a=0,s=i.indexOf(t);for(;s>-1;)o+=n.substring(a,a+s)+r,i=i.substring(s+t.length,i.length),a+=s+t.length,s=i.indexOf(t);return i.length>0&&(o+=n.substring(n.length-i.length,n.length)),o},x=e=>\"number\"==typeof e?e:S(S(e,\"~\",\"~0\"),\"/\",\"~1\"),_=/[^a-zA–Z0–9_.!~*'()\\/\\-\\u{D800}-\\u{DFFF}]/gu;function N(e){return e.replace(_,encodeURIComponent)}const k=e=>{const t=x(e);return\"number\"==typeof t?t:N(t)},P=e=>I(e),I=e=>{if(e&&\"object\"!=typeof e)throw new TypeError(\"Invalid type: path must be an array of segments.\");return 0===e.length?\"#\":`#/${e.map(k).join(\"/\")}`};function T(e){try{return decodeURIComponent(e)}catch(t){return e}}const R=/%[0-9a-f]+/gi,U=e=>{let t;try{t=decodeURIComponent(e)}catch(r){t=e.replace(R,T)}return S(S(t,\"~1\",\"/\"),\"~0\",\"~\")},K=e=>J(e),J=e=>{if(\"string\"!=typeof e)throw new TypeError(\"Invalid type: JSON Pointers are represented as strings.\");if(0===e.length||\"#\"!==e[0])throw new URIError(\"Invalid JSON Pointer syntax; URI fragment identifiers must begin with a hash.\");if(1===e.length)return[];if(\"/\"!==e[1])throw new URIError(\"Invalid JSON Pointer syntax.\");return(e=>{const t=e.length,r=[];let n=-1;for(;++n{const n={value:e,path:r};t.onEnter&&t.onEnter(n);for(const n of Object.keys(e)){const o=e[n];t.onProperty&&t.onProperty({parent:e,parentPath:r,property:n,propertyValue:o}),\"object\"==typeof o&&null!==o&&C(o,t,r.concat(n))}t.onLeave&&t.onLeave(n)},D=(e,t)=>{\"object\"==typeof e&&null!==e&&C(e,\"function\"==typeof t?{onProperty:t}:t,[])};function F(e,t,r){D(e,{onProperty({property:e,propertyValue:n,parent:o}){\"$ref\"===e&&\"string\"==typeof n&&n.startsWith(t)&&(o.$ref=`${r}${n.slice(t.length)}`)}})}const M=e=>e.length>0&&\"#\"!==e[0],V=e=>{if(\"string\"!=typeof e||0===e.length||!M(e))return null;const t=e.indexOf(\"#\");return-1===t?e:e.slice(0,t)};function W(e,t){return w(t)&&w(e)&&(\"summary\"in e||\"description\"in e)?Object.assign(Object.assign(Object.assign({},t),\"description\"in e?{description:e.description}:null),\"summary\"in e?{summary:e.summary}:null):t}function*L(e,t,r){A(e.value)&&(j(e.value),yield[-1,e.value]);for(const[n,o]of t.entries())O(e.value,o,r),e.value=e.value[o],A(e.value)&&(j(e.value),yield[n,e.value])}function B(e,t){return z(e,t).value}function z(e,t){return function e(t,r,n,o){if(null!==V(r))throw new ReferenceError(\"Cannot resolve external references\");const i=K(r);let a=[...i];\"#\"===r&&A(t)&&(j(t),i.unshift(...K(t.$ref)));const s={value:t};for(const[c,u]of L(s,i,r)){if(n.includes(u))return{source:null,location:null!=o?o:a,value:n[n.length-1]};n.push(u);const r=e(t,u.$ref,n,a);s.value=r.value,(a=r.location).push(...i.slice(c+1))}return{source:null,location:a,value:n.length>0?W(n[n.length-1],s.value):s.value}}(e,t,[])}const Z=\"#/__bundled__\",q=\"#/__errors__\",G=({document:t,path:r,bundleRoot:n=\"#/__bundled__\",errorsRoot:o=\"#/__errors__\",cloneDocument:i=!0,keyProvider:a},s)=>{if(r===n||r===o)throw new Error(\"Roots do not make any sense\");const c=i?e(t):t;return H(c,K(n),K(o),r,a)(r,{[r]:!0},s)},H=(e,a,s,c,u)=>{const l=new Set,f=(p,h,y,g={},d={},m={})=>{const v=K(p),b=t(e,v);D(y||b,{onEnter:({value:s})=>{if($(s)&&E(s.$ref)){const y=s.$ref;if(m[y])return;if(y===p&&(g[y]=\"#\"),g[y])return void(s.$ref=g[y]);let v,b,w,O,j;try{let r;v=K(y),u&&(r=u({document:e,path:v})),r||(r=(({document:e,path:r})=>{if(0===r.length)return\"root\";if(Array.isArray(t(e,r.slice(0,-1))))return`${r[r.length-2]}_${r[r.length-1]}`;return String(r[r.length-1])})({document:e,path:v})),w=r;let n=1;for(;l.has(w);)if(w=`${r}_${++n}`,n>20)throw new Error(`Keys ${r}_2 through ${r}_20 already taken.`);l.add(w),b=[...a,w],O=P(b)}catch(e){m[y]=e instanceof Error?e.message:String(e)}if(!v||!b||!O)return;if(\"object\"==typeof e&&null!==e&&!(j=t(e,v)))try{j=B(Object(e),y)}catch(e){}void 0!==j&&(g[y]=O,s.$ref=O,n(d,b)||(Array.isArray(j)?r(d,b,new Array(j.length).fill(null)):\"object\"==typeof j&&o(d,b,{},Object),r(d,b,j),\"#\"===y?function(e,t,n,o){const a=n.map(e=>`[${JSON.stringify(e)}]`).join(\"\"),s=JSON.parse(JSON.stringify(i(Object(e),a))),c={};r(t,o,s),r(s,n,c),F(s,\"#\",P(o)),c.$ref=\"#\"}(e,d,K(c),b):h[y]||(h[y]=!0,f(p,h,j,g,d,m),h[y]=!1)))}}});const w=t(d,a);return w&&Object.keys(w).length&&r(b,a,w),(Object.keys(m).length||n(e,s))&&r(b,s,n(e,s)?t(e,s):m),b};return f};const Q=e=>S(S(e,\"~1\",\"/\"),\"~0\",\"~\"),X=(e,t)=>{const r=new WeakMap;return function e(n,o){let i;if(t&&(n=t(n)),w(n)||Array.isArray(n)){const t=r.get(n);return t?{$ref:t}:(r.set(n,P(o)),Array.isArray(n)?i=n.map((t,r)=>e(t,[...o,String(r)])):(i={},Object.keys(n).forEach(t=>{i[t]=e(n[t],[...o,t])})),r.delete(n),i)}return n}(e,[])},Y=e=>S(S(e,\"~\",\"~0\"),\"//\",\"/~1\"),ee=e=>{if(\"string\"!=typeof e||0===e.length)return null;const t=e.indexOf(\"#\");return-1===t?null:e.slice(t)},te=e=>{const t=l(e,!0);if(t.scan(),1!==t.getToken())return;if(t.scan(),2===t.getToken())return;if(10!==t.getToken())throw new SyntaxError(\"Unexpected character\");const r=t.getTokenValue();if(t.scan(),6!==t.getToken())throw new SyntaxError(\"Colon expected\");switch(t.scan(),t.getToken()){case 10:return[r,t.getTokenValue()];case 11:return[r,Number(t.getTokenValue())];case 8:return[r,!0];case 9:return[r,!1];case 7:return[r,null];case 16:throw new SyntaxError(\"Unexpected character\");case 17:throw new SyntaxError(\"Unexpected end of file\");default:return}},re=({lineMap:e,ast:t},r)=>{const n=e[r.line],o=e[r.line+1];if(void 0===n)return;const i=f(t,void 0===o?n+r.character:Math.min(o,n+r.character),!0);if(void 0===i)return;const a=p(i);return 0!==a.length?a:void 0};function ne(e){return Q(e.split(\"/\").pop()||\"\")}const oe=({ast:e},t,r=!1)=>{const n=function(e,t,r){e:for(const n of t){const t=Number.isInteger(Number(n))?Number(n):n;if(\"string\"==typeof t||\"number\"==typeof t&&\"array\"!==e.type){if(\"object\"!==e.type||!Array.isArray(e.children))return r?e:void 0;for(const r of e.children)if(Array.isArray(r.children)&&r.children[0].value===String(t)&&2===r.children.length){e=r.children[1];continue e}return r?e:void 0}if(\"array\"!==e.type||t<0||!Array.isArray(e.children)||t>=e.children.length)return r?e:void 0;e=e.children[t]}return e}(e,t,r);if(void 0!==n&&void 0!==n.range)return{range:n.range}};const ie=(e,t={disallowComments:!0})=>{const r=[],{ast:n,data:o,lineMap:i}=ae(e,r,t);return{data:o,diagnostics:r,ast:n,lineMap:i}};function ae(e,t=[],r){const n=ce(e);let o={type:\"array\",offset:-1,length:-1,children:[],parent:void 0},i=null,a=[];const s=new WeakMap,c=[];function u(e){\"property\"===o.type&&(o.length=e-o.offset,o=o.parent)}function l(e,t,r){return{start:{line:e,character:t},end:{line:e,character:t+r}}}function f(e){return o.children.push(e),e}function p(e){Array.isArray(a)?a.push(e):null!==i&&(a[i]=e)}function m(e){p(e),c.push(a),a=e,i=null}function b(){a=c.pop()}h(e,{onObjectBegin:(e,t,n,i)=>{o=f({type:\"object\",offset:e,length:-1,parent:o,children:[],range:l(n,i,t)}),!1===r.ignoreDuplicateKeys&&s.set(o,[]),m(function(e){return e?g({}):{}}(!0===r.preserveKeyOrder))},onObjectProperty:(e,n,c,u,p)=>{if((o=f({type:\"property\",offset:n,length:-1,parent:o,children:[]})).children.push({type:\"string\",value:e,offset:n,length:c,parent:o}),!1===r.ignoreDuplicateKeys){const r=s.get(o.parent);r&&(0!==r.length&&r.includes(e)?t.push({range:l(u,p,c),message:\"DuplicateKey\",severity:v.Error,path:ue(o),code:20}):r.push(e))}!0===r.preserveKeyOrder&&function(e,t){if(!(t in e))return;const r=d(e),n=r.indexOf(t);-1!==n&&(r.splice(n,1),r.push(t))}(a,e),i=e},onObjectEnd:(e,t,n,i)=>{!1===r.ignoreDuplicateKeys&&s.delete(o),o.length=e+t-o.offset,o.range&&(o.range.end.line=n,o.range.end.character=i+t),o=o.parent,u(e+t),b()},onArrayBegin:(e,t,r,n)=>{o=f({type:\"array\",offset:e,length:-1,parent:o,children:[],range:l(r,n,t)}),m([])},onArrayEnd:(e,t,r,n)=>{o.length=e+t-o.offset,o.range&&(o.range.end.line=r,o.range.end.character=n+t),o=o.parent,u(e+t),b()},onLiteralValue:(e,t,r,n,i)=>{f({type:se(e),offset:t,length:r,parent:o,value:e,range:l(n,i,r)}),u(t+r),p(e)},onSeparator:(e,t)=>{\"property\"===o.type&&(\":\"===e?o.colonOffset=t:\",\"===e&&u(t))},onError:(e,r,n,o,i)=>{t.push({range:l(o,i,n),message:y(e),severity:v.Error,code:e})}},r);const w=o.children[0];return w&&delete w.parent,{ast:w,data:a[0],lineMap:n}}function se(e){switch(typeof e){case\"boolean\":return\"boolean\";case\"number\":return\"number\";case\"string\":return\"string\";default:return\"null\"}}const ce=e=>{const t=[0];let r=0;for(;r{if(!e||!Object.hasOwnProperty.call(e,t)||t===r)return e;const n={};for(const[o,i]of Object.entries(e))o===t?n[r]=i:o in n||(n[o]=i);return n};function fe(e){return w(e)||Array.isArray(e)}function pe(e,t,r){if(r.length<=1||t.length<=1)throw Error(\"Source/target path must not be empty and point at root\");if(0===t.indexOf(r))throw Error(\"Target path cannot be contained within source\");const n=K(t);let o=e;for(const e of n){if(!fe(o))return;o=o[e]}if(!fe(o))return;const i=K(r);let a=e;for(const[e,t]of i.entries()){if(!fe(a)||t in a)return;const r=e===i.length-1?o:{};a[t]=r,a=r}delete e[n[0]],function e(t,r,n){for(const o of Object.keys(t)){const i=t[o];if(\"$ref\"!==o)fe(i)&&e(i,r,n);else{if(\"string\"!=typeof i||!E(i))continue;0===i.indexOf(r)&&(t[o]=i.replace(r,n))}}}(e,t,r)}async function he(e,t,r,n,o){let i=function(e,t){const r=V(t);return null===r?e:s(r)?r:c(u(e),r)}(t,r);const a=ee(r)||\"#\",l=await e[i],f=K(a);let p=[...f];const h={value:l};for(const[r,s]of L(h,f,a)){if(n.includes(s))return{source:t,location:null!=o?o:p,value:n[n.length-1]};n.push(s);const a=await he(e,i,s.$ref,n,p);({source:i,location:p}=a),h.value=a.value,p.push(...f.slice(r+1))}return{source:i,location:p,value:n.length>0?W(n[n.length-1],h.value):h.value}}async function ye(e,t,r){return(await ge(e,t,r)).value}function ge(e,t,r){return he(e,t,r,[])}const de=(e,t)=>{if(\"string\"!=typeof e)return e;try{const r=me(e);return\"string\"==typeof r?r:JSON.parse(e,t)}catch(e){return}},me=e=>{const t=Number(e);return Number.isFinite(t)?String(t)===e?t:e:NaN},ve=(e,t,r)=>{if(\"string\"==typeof e)return e;try{return JSON.stringify(e,t,r)}catch(n){return b(e,t,r)}},be=(e,t)=>{if(e instanceof Array){if(t instanceof Array){if(t.length>e.length)return!1;for(const r in t){if(!t.hasOwnProperty(r))continue;const n=parseInt(e[r]),o=parseInt(t[r]);if(isNaN(n)&&isNaN(o)){if(e[r]!==t[r])return!1}else if(n!==o)return!1}}}else{if(\"string\"!=typeof e)return!1;if(\"string\"==typeof t)return e.startsWith(t)}return!0},we=(e,t,r)=>{const n=ve(e,t,r);if(void 0===n)throw new Error(\"The value could not be stringified\");return n};function Oe(e){return e.replace(/^(\\/|#\\/)/,\"\").split(\"/\").map(Q).map(je).join(\".\")}function je(e){return e.includes(\".\")?`[\"${e.replace(/\"/g,'\\\\\"')}\"]`:e}const Ae=Symbol.for(m),$e={ownKeys:e=>Ae in e?e[Ae]:Reflect.ownKeys(e)},Ee=e=>new Proxy(e,$e);function Se(e,t){if(\"string\"==typeof e&&\"string\"==typeof t)return a(e,t);if(!(e&&Array.isArray(e)&&e.length&&t&&Array.isArray(t)&&t.length))return e;let r=0;for(const n in e)if(e.hasOwnProperty(n)){if(e[n]!==t[n])break;r++}return e.slice(r)}export{Z as BUNDLE_ROOT,q as ERRORS_ROOT,Ae as KEYS,G as bundleTarget,U as decodePointer,Q as decodePointerFragment,U as decodePointerUriFragment,X as decycle,Y as encodePointer,x as encodePointerFragment,k as encodePointerUriFragment,N as encodeUriPointer,ee as extractPointerFromRef,V as extractSourceFromRef,te as getFirstPrimitiveProperty,re as getJsonPathForPosition,ne as getLastPathSegment,oe as getLocationForJsonPath,$ as hasRef,M as isExternalRef,E as isLocalRef,w as isPlainObject,ae as parseTree,ie as parseWithPointers,P as pathToPointer,K as pointerToPath,F as remapRefs,le as renameObjectKey,pe as reparentBundleTarget,ye as resolveExternalRef,ge as resolveExternalRefWithLocation,B as resolveInlineRef,z as resolveInlineRefWithLocation,de as safeParse,ve as safeStringify,be as startsWith,we as stringify,Oe as toPropertyPath,Ee as trapAccess,D as traverse,Se as trimStart};\n","export default function (err) {\n return new Proxy(err, {\n getOwnPropertyDescriptor(target, key) {\n for (const prototype of traversePrototypeUntilErrorPrototype(target)) {\n if (Object.hasOwnProperty.call(prototype, key)) {\n const descriptor = Reflect.getOwnPropertyDescriptor(prototype, key);\n descriptor.enumerable = true;\n return descriptor;\n }\n }\n },\n\n ownKeys(target) {\n const keys = [];\n for (const prototype of traversePrototypeUntilErrorPrototype(target)) {\n for (const key of Reflect.ownKeys(prototype)) {\n if (!keys.includes(key)) {\n keys.push(key);\n }\n }\n }\n\n return keys;\n },\n\n set(target, key, value) {\n return Reflect.set(target, key, value);\n },\n });\n}\n\nfunction* traversePrototypeUntilErrorPrototype(prototype) {\n while (prototype !== null && prototype !== Error.prototype) {\n yield prototype;\n prototype = Object.getPrototypeOf(prototype);\n }\n}\n","import type { MirroredRegularNode } from './mirrored';\nimport type { RegularNode } from './RegularNode';\nimport type { RootNode } from './RootNode';\n\nlet SEED = BigInt(0); // cannot use literal, cause TS.\n\nexport abstract class BaseNode {\n public readonly id: string;\n\n public parent: RegularNode | RootNode | MirroredRegularNode | null = null;\n public subpath: string[];\n\n public get path(): ReadonlyArray {\n return this.parent === null ? this.subpath : [...this.parent.path, ...this.subpath];\n }\n\n public get depth(): number {\n return this.parent === null ? 0 : this.parent.depth + 1;\n }\n\n private get parentChildren(): BaseNode[] {\n return (this.parent?.children ?? []) as BaseNode[];\n }\n\n public get pos(): number {\n return Math.max(0, this.parentChildren.indexOf(this));\n }\n\n public get isFirst(): boolean {\n return this.pos === 0;\n }\n\n public get isLast(): boolean {\n return this.pos === this.parentChildren.length - 1;\n }\n\n protected constructor() {\n this.id = String(SEED++);\n this.subpath = [];\n }\n}\n","import { BaseNode } from './BaseNode';\n\nexport class BooleanishNode extends BaseNode {\n constructor(public readonly fragment: boolean) {\n super();\n }\n}\n","import type { SchemaFragment } from '../../types';\nimport { BaseNode } from '../BaseNode';\nimport type { ReferenceNode } from '../ReferenceNode';\n\nexport class MirroredReferenceNode extends BaseNode implements ReferenceNode {\n public readonly fragment: SchemaFragment;\n\n constructor(public readonly mirroredNode: ReferenceNode) {\n super();\n this.fragment = mirroredNode.fragment;\n }\n\n get error() {\n return this.mirroredNode.error;\n }\n\n get value() {\n return this.mirroredNode.value;\n }\n\n public get external() {\n return this.mirroredNode.external;\n }\n}\n","import type { Dictionary } from '@stoplight/types';\n\nimport type { SchemaFragment } from '../types';\n\nexport function isStringOrNumber(value: unknown): value is number | string {\n return typeof value === 'string' || typeof value === 'number';\n}\n\nexport function isObject(maybeObj: unknown): maybeObj is object {\n return maybeObj !== void 0 && maybeObj !== null && typeof maybeObj === 'object';\n}\n\nexport function isPrimitive(\n maybePrimitive: unknown,\n): maybePrimitive is string | number | boolean | undefined | null | symbol | bigint {\n return typeof maybePrimitive !== 'function' && !isObject(maybePrimitive);\n}\n\nexport function isObjectLiteral(maybeObj: unknown): maybeObj is Dictionary {\n if (isPrimitive(maybeObj) === true) return false;\n const proto = Object.getPrototypeOf(maybeObj);\n return proto === null || proto === Object.prototype;\n}\n\nexport function isNonNullable(maybeNullable: T): maybeNullable is NonNullable {\n return maybeNullable !== void 0 && maybeNullable !== null;\n}\n\nexport function isValidSchemaFragment(maybeSchemaFragment: unknown): maybeSchemaFragment is SchemaFragment {\n return typeof maybeSchemaFragment === 'boolean' || isObjectLiteral(maybeSchemaFragment);\n}\n","import type { Dictionary } from '@stoplight/types';\n\nexport function pick(target: object, keys: readonly (string | number)[]) {\n const source: Dictionary = {};\n\n for (const key of keys) {\n if (key in target) {\n source[key] = target[key];\n }\n }\n\n return source;\n}\n","import type { Dictionary } from '@stoplight/types';\n\nimport { isReferenceNode, isRegularNode } from '../../guards';\nimport type { SchemaFragment } from '../../types';\nimport { isNonNullable } from '../../utils';\nimport { BaseNode } from '../BaseNode';\nimport { BooleanishNode } from '../BooleanishNode';\nimport type { ReferenceNode } from '../ReferenceNode';\nimport type { RegularNode } from '../RegularNode';\nimport type { SchemaAnnotations, SchemaCombinerName, SchemaNodeKind } from '../types';\nimport { MirroredReferenceNode } from './MirroredReferenceNode';\n\nexport class MirroredRegularNode extends BaseNode implements RegularNode {\n public readonly fragment: SchemaFragment;\n public readonly $id!: string | null;\n public readonly types!: SchemaNodeKind[] | null;\n public readonly primaryType!: SchemaNodeKind | null;\n public readonly combiners!: SchemaCombinerName[] | null;\n\n public readonly required!: string[] | null;\n public readonly enum!: unknown[] | null;\n public readonly format!: string | null;\n public readonly title!: string | null;\n public readonly deprecated!: boolean;\n\n public readonly annotations!: Readonly>>;\n public readonly validations!: Readonly>;\n public readonly originalFragment!: SchemaFragment;\n\n public readonly simple!: boolean;\n public readonly unknown!: boolean;\n\n private readonly cache: WeakMap<\n RegularNode | BooleanishNode | ReferenceNode,\n MirroredRegularNode | BooleanishNode | MirroredReferenceNode\n >;\n\n constructor(public readonly mirroredNode: RegularNode, context?: { originalFragment?: SchemaFragment }) {\n super();\n this.fragment = mirroredNode.fragment;\n this.originalFragment = context?.originalFragment ?? mirroredNode.originalFragment;\n\n this.cache = new WeakMap();\n\n this._this = new Proxy(this, {\n get(target, key) {\n if (key in target) {\n return target[key];\n }\n\n if (key in mirroredNode) {\n return Reflect.get(mirroredNode, key, mirroredNode);\n }\n\n return;\n },\n\n has(target, key) {\n return key in target || key in mirroredNode;\n },\n });\n\n return this._this;\n }\n\n private readonly _this: MirroredRegularNode;\n\n private _children?: (MirroredRegularNode | BooleanishNode | MirroredReferenceNode)[];\n\n public get children(): (MirroredRegularNode | BooleanishNode | MirroredReferenceNode)[] | null | undefined {\n const referencedChildren = this.mirroredNode.children;\n\n if (!isNonNullable(referencedChildren)) {\n return referencedChildren;\n }\n\n if (this._children === void 0) {\n this._children = [];\n } else {\n this._children.length = 0;\n }\n\n const children: (MirroredRegularNode | BooleanishNode | MirroredReferenceNode)[] = this._children;\n for (const child of referencedChildren) {\n // this is to avoid pointing at nested mirroring\n const cached = this.cache.get(child);\n\n if (cached !== void 0) {\n children.push(cached);\n continue;\n }\n\n const mirroredChild = isRegularNode(child)\n ? new MirroredRegularNode(child)\n : isReferenceNode(child)\n ? new MirroredReferenceNode(child)\n : new BooleanishNode(child.fragment);\n\n mirroredChild.parent = this._this;\n mirroredChild.subpath = child.subpath;\n this.cache.set(child, mirroredChild);\n children.push(mirroredChild);\n }\n\n return children;\n }\n}\n","export function unwrapStringOrNull(value: unknown): string | null {\n return typeof value === 'string' ? value : null;\n}\n\nexport function unwrapArrayOrNull(value: unknown): unknown[] | null {\n return Array.isArray(value) ? value : null;\n}\n","import { isLocalRef } from '@stoplight/json';\n\nimport { unwrapStringOrNull } from '../accessors/unwrap';\nimport type { SchemaFragment } from '../types';\nimport { BaseNode } from './BaseNode';\n\nexport class ReferenceNode extends BaseNode {\n public readonly value: string | null;\n\n constructor(public readonly fragment: SchemaFragment, public readonly error: string | null) {\n super();\n\n this.value = unwrapStringOrNull(fragment.$ref);\n }\n\n public get external() {\n return this.value !== null && !isLocalRef(this.value);\n }\n}\n","import type { SchemaFragment } from '../types';\nimport { pick } from '../utils/pick';\n\nconst ANNOTATIONS = ['description', 'default', 'examples'] as const;\n\nexport type SchemaAnnotations = typeof ANNOTATIONS[number];\n\nexport function getAnnotations(fragment: SchemaFragment) {\n const annotations = pick(fragment, ANNOTATIONS);\n if ('example' in fragment && !Array.isArray(annotations.examples)) {\n // example is more OAS-ish, but it's common enough to be worth supporting\n annotations.examples = [fragment.example];\n }\n\n return annotations;\n}\n","import type { BooleanishNode } from './BooleanishNode';\nimport type { MirroredReferenceNode } from './mirrored/MirroredReferenceNode';\nimport type { MirroredRegularNode } from './mirrored/MirroredRegularNode';\nimport type { ReferenceNode } from './ReferenceNode';\nimport type { RegularNode } from './RegularNode';\nimport type { RootNode } from './RootNode';\n\nexport type MirroredSchemaNode = MirroredRegularNode | MirroredReferenceNode;\n\nexport type SchemaNode = RootNode | RegularNode | BooleanishNode | ReferenceNode | MirroredSchemaNode;\n\nexport enum SchemaNodeKind {\n Any = 'any',\n String = 'string',\n Number = 'number',\n Integer = 'integer',\n Boolean = 'boolean',\n Null = 'null',\n Array = 'array',\n Object = 'object',\n}\n\nexport enum SchemaCombinerName {\n AllOf = 'allOf',\n AnyOf = 'anyOf',\n OneOf = 'oneOf',\n}\n\nexport { SchemaAnnotations } from '../accessors/getAnnotations';\n","import { SchemaCombinerName } from '../nodes/types';\nimport type { SchemaFragment } from '../types';\n\nexport function getCombiners(fragment: SchemaFragment): SchemaCombinerName[] | null {\n let combiners: SchemaCombinerName[] | null = null;\n\n if (SchemaCombinerName.AnyOf in fragment) {\n combiners ??= [];\n combiners.push(SchemaCombinerName.AnyOf);\n }\n\n if (SchemaCombinerName.OneOf in fragment) {\n combiners ??= [];\n combiners.push(SchemaCombinerName.OneOf);\n }\n\n if (SchemaCombinerName.AllOf in fragment) {\n combiners ??= [];\n combiners.push(SchemaCombinerName.AllOf);\n }\n\n return combiners;\n}\n","import { SchemaNodeKind } from '../nodes/types';\nimport type { SchemaFragment } from '../types';\n\nexport function getPrimaryType(fragment: SchemaFragment, types: SchemaNodeKind[] | null) {\n if (types !== null) {\n if (types.includes(SchemaNodeKind.Object)) {\n return SchemaNodeKind.Object;\n }\n\n if (types.includes(SchemaNodeKind.Array)) {\n return SchemaNodeKind.Array;\n }\n\n if (types.length > 0) {\n return types[0];\n }\n\n return null;\n }\n\n return null;\n}\n","import { isStringOrNumber } from '../utils/guards';\n\nexport function getRequired(required: unknown): string[] | null {\n if (!Array.isArray(required)) return null;\n return required.filter(isStringOrNumber).map(String);\n}\n","import { SchemaNodeKind } from '../../nodes/types';\n\nconst VALID_TYPES = Object.values(SchemaNodeKind);\n\nexport const isValidType = (maybeType: unknown): maybeType is SchemaNodeKind =>\n typeof maybeType === 'string' && VALID_TYPES.includes(maybeType as SchemaNodeKind);\n","import { SchemaNodeKind } from '../nodes/types';\nimport type { SchemaFragment } from '../types';\n\nexport function inferType(fragment: SchemaFragment): SchemaNodeKind | null {\n if ('properties' in fragment || 'additionalProperties' in fragment || 'patternProperties' in fragment) {\n return SchemaNodeKind.Object;\n }\n\n if ('items' in fragment || 'additionalItems' in fragment) {\n return SchemaNodeKind.Array;\n }\n\n return null;\n}\n","import { SchemaNodeKind } from '../nodes/types';\nimport type { SchemaFragment } from '../types';\nimport { isValidType } from './guards/isValidType';\nimport { inferType } from './inferType';\n\nexport function getTypes(fragment: SchemaFragment): SchemaNodeKind[] | null {\n const types: SchemaNodeKind[] = [];\n let isNullable = false;\n\n if ('nullable' in fragment) {\n if (fragment.nullable === true) {\n isNullable = true;\n }\n }\n if ('type' in fragment) {\n if (Array.isArray(fragment.type)) {\n types.push(...fragment.type.filter(isValidType));\n } else if (isValidType(fragment.type)) {\n types.push(fragment.type);\n }\n if (isNullable && !types.includes(SchemaNodeKind.Null)) {\n types.push(SchemaNodeKind.Null);\n }\n return types;\n }\n\n const inferredType = inferType(fragment);\n if (inferredType !== null) {\n types.push(inferredType);\n if (isNullable && !types.includes(SchemaNodeKind.Null)) {\n types.push(SchemaNodeKind.Null);\n }\n return types;\n }\n\n return null;\n}\n","import type { Dictionary } from '@stoplight/types';\n\nimport type { SchemaNodeKind } from '../nodes/types';\nimport type { SchemaFragment } from '../types';\nimport { pick } from '../utils/pick';\n\nexport const COMMON_VALIDATION_TYPES: string[] = ['readOnly', 'writeOnly', 'style'];\n\nconst VALIDATION_TYPES: Partial> = {\n string: ['minLength', 'maxLength', 'pattern'],\n number: ['multipleOf', 'minimum', 'exclusiveMinimum', 'maximum', 'exclusiveMaximum'],\n get integer() {\n return this.number;\n },\n object: ['minProperties', 'maxProperties'],\n array: ['minItems', 'maxItems', 'uniqueItems'],\n};\n\nfunction getTypeValidations(types: SchemaNodeKind[]): (keyof SchemaFragment)[] | null {\n let extraValidations: (keyof SchemaFragment)[] | null = null;\n\n for (const type of types) {\n const value = VALIDATION_TYPES[type];\n if (value !== void 0) {\n extraValidations ??= [];\n extraValidations.push(...value);\n }\n }\n\n return extraValidations;\n}\n\nexport function getValidations(fragment: SchemaFragment, types: SchemaNodeKind[] | null): Dictionary {\n const extraValidations = types === null ? null : getTypeValidations(types);\n\n return {\n ...pick(fragment, COMMON_VALIDATION_TYPES),\n ...(extraValidations !== null ? pick(fragment, extraValidations) : null),\n };\n}\n","import type { SchemaFragment } from '../types';\n\nexport function isDeprecated(fragment: SchemaFragment): boolean {\n if ('x-deprecated' in fragment) {\n return fragment['x-deprecated'] === true;\n }\n\n if ('deprecated' in fragment) {\n return fragment.deprecated === true;\n }\n\n return false;\n}\n","import type { Dictionary } from '@stoplight/types';\n\nimport { getAnnotations } from '../accessors/getAnnotations';\nimport { getCombiners } from '../accessors/getCombiners';\nimport { getPrimaryType } from '../accessors/getPrimaryType';\nimport { getRequired } from '../accessors/getRequired';\nimport { getTypes } from '../accessors/getTypes';\nimport { getValidations } from '../accessors/getValidations';\nimport { isDeprecated } from '../accessors/isDeprecated';\nimport { unwrapArrayOrNull, unwrapStringOrNull } from '../accessors/unwrap';\nimport type { SchemaFragment } from '../types';\nimport { BaseNode } from './BaseNode';\nimport type { BooleanishNode } from './BooleanishNode';\nimport type { ReferenceNode } from './ReferenceNode';\nimport { MirroredSchemaNode, SchemaAnnotations, SchemaCombinerName, SchemaNodeKind } from './types';\n\nexport class RegularNode extends BaseNode {\n public readonly $id: string | null;\n public readonly types: SchemaNodeKind[] | null;\n public readonly primaryType: SchemaNodeKind | null; // object (first choice) or array (second option), primitive last\n public readonly combiners: SchemaCombinerName[] | null;\n\n public readonly required: string[] | null;\n public readonly enum: unknown[] | null; // https://tools.ietf.org/html/draft-fge-json-schema-validation-00#section-5.5.1\n public readonly format: string | null; // https://tools.ietf.org/html/draft-fge-json-schema-validation-00#section-7\n public readonly title: string | null;\n public readonly deprecated: boolean;\n\n public children: (RegularNode | BooleanishNode | ReferenceNode | MirroredSchemaNode)[] | null | undefined;\n\n public readonly annotations: Readonly>>;\n public readonly validations: Readonly>;\n public readonly originalFragment: SchemaFragment;\n\n constructor(public readonly fragment: SchemaFragment, context?: { originalFragment?: SchemaFragment }) {\n super();\n\n this.$id = unwrapStringOrNull('id' in fragment ? fragment.id : fragment.$id);\n this.types = getTypes(fragment);\n this.primaryType = getPrimaryType(fragment, this.types);\n this.combiners = getCombiners(fragment);\n\n this.deprecated = isDeprecated(fragment);\n this.enum = 'const' in fragment ? [fragment.const] : unwrapArrayOrNull(fragment.enum);\n this.required = getRequired(fragment.required);\n this.format = unwrapStringOrNull(fragment.format);\n this.title = unwrapStringOrNull(fragment.title);\n\n this.annotations = getAnnotations(fragment);\n this.validations = getValidations(fragment, this.types);\n this.originalFragment = context?.originalFragment ?? fragment;\n\n this.children = void 0;\n }\n\n public get simple() {\n return (\n this.primaryType !== SchemaNodeKind.Array && this.primaryType !== SchemaNodeKind.Object && this.combiners === null\n );\n }\n\n public get unknown() {\n return (\n this.types === null &&\n this.combiners === null &&\n this.format === null &&\n this.enum === null &&\n Object.keys(this.annotations).length + Object.keys(this.validations).length === 0\n );\n }\n}\n","import type { SchemaFragment } from '../types';\nimport { BaseNode } from './BaseNode';\nimport type { SchemaNode } from './types';\n\nexport class RootNode extends BaseNode {\n public readonly parent = null;\n public readonly children: SchemaNode[];\n\n constructor(public readonly fragment: SchemaFragment) {\n super();\n this.children = [];\n }\n}\n","import {\n MirroredReferenceNode,\n MirroredRegularNode,\n MirroredSchemaNode,\n ReferenceNode,\n RegularNode,\n RootNode,\n SchemaNode,\n} from '../nodes';\nimport type { BooleanishNode } from '../nodes/BooleanishNode';\n\nexport function isSchemaNode(node: unknown): node is SchemaNode {\n const name = Object.getPrototypeOf(node).constructor.name;\n return (\n name === RootNode.name ||\n name === RegularNode.name ||\n name === MirroredRegularNode.name ||\n name === ReferenceNode.name ||\n name === MirroredReferenceNode.name\n );\n}\n\nexport function isRootNode(node: SchemaNode): node is RootNode {\n return Object.getPrototypeOf(node).constructor.name === 'RootNode';\n}\n\nexport function isRegularNode(node: SchemaNode): node is RegularNode {\n return 'types' in node && 'primaryType' in node && 'combiners' in node;\n}\n\nexport function isMirroredNode(node: SchemaNode): node is MirroredSchemaNode {\n return 'mirroredNode' in node;\n}\n\nexport function isReferenceNode(node: SchemaNode): node is ReferenceNode {\n return 'external' in node && 'value' in node;\n}\n\nexport function isBooleanishNode(node: SchemaNode): node is BooleanishNode {\n return typeof node.fragment === 'boolean';\n}\n","export class ResolvingError extends ReferenceError {\n public readonly name = 'ResolvingError';\n}\n\nexport class MergingError extends Error {\n public readonly name = 'MergingError';\n}\n","import { pathToPointer } from '@stoplight/json';\n\nimport { ResolvingError } from '../errors';\nimport type { SchemaFragment } from '../types';\nimport type { WalkerRefResolver, WalkingOptions } from '../walker/types';\n\nconst resolveAllOf = require('@stoplight/json-schema-merge-allof');\n\nconst store = new WeakMap>();\n\nfunction _mergeAllOf(\n fragment: SchemaFragment,\n path: string[],\n resolveRef: WalkerRefResolver | null,\n seen: WeakMap,\n): SchemaFragment {\n const cached = seen.get(fragment);\n if (cached !== void 0) {\n return cached;\n }\n\n const merged = resolveAllOf(fragment, {\n deep: false,\n resolvers: resolveAllOf.stoplightResolvers,\n ...(resolveRef !== null\n ? {\n $refResolver($ref: unknown) {\n if (typeof $ref !== 'string') {\n return {};\n }\n\n if (pathToPointer(path).startsWith($ref)) {\n throw new ResolvingError('Circular reference detected');\n }\n\n const allRefs = store.get(resolveRef)!;\n let schemaRefs = allRefs.get(fragment);\n\n if (schemaRefs === void 0) {\n schemaRefs = [$ref];\n allRefs.set(fragment, schemaRefs);\n } else if (schemaRefs.includes($ref)) {\n const resolved = resolveRef(null, $ref);\n return 'allOf' in resolved ? _mergeAllOf(resolved, path, resolveRef, seen) : resolved;\n } else {\n schemaRefs.push($ref);\n }\n\n const resolved = resolveRef(null, $ref);\n\n if (Array.isArray(resolved.allOf)) {\n for (const member of resolved.allOf) {\n const index = schemaRefs.indexOf(member.$ref);\n if (typeof member.$ref === 'string' && index !== -1 && index !== schemaRefs.lastIndexOf(member.$ref)) {\n throw new ResolvingError('Circular reference detected');\n }\n }\n }\n\n return resolved;\n },\n }\n : null),\n });\n\n seen.set(fragment, merged);\n return merged;\n}\n\nexport function mergeAllOf(\n fragment: SchemaFragment,\n path: string[],\n walkingOptions: WalkingOptions,\n seen: WeakMap,\n) {\n if (walkingOptions.resolveRef !== null && !store.has(walkingOptions.resolveRef)) {\n store.set(walkingOptions.resolveRef, new WeakMap());\n }\n\n let merged = fragment;\n do {\n merged = _mergeAllOf(merged, path, walkingOptions.resolveRef, seen);\n } while ('allOf' in merged);\n\n return merged;\n}\n","import { SchemaCombinerName } from '../nodes/types';\nimport type { SchemaFragment } from '../types';\nimport type { WalkingOptions } from '../walker/types';\nimport { mergeAllOf } from './mergeAllOf';\n\nexport function mergeOneOrAnyOf(\n fragment: SchemaFragment,\n path: string[],\n walkingOptions: WalkingOptions,\n mergedAllOfs: WeakMap,\n): SchemaFragment[] {\n const combiner = SchemaCombinerName.OneOf in fragment ? SchemaCombinerName.OneOf : SchemaCombinerName.AnyOf;\n const items = fragment[combiner];\n\n if (!Array.isArray(items)) return []; // just in case\n\n const merged: SchemaFragment[] = [];\n\n if (Array.isArray(fragment.allOf)) {\n for (const item of items) {\n merged.push({\n allOf: [...fragment.allOf, item],\n });\n }\n\n return merged;\n } else {\n const prunedSchema = { ...fragment };\n delete prunedSchema[combiner];\n\n for (const item of items) {\n if (Object.keys(prunedSchema).length === 0) {\n merged.push(item);\n } else {\n merged.push(\n mergeAllOf(\n {\n allOf: [prunedSchema, item],\n },\n path,\n walkingOptions,\n mergedAllOfs,\n ),\n );\n }\n }\n }\n\n return merged;\n}\n","import { EventEmitter } from '@stoplight/lifecycle';\nimport type { Dictionary } from '@stoplight/types';\nimport createMagicError from 'magic-error';\n\nimport { MergingError } from '../errors';\nimport { isMirroredNode, isReferenceNode, isRegularNode, isRootNode } from '../guards';\nimport { mergeAllOf } from '../mergers/mergeAllOf';\nimport { mergeOneOrAnyOf } from '../mergers/mergeOneOrAnyOf';\nimport { MirroredReferenceNode, MirroredRegularNode, MirroredSchemaNode, ReferenceNode, RegularNode } from '../nodes';\nimport { BooleanishNode } from '../nodes/BooleanishNode';\nimport type { RootNode } from '../nodes/RootNode';\nimport { SchemaCombinerName, SchemaNode, SchemaNodeKind } from '../nodes/types';\nimport type { SchemaFragment } from '../types';\nimport { isNonNullable, isObjectLiteral, isValidSchemaFragment } from '../utils/guards';\nimport type { WalkerEmitter, WalkerHookAction, WalkerHookHandler, WalkerSnapshot, WalkingOptions } from './types';\n\ntype InternalWalkerState = {\n depth: number;\n pathLength: number;\n schemaNode: RegularNode | RootNode;\n};\n\ntype ProcessedFragment = SchemaFragment | SchemaFragment[];\n\nexport class Walker extends EventEmitter {\n public readonly path: string[];\n public depth: number;\n\n protected fragment: SchemaFragment | boolean;\n protected schemaNode: RegularNode | RootNode;\n\n private mergedAllOfs: WeakMap;\n private processedFragments: WeakMap;\n\n private readonly hooks: Partial>;\n\n constructor(protected readonly root: RootNode, protected readonly walkingOptions: WalkingOptions) {\n super();\n\n let maxRefDepth = walkingOptions.maxRefDepth ?? null;\n if (typeof maxRefDepth === 'number') {\n if (maxRefDepth < 1) {\n maxRefDepth = null;\n } else if (maxRefDepth > 1000) {\n // experimented with 1500 and the recursion limit is still lower than that\n maxRefDepth = 1000;\n }\n }\n walkingOptions.maxRefDepth = maxRefDepth;\n\n this.path = [];\n this.depth = -1;\n this.fragment = root.fragment;\n this.schemaNode = root;\n this.processedFragments = new WeakMap();\n this.mergedAllOfs = new WeakMap();\n\n this.hooks = {};\n }\n\n public destroy() {\n this.path.length = 0;\n this.depth = -1;\n this.fragment = this.root.fragment;\n this.schemaNode = this.root;\n this.processedFragments = new WeakMap();\n this.mergedAllOfs = new WeakMap();\n }\n\n public loadSnapshot(snapshot: WalkerSnapshot) {\n this.path.splice(0, this.path.length, ...snapshot.path);\n this.depth = snapshot.depth;\n this.fragment = snapshot.fragment;\n this.schemaNode = snapshot.schemaNode;\n }\n\n public saveSnapshot(): WalkerSnapshot {\n return {\n depth: this.depth,\n fragment: this.fragment,\n schemaNode: this.schemaNode,\n path: this.path.slice(),\n };\n }\n\n public hookInto(action: WalkerHookAction, handler: WalkerHookHandler) {\n this.hooks[action] = handler;\n }\n\n public restoreWalkerAtNode(node: RegularNode) {\n this.processedFragments.delete(node.fragment);\n this.path.splice(0, this.path.length, ...node.path);\n this.depth = node.depth;\n this.fragment = node.fragment;\n this.schemaNode = node;\n }\n\n public walk(): void {\n const { depth: initialDepth, fragment } = this;\n let { schemaNode: initialSchemaNode } = this;\n\n if (initialDepth === -1 && Object.keys(fragment).length === 0) {\n // empty schema, nothing to do\n return;\n }\n\n while (isMirroredNode(initialSchemaNode)) {\n if (!isRegularNode(initialSchemaNode.mirroredNode)) {\n return;\n }\n\n if (initialSchemaNode.mirroredNode.children === void 0) {\n this.restoreWalkerAtNode(initialSchemaNode.mirroredNode);\n initialSchemaNode = this.schemaNode;\n this.depth = initialDepth;\n } else {\n return;\n }\n }\n\n const state = this.dumpInternalWalkerState();\n\n super.emit('enterFragment', fragment);\n const [schemaNode, initialFragment] = this.processFragment();\n super.emit('enterNode', schemaNode);\n\n const actualNode = isMirroredNode(schemaNode) ? schemaNode.mirroredNode : schemaNode;\n if (typeof schemaNode.fragment !== 'boolean' && initialFragment !== null) {\n this.processedFragments.set(schemaNode.fragment, actualNode);\n this.processedFragments.set(initialFragment, actualNode);\n }\n\n this.fragment = schemaNode.fragment;\n this.depth = initialDepth + 1;\n\n if (!isRootNode(schemaNode)) {\n schemaNode.parent = initialSchemaNode;\n schemaNode.subpath = this.path.slice(initialSchemaNode.path.length);\n }\n\n const isIncluded = this.hooks.filter?.(schemaNode);\n\n if (isIncluded === false) {\n super.emit('skipNode', schemaNode);\n return;\n }\n\n if ('children' in initialSchemaNode && !isRootNode(schemaNode)) {\n if (initialSchemaNode.children === void 0) {\n (initialSchemaNode as RegularNode).children = [schemaNode];\n } else {\n initialSchemaNode.children!.push(schemaNode);\n }\n }\n\n super.emit('includeNode', schemaNode);\n\n if (isRegularNode(schemaNode)) {\n this.schemaNode = schemaNode;\n\n if (this.hooks.stepIn?.(schemaNode) !== false) {\n super.emit('stepInNode', schemaNode);\n this.walkNodeChildren();\n super.emit('stepOutNode', schemaNode);\n } else {\n super.emit('stepOverNode', schemaNode);\n }\n }\n\n super.emit('exitNode', schemaNode);\n this.restoreInternalWalkerState(state);\n super.emit('exitFragment', fragment);\n }\n\n protected dumpInternalWalkerState(): InternalWalkerState {\n return {\n depth: this.depth,\n pathLength: this.path.length,\n schemaNode: this.schemaNode,\n };\n }\n\n protected restoreInternalWalkerState({ depth, pathLength, schemaNode }: InternalWalkerState) {\n this.depth = depth;\n this.path.length = pathLength;\n this.schemaNode = schemaNode;\n }\n\n protected walkNodeChildren(): void {\n const { fragment, schemaNode } = this;\n\n if (!isRegularNode(schemaNode) || typeof fragment === 'boolean') return;\n\n const state = this.dumpInternalWalkerState();\n\n if (schemaNode.combiners !== null) {\n for (const combiner of schemaNode.combiners) {\n const items = fragment[combiner];\n if (!Array.isArray(items)) continue;\n\n let i = -1;\n for (const item of items) {\n i++;\n if (!isObjectLiteral(item)) continue;\n this.fragment = item;\n this.restoreInternalWalkerState(state);\n this.path.push(combiner, String(i));\n this.walk();\n }\n }\n }\n\n switch (schemaNode.primaryType) {\n case SchemaNodeKind.Array:\n if (Array.isArray(fragment.items)) {\n let i = -1;\n for (const item of fragment.items) {\n i++;\n if (!isValidSchemaFragment(item)) continue;\n this.fragment = item;\n this.restoreInternalWalkerState(state);\n this.path.push('items', String(i));\n this.walk();\n }\n } else {\n if (isObjectLiteral(fragment.items)) {\n this.fragment = fragment.items;\n this.restoreInternalWalkerState(state);\n this.path.push('items');\n this.walk();\n }\n\n if (isValidSchemaFragment(fragment.additionalItems)) {\n this.fragment = fragment.additionalItems;\n this.restoreInternalWalkerState(state);\n this.path.push('additionalItems');\n this.walk();\n }\n }\n\n break;\n case SchemaNodeKind.Object:\n if (isObjectLiteral(fragment.properties)) {\n for (const key of Object.keys(fragment.properties)) {\n const value = fragment.properties[key];\n if (!isValidSchemaFragment(value)) continue;\n this.fragment = value;\n this.restoreInternalWalkerState(state);\n this.path.push('properties', key);\n this.walk();\n }\n }\n\n if (isObjectLiteral(fragment.patternProperties)) {\n for (const key of Object.keys(fragment.patternProperties)) {\n const value = fragment.patternProperties[key];\n if (!isValidSchemaFragment(value)) continue;\n this.fragment = value;\n this.restoreInternalWalkerState(state);\n this.path.push('patternProperties', key);\n this.walk();\n }\n }\n\n if (isValidSchemaFragment(fragment.additionalProperties)) {\n this.fragment = fragment.additionalProperties;\n this.restoreInternalWalkerState(state);\n this.path.push('additionalProperties');\n this.walk();\n }\n\n break;\n }\n\n this.schemaNode = schemaNode;\n }\n\n protected retrieveFromFragment(\n fragment: ProcessedFragment,\n originalFragment: SchemaFragment,\n ): [MirroredSchemaNode, ProcessedFragment] | void {\n const processedSchemaNode = this.processedFragments.get(fragment);\n if (processedSchemaNode !== void 0) {\n if (isRegularNode(processedSchemaNode)) {\n return [new MirroredRegularNode(processedSchemaNode, { originalFragment }), fragment];\n }\n\n if (isReferenceNode(processedSchemaNode)) {\n return [new MirroredReferenceNode(processedSchemaNode), fragment];\n }\n\n // whoops, we don't know what to do with it\n throw new TypeError('Cannot mirror the node');\n }\n }\n\n protected processFragment(): [SchemaNode, ProcessedFragment | null] {\n const { walkingOptions, path, fragment: originalFragment, depth } = this;\n let { fragment } = this;\n\n if (typeof fragment === 'boolean') {\n return [new BooleanishNode(fragment), null];\n }\n\n if (typeof originalFragment === 'boolean') {\n throw new TypeError('Original fragment cannot be a boolean');\n }\n\n let retrieved = isNonNullable(fragment) ? this.retrieveFromFragment(fragment, fragment) : null;\n\n if (retrieved) {\n return retrieved;\n }\n\n let initialFragment: ProcessedFragment = fragment;\n\n if ('$ref' in fragment) {\n if (typeof walkingOptions.maxRefDepth === 'number' && walkingOptions.maxRefDepth < depth) {\n return [new ReferenceNode(fragment, `max $ref depth limit reached`), fragment];\n } else if (typeof fragment.$ref !== 'string') {\n return [new ReferenceNode(fragment, '$ref is not a string'), fragment];\n } else if (walkingOptions.resolveRef !== null) {\n try {\n let newFragment = walkingOptions.resolveRef(path, fragment.$ref);\n\n if (typeof fragment.description === 'string') {\n newFragment = { ...newFragment };\n Object.assign(newFragment, { description: fragment.description });\n } else {\n retrieved = this.retrieveFromFragment(newFragment, originalFragment);\n if (retrieved) {\n return retrieved;\n }\n }\n\n fragment = newFragment;\n } catch (ex) {\n super.emit('error', createMagicError(ex));\n return [new ReferenceNode(fragment, ex?.message ?? 'Unknown resolving error'), fragment];\n }\n } else {\n return [new ReferenceNode(fragment, null), fragment];\n }\n }\n //fragment with type 'array' and no description should adopt description of $ref if it exists.\n if (fragment.type === 'array' && fragment.description === void 0) {\n if (fragment.items !== void 0 && isObjectLiteral(fragment.items)) {\n for (const key of Object.keys(fragment.items)) {\n if (key === '$ref') {\n const refToResolve = fragment.items[key];\n if (typeof refToResolve !== 'string') {\n return [new ReferenceNode(fragment, '$ref is not a string'), fragment];\n } else if (walkingOptions.resolveRef !== null) {\n try {\n let newFragment = walkingOptions.resolveRef(path, refToResolve);\n if (newFragment.description !== void 0) {\n newFragment = { ...newFragment };\n Object.assign(fragment, { description: newFragment.description });\n }\n } catch (ex) {\n super.emit('error', createMagicError(ex));\n }\n }\n }\n }\n }\n }\n if (walkingOptions.mergeAllOf && SchemaCombinerName.AllOf in fragment) {\n try {\n if (Array.isArray(fragment.allOf)) {\n initialFragment = fragment.allOf;\n }\n\n fragment = mergeAllOf(fragment, path, walkingOptions, this.mergedAllOfs);\n } catch (ex) {\n initialFragment = fragment;\n super.emit('error', createMagicError(new MergingError(ex?.message ?? 'Unknown merging error')));\n // no the end of the world - we will render raw unprocessed fragment\n }\n }\n\n if (SchemaCombinerName.OneOf in fragment || SchemaCombinerName.AnyOf in fragment) {\n try {\n const merged = mergeOneOrAnyOf(fragment, path, walkingOptions, this.mergedAllOfs);\n if (merged.length === 1) {\n return [new RegularNode(merged[0], { originalFragment }), initialFragment];\n } else {\n const combiner = SchemaCombinerName.OneOf in fragment ? SchemaCombinerName.OneOf : SchemaCombinerName.AnyOf;\n return [new RegularNode({ [combiner]: merged }, { originalFragment }), initialFragment];\n }\n } catch (ex) {\n super.emit('error', createMagicError(new MergingError(ex?.message ?? 'Unknown merging error')));\n // no the end of the world - we will render raw unprocessed fragment\n }\n }\n\n retrieved = isNonNullable(fragment) ? this.retrieveFromFragment(initialFragment, originalFragment) : null;\n\n if (retrieved) {\n return retrieved;\n }\n\n return [new RegularNode(fragment, { originalFragment }), initialFragment];\n }\n}\n","import { extractPointerFromRef, extractSourceFromRef, resolveInlineRef } from '@stoplight/json';\n\nimport { ResolvingError } from '../errors';\nimport { RootNode } from '../nodes/RootNode';\nimport type { SchemaFragment } from '../types';\nimport { isObjectLiteral } from '../utils';\nimport { Walker } from '../walker';\nimport type { WalkerRefResolver } from '../walker/types';\nimport type { SchemaTreeOptions } from './types';\n\nexport class SchemaTree {\n public walker: Walker;\n public root: RootNode;\n private readonly resolvedRefs = new Map();\n\n constructor(public schema: SchemaFragment, protected readonly opts?: Partial) {\n this.root = new RootNode(schema);\n this.resolvedRefs = new Map();\n this.walker = new Walker(this.root, {\n mergeAllOf: this.opts?.mergeAllOf !== false,\n resolveRef: opts?.refResolver === null ? null : this.resolveRef,\n maxRefDepth: opts?.maxRefDepth,\n });\n }\n\n public destroy() {\n this.root.children.length = 0;\n this.walker.destroy();\n this.resolvedRefs.clear();\n }\n\n public populate() {\n this.invokeWalker(this.walker);\n }\n\n public invokeWalker(walker: Walker) {\n walker.walk();\n }\n\n protected resolveRef: WalkerRefResolver = (path, $ref) => {\n if (this.resolvedRefs.has($ref)) {\n return this.resolvedRefs.get($ref);\n }\n\n const seenRefs: string[] = [];\n let cur$ref: unknown = $ref;\n let resolvedValue!: SchemaFragment;\n\n while (typeof cur$ref === 'string') {\n if (seenRefs.includes(cur$ref)) {\n break;\n }\n\n seenRefs.push(cur$ref);\n resolvedValue = this._resolveRef(path, cur$ref);\n cur$ref = resolvedValue.$ref;\n }\n\n this.resolvedRefs.set($ref, resolvedValue);\n return resolvedValue;\n };\n\n private _resolveRef: WalkerRefResolver = (path, $ref) => {\n const source = extractSourceFromRef($ref);\n const pointer = extractPointerFromRef($ref);\n const refResolver = this.opts?.refResolver;\n\n if (typeof refResolver === 'function') {\n return refResolver({ source, pointer }, path, this.schema);\n } else if (source !== null) {\n throw new ResolvingError('Cannot dereference external references');\n } else if (pointer === null) {\n throw new ResolvingError('The pointer is empty');\n } else if (isObjectLiteral(this.schema)) {\n const value = resolveInlineRef(this.schema, pointer);\n if (!isObjectLiteral(value)) {\n throw new ResolvingError('Invalid value');\n }\n\n return value;\n } else {\n throw new ResolvingError('Unexpected input');\n }\n };\n}\n","import * as React from 'react';\n\nimport { ExtensionAddonRenderer, GoToRefHandler, RowAddonRenderer, ViewMode } from '../types';\n\nexport type ChangeType = 'added' | 'removed' | 'modified';\n\nexport type NodeHasChangedFn = (props: {\n nodeId: string;\n mode?: 'read' | 'write';\n}) => { type: ChangeType } | undefined;\n\nexport type JSVOptions = {\n defaultExpandedDepth: number;\n viewMode: ViewMode;\n onGoToRef?: GoToRefHandler;\n renderRowAddon?: RowAddonRenderer;\n renderExtensionAddon?: ExtensionAddonRenderer;\n hideExamples?: boolean;\n renderRootTreeLines?: boolean;\n disableCrumbs?: boolean;\n nodeHasChanged?: NodeHasChangedFn;\n markup?: boolean;\n};\n\nconst JSVOptionsContext = React.createContext({\n defaultExpandedDepth: 0,\n viewMode: 'standalone',\n hideExamples: false,\n});\n\nexport const useJSVOptionsContext = () => React.useContext(JSVOptionsContext);\n\nexport const JSVOptionsContextProvider = JSVOptionsContext.Provider;\n","export function isNonNullable(maybeNullable: T): maybeNullable is NonNullable {\n return maybeNullable !== void 0 && maybeNullable !== null;\n}\n","import { isPlainObject } from '@stoplight/json';\nimport {\n type MirroredSchemaNode,\n type ReferenceNode,\n type RegularNode,\n type SchemaNode,\n isBooleanishNode,\n isReferenceNode,\n isRegularNode,\n isRootNode,\n SchemaNodeKind,\n} from '@stoplight/json-schema-tree';\nimport { BooleanishNode } from '@stoplight/json-schema-tree/nodes/BooleanishNode';\n\nimport { isNonNullable } from '../guards/isNonNullable';\nimport type { ViewMode } from '../types';\nimport type {\n ArrayNode,\n ComplexArrayNode,\n ComplexDictionaryNode,\n DictionaryNode,\n FlattenableNode,\n PrimitiveArrayNode,\n PrimitiveDictionaryNode,\n} from './types';\n\nexport type ChildNode = RegularNode | ReferenceNode | MirroredSchemaNode;\n\nexport const isNonEmptyParentNode = (\n node: SchemaNode,\n): node is RegularNode & {\n children: ChildNode[] & { 0: ChildNode };\n} => isRegularNode(node) && !!node.children && node.children.length > 0;\n\nexport function isFlattenableNode(node: SchemaNode): node is FlattenableNode {\n if (!isRegularNode(node)) return false;\n\n if ((!isArrayNode(node) && !isDictionaryNode(node)) || !isNonNullable(node.children) || node.children.length === 0) {\n return false;\n }\n\n return (\n node.children.length === 1 &&\n ((isRegularNode(node.children[0]) && (!isArrayNode(node) || !isDictionaryNode(node.children[0]))) ||\n (isReferenceNode(node.children[0]) && node.children[0].error !== null))\n );\n}\n\nexport function isPrimitiveArray(node: SchemaNode): node is PrimitiveArrayNode {\n return isFlattenableNode(node) && isArrayNode(node) && isRegularNode(node.children[0]) && node.children[0].simple;\n}\n\nexport function isPrimitiveDictionary(node: SchemaNode): node is PrimitiveDictionaryNode {\n return (\n isFlattenableNode(node) && isDictionaryNode(node) && isRegularNode(node.children[0]) && node.children[0].simple\n );\n}\n\nexport function isComplexArray(node: SchemaNode): node is ComplexArrayNode {\n return isFlattenableNode(node) && isArrayNode(node) && isRegularNode(node.children[0]) && !node.children[0].simple;\n}\n\nexport function isComplexDictionary(node: SchemaNode): node is ComplexDictionaryNode {\n return (\n isFlattenableNode(node) && isDictionaryNode(node) && isRegularNode(node.children[0]) && !node.children[0].simple\n );\n}\n\nexport function isDictionaryNode(node: SchemaNode): node is DictionaryNode {\n return (\n isRegularNode(node) &&\n node.primaryType === SchemaNodeKind.Object &&\n isPlainObject(node.fragment.additionalProperties)\n );\n}\n\nexport function isArrayNode(node: SchemaNode): node is ArrayNode {\n return isRegularNode(node) && node.primaryType === SchemaNodeKind.Array;\n}\n\n/**\n * Returns the children of `node` that should be displayed in a viewer or\n * editor. Defaults to `node.children`, except for Arrays that get special\n * handling (flattening).\n */\nexport function visibleChildren(node: SchemaNode): SchemaNode[] {\n if (!isRegularNode(node) || isPrimitiveArray(node) || isPrimitiveDictionary(node)) {\n return [];\n }\n if (isComplexArray(node) || isComplexDictionary(node)) {\n // flatten the tree here, and show the properties of the item type directly\n return node.children[0].children ?? [];\n }\n return node.children ?? [];\n}\n\nexport function isPropertyRequired(schemaNode: SchemaNode): boolean {\n const { parent } = schemaNode;\n if (parent === null || !isRegularNode(parent) || schemaNode.subpath.length === 0) {\n return false;\n }\n\n return !!parent.required?.includes(schemaNode.subpath[schemaNode.subpath.length - 1]);\n}\n\nfunction isValidViewMode(node: RegularNode, viewMode: ViewMode): boolean {\n const { validations } = node;\n\n if (!!validations.writeOnly === !!validations.readOnly) {\n return true;\n }\n\n return !((viewMode === 'read' && !!validations.writeOnly) || (viewMode === 'write' && !!validations.readOnly));\n}\n\nfunction isRenderableNode(node: BooleanishNode | RegularNode): boolean {\n if (node.parent === null) return true;\n\n if (isDictionaryNode(node.parent)) {\n // if dictionary, do not render explicitly defined properties\n return node.subpath.length !== 2 || node.subpath[0] !== 'properties';\n }\n\n // do not render additionalItems\n if (isArrayNode(node.parent)) {\n return node.subpath[0] !== 'additionalItems';\n }\n\n // do not render true/false additionalProperties\n if (isRegularNode(node.parent) && node.parent.primaryType === SchemaNodeKind.Object && isBooleanishNode(node)) {\n return !(node.subpath.length === 1 || node.subpath[0] === 'additionalProperties');\n }\n\n return true;\n}\n\nexport function shouldNodeBeIncluded(node: SchemaNode, viewMode: ViewMode = 'standalone'): boolean {\n return (\n (isReferenceNode(node) || isRootNode(node) || isRenderableNode(node)) &&\n (!isRegularNode(node) || isValidViewMode(node, viewMode))\n );\n}\n","import { SchemaNode } from '@stoplight/json-schema-tree';\nimport { atom } from 'jotai';\nimport { atomFamily } from 'jotai/utils';\n\nexport const hoveredNodeAtom = atom(null);\n\nexport const isNodeHoveredAtom = atomFamily((node: SchemaNode) =>\n atom(get => node === get(hoveredNodeAtom)),\n);\n\nexport const isChildNodeHoveredAtom = atomFamily((parent: SchemaNode) =>\n atom(get => {\n const hoveredNode = get(hoveredNodeAtom);\n\n if (!hoveredNode || hoveredNode === parent) return false;\n\n return hoveredNode.parent === parent;\n }),\n);\n","import { isRegularNode, isRootNode, SchemaNode } from '@stoplight/json-schema-tree';\nimport { atom } from 'jotai';\n\nimport { hoveredNodeAtom } from '../SchemaRow/state';\n\nexport const pathCrumbsAtom = atom(get => {\n const node = get(hoveredNodeAtom);\n\n if (!node) return [];\n\n return propertyPathToObjectPath(node as SchemaNode);\n});\n\nfunction propertyPathToObjectPath(node: SchemaNode) {\n const objectPath: string[] = [];\n\n let currentNode: SchemaNode | null = node;\n while (currentNode && !isRootNode(currentNode)) {\n if (isRegularNode(currentNode)) {\n const pathPart = currentNode.subpath[currentNode.subpath.length - 1];\n\n if (currentNode.primaryType === 'array') {\n const key = `${pathPart || ''}[]`;\n if (objectPath[objectPath.length - 1]) {\n objectPath[objectPath.length - 1] = key;\n } else {\n objectPath.push(key);\n }\n } else if (\n pathPart &&\n (currentNode.subpath.length !== 2 || !['allOf', 'oneOf', 'anyOf'].includes(currentNode.subpath[0]))\n ) {\n objectPath.push(currentNode.subpath[currentNode.subpath.length - 1]);\n }\n }\n\n currentNode = currentNode.parent;\n }\n\n return objectPath.reverse();\n}\n","import { useAtomValue } from 'jotai';\nimport * as React from 'react';\n\nimport { useJSVOptionsContext } from '../../contexts';\nimport { pathCrumbsAtom } from './state';\n\nconst SCROLL_THRESHOLD = 20; // pixels scrolled before showing crumbs\n\nexport const PathCrumbs: React.FC<{ parentCrumbs?: string[] }> = ({ parentCrumbs = [] }) => {\n const pathCrumbs = useAtomValue(pathCrumbsAtom);\n const { disableCrumbs } = useJSVOptionsContext();\n const crumbsRef = React.useRef(null);\n const [style, setStyle] = React.useState({\n position: 'fixed',\n top: -100, // Start off-screen\n left: 0,\n width: 0,\n });\n const [hasScrolled, setHasScrolled] = React.useState(false);\n\n // JS-based sticky positioning\n React.useEffect(() => {\n const crumbsEl = crumbsRef.current;\n if (!crumbsEl) return;\n\n const scrollContainer = crumbsEl.closest('.jsv-root') as HTMLElement;\n if (!scrollContainer) return;\n\n const updatePosition = () => {\n const containerRect = scrollContainer.getBoundingClientRect();\n const scrolled = scrollContainer.scrollTop > SCROLL_THRESHOLD;\n \n setHasScrolled(scrolled);\n setStyle({\n position: 'fixed',\n top: Math.max(0, containerRect.top),\n left: containerRect.left,\n width: containerRect.width,\n });\n };\n\n updatePosition();\n scrollContainer.addEventListener('scroll', updatePosition);\n window.addEventListener('scroll', updatePosition);\n window.addEventListener('resize', updatePosition);\n\n return () => {\n scrollContainer.removeEventListener('scroll', updatePosition);\n window.removeEventListener('scroll', updatePosition);\n window.removeEventListener('resize', updatePosition);\n };\n }, []);\n\n if (disableCrumbs) {\n return null;\n }\n\n const parentCrumbElems: React.ReactNode[] = [];\n parentCrumbs.forEach((crumb, i) => {\n parentCrumbElems.push({crumb});\n });\n\n const pathCrumbElems: React.ReactNode[] = [];\n pathCrumbs.forEach((crumb, i) => {\n if (pathCrumbs[i + 1]) {\n pathCrumbElems.push({crumb});\n } else {\n pathCrumbElems.push(\n \n {crumb}\n ,\n );\n }\n });\n\n // Only show content when there's at least one crumb to display AND user has scrolled\n const hasCrumbs = parentCrumbElems.length > 0 || pathCrumbElems.length > 0;\n const isVisible = hasCrumbs && hasScrolled;\n\n return (\n
\n {parentCrumbElems.map((elem, i) => (\n \n {elem}\n {i < parentCrumbElems.length - 1 && /}\n \n ))}\n {parentCrumbElems.length > 0 && pathCrumbElems.length > 0 && /}\n {pathCrumbElems.map((elem, i) => (\n \n {elem}\n {i < pathCrumbElems.length - 1 && .}\n \n ))}\n
\n );\n};\n","import { SchemaCombinerName } from '@stoplight/json-schema-tree';\n\nexport const COMBINER_PRETTY_NAMES: Readonly> = {\n [SchemaCombinerName.AllOf]: 'and',\n [SchemaCombinerName.AnyOf]: 'and/or',\n [SchemaCombinerName.OneOf]: 'or',\n};\n\nexport const COMMON_JSON_SCHEMA_AND_OAS_FORMATS: Readonly> = {\n // strings are omitted because they are the default type to apply format to\n number: ['byte', 'int32', 'int64', 'float', 'double'],\n get integer() {\n return this.number;\n },\n};\n\nexport const NESTING_OFFSET = 3;\n\nexport const COMBINER_NAME_MAP: Record = {\n allOf: 'all of',\n anyOf: 'any of',\n oneOf: 'one of',\n};\n","import { isPlainObject } from '@stoplight/json';\nimport type { SchemaFragment, SchemaNode } from '@stoplight/json-schema-tree';\n\n// for easier debugging the values going into hash\nlet SKIP_HASHING = false;\n\nexport const setSkipHashing = (skip: boolean) => {\n SKIP_HASHING = skip;\n};\n\n// Simple FNV-1a 52-bit hash implementation\n// This produces the same output as fnv.fast1a52hex()\nfunction fnv1a52(str: string): string {\n const FNV_PRIME = 0x01000193;\n const FNV_OFFSET = 0x811c9dc5;\n \n let hash = FNV_OFFSET;\n for (let i = 0; i < str.length; i++) {\n hash ^= str.charCodeAt(i);\n hash = Math.imul(hash, FNV_PRIME);\n }\n \n // Convert to unsigned 32-bit and then to hex\n const hash32 = hash >>> 0;\n return hash32.toString(16).padStart(8, '0');\n}\n\nexport const hash = (value: string, skipHashing: boolean = SKIP_HASHING): string => {\n // Never change this, as it would affect how the default stable id is generated, and cause mismatches with whatever\n // we already have stored in our DB etc.\n return skipHashing ? value : fnv1a52(value);\n};\n\nfunction getStoplightId(fragment: SchemaFragment | boolean): string | undefined {\n if (typeof fragment === 'boolean') return undefined;\n const xStoplight = fragment['x-stoplight' as keyof typeof fragment];\n if (isPlainObject(xStoplight)) {\n const id = (xStoplight as Record).id;\n return typeof id === 'string' ? id : undefined;\n }\n return undefined;\n}\n\nexport const getNodeId = (node: SchemaNode, parentId?: string): string => {\n const nodeId = getStoplightId(node.fragment);\n if (nodeId) return nodeId;\n\n const key = node.path[node.path.length - 1];\n\n return hash(['schema_property', parentId, String(key)].join('-'));\n};\n\nexport const getOriginalNodeId = (node: SchemaNode, parentId?: string): string => {\n // @ts-expect-error originalFragment does exist...\n const nodeId = getStoplightId(node.originalFragment);\n if (nodeId) return nodeId;\n\n const key = node.path[node.path.length - 1];\n\n return hash(['schema_property', parentId, String(key)].join('-'));\n};\n","import { SchemaFragment } from '@stoplight/json-schema-tree';\n\nexport type VendorExtensionsList = {\n [keyof: string]: unknown;\n};\n\nexport type VendorExtensionsResult = [number, VendorExtensionsList];\n\n/**\n * Extract all vendor extensions or properties prefix with 'x-' from the schema definition\n * @param fragment The fragment to extract the vendor extensions from\n * @returns VendorExtensionsResult\n */\nexport function extractVendorExtensions(fragment: SchemaFragment | boolean): VendorExtensionsResult {\n if (typeof fragment === 'boolean') {\n return [0, {}];\n }\n\n const extensionKeys = Object.entries(fragment).filter(([key]) => key.startsWith('x-'));\n let vendorExtensions: VendorExtensionsList = {};\n\n for (const [key, value] of extensionKeys) {\n vendorExtensions[key] = value;\n }\n\n return [extensionKeys.length, vendorExtensions];\n}\n","import { CaretRight } from '@phosphor-icons/react';\nimport { clsx } from 'clsx';\nimport * as React from 'react';\n\nexport interface CaretProps {\n isExpanded: boolean;\n}\n\nexport const Caret: React.FC = ({ isExpanded }) => (\n \n \n
\n);\n","import { SchemaNode } from '@stoplight/json-schema-tree';\nimport { clsx } from 'clsx';\nimport * as React from 'react';\n\nimport { useJSVOptionsContext } from '../../contexts';\nimport { SchemaRow, SchemaRowProps } from '../SchemaRow';\n\ntype ChangeType = 'added' | 'removed' | 'modified';\n\ntype ChildStackProps = {\n schemaNode: SchemaNode;\n childNodes: readonly SchemaNode[];\n currentNestingLevel: number;\n className?: string;\n parentNodeId?: string;\n RowComponent?: React.FC;\n parentChangeType?: ChangeType;\n};\n\nexport const ChildStack = React.memo(\n ({\n childNodes,\n currentNestingLevel,\n className,\n RowComponent = SchemaRow,\n parentNodeId,\n parentChangeType,\n }: ChildStackProps) => {\n const { renderRootTreeLines } = useJSVOptionsContext();\n const rootLevel = renderRootTreeLines ? 0 : 1;\n const isRootLevel = currentNestingLevel < rootLevel;\n\n return (\n \n {childNodes.map((childNode: SchemaNode) => (\n \n ))}\n \n );\n },\n);\n\nChildStack.displayName = 'ChildStack';\n","import * as React from 'react';\nimport { JsonSchemaViewerErrorBoundary } from '../JsonSchemaViewer';\nimport { useJSVOptionsContext } from '../../contexts';\n\nconst Markdown = React.lazy(async () => { \n return await import ('react-markdown');\n});\n\nexport interface DescriptionProps {\n value: unknown;\n}\n\ninterface MarkupProps {\n value: string\n}\nconst MarkupWithFallback: React.FC = ({value}) => {\n return (\n \n \n {value}\n \n \n );\n}\n\nexport const Description: React.FC = ({ value }) => {\n const [showAll, setShowAll] = React.useState(false);\n const {markup = false} = useJSVOptionsContext();\n\n if (typeof value !== 'string' || value.trim().length === 0) return null;\n\n const paragraphs = value.split('\\n\\n');\n\n if (paragraphs.length <= 1 || showAll) {\n return (\n
\n {markup ? : value}\n
\n );\n }\n\n const firstParagraph = paragraphs[0];\n\n return (\n
\n

\n {markup ? : firstParagraph}\n setShowAll(true)}\n >\n Show all...\n \n

\n
\n );\n};\n","import { clsx } from 'clsx';\nimport { Atom, useAtomValue } from 'jotai';\nimport * as React from 'react';\n\ninterface DividerProps {\n hoveredAtom: Atom;\n}\n\nexport const Divider: React.FC = ({ hoveredAtom }) => {\n const isHovered = useAtomValue(hoveredAtom);\n\n return (\n \n );\n};\n","import { isPlainObject } from '@stoplight/json';\nimport type { SchemaNode } from '@stoplight/json-schema-tree';\n\nexport function getInternalSchemaError(schemaNode: SchemaNode): string | undefined {\n let errorMessage;\n const fragment: unknown = schemaNode.fragment;\n if (!isPlainObject(fragment)) return;\n\n const xStoplight = fragment['x-stoplight'];\n\n if (isPlainObject(xStoplight) && typeof xStoplight['error-message'] === 'string') {\n errorMessage = xStoplight['error-message'];\n } else {\n const fragmentErrorMessage = fragment['x-sl-error-message'];\n if (typeof fragmentErrorMessage === 'string') {\n errorMessage = fragmentErrorMessage;\n } else {\n const items: unknown = fragment['items'];\n if (isPlainObject(items)) {\n const itemsErrorMessage = items['x-sl-error-message'];\n if (typeof itemsErrorMessage === 'string') {\n errorMessage = itemsErrorMessage;\n }\n }\n }\n }\n\n return errorMessage;\n}\n","import { isReferenceNode, isRegularNode, ReferenceNode, SchemaNode, SchemaNodeKind } from '@stoplight/json-schema-tree';\nimport { Warning } from '@phosphor-icons/react';\nimport * as React from 'react';\n\nimport { isFlattenableNode } from '../../tree';\nimport { getInternalSchemaError } from '../../utils/getInternalSchemaError';\n\nfunction useRefNode(schemaNode: SchemaNode) {\n return React.useMemo(() => {\n if (isReferenceNode(schemaNode)) {\n return schemaNode;\n }\n\n if (\n isRegularNode(schemaNode) &&\n (isFlattenableNode(schemaNode) ||\n (schemaNode.primaryType === SchemaNodeKind.Array && schemaNode.children?.length === 1))\n ) {\n return (schemaNode.children?.find(isReferenceNode) as ReferenceNode | undefined) ?? null;\n }\n\n return null;\n }, [schemaNode]);\n}\n\nexport const Error: React.FC<{ schemaNode: SchemaNode }> = ({ schemaNode }) => {\n const refNode = useRefNode(schemaNode);\n const error = getInternalSchemaError(schemaNode) ?? refNode?.error;\n\n if (typeof error !== 'string') return null;\n\n return (\n \n \n \n );\n};\n","import { clsx } from 'clsx';\nimport * as React from 'react';\n\ntype ChangeType = 'added' | 'removed' | 'modified';\n\nexport interface NodeAnnotationProps {\n change?: { type: ChangeType } | null;\n style?: React.CSSProperties;\n}\n\nexport const NodeAnnotation: React.FC = ({ change, style }) => {\n if (!change) return null;\n\n return (\n \n );\n};\n","import * as React from 'react';\n\nimport { useJSVOptionsContext } from '../../contexts';\n\nexport interface PropertiesProps {\n required: boolean;\n deprecated: boolean;\n validations: Record;\n}\n\nexport const useHasProperties = ({ required, deprecated, validations: { readOnly, writeOnly } }: PropertiesProps) => {\n const { viewMode } = useJSVOptionsContext();\n\n const showVisibilityValidations = viewMode === 'standalone' && !!readOnly !== !!writeOnly;\n\n return deprecated || showVisibilityValidations || required;\n};\n\nexport const Properties: React.FC = ({\n required,\n deprecated,\n validations: { readOnly, writeOnly },\n}) => {\n const { viewMode } = useJSVOptionsContext();\n\n // Show readOnly writeOnly validations only in standalone mode and only if just one of them is present\n const showVisibilityValidations = viewMode === 'standalone' && !!readOnly !== !!writeOnly;\n const visibility = showVisibilityValidations ? (\n readOnly ? (\n \n read-only\n \n ) : (\n \n write-only\n \n )\n ) : null;\n\n return (\n <>\n {deprecated ? (\n \n deprecated\n \n ) : null}\n {visibility}\n {required && (\n \n required\n \n )}\n \n );\n};\n","import { Select as BaseSelect } from '@base-ui/react/select';\nimport { CaretDown, Check } from '@phosphor-icons/react';\nimport * as React from 'react';\n\nexport interface SelectOption {\n value: string;\n label: string;\n}\n\nexport interface SelectProps {\n 'aria-label'?: string;\n options: SelectOption[];\n value: string;\n onChange: (value: string) => void;\n prefix?: string;\n}\n\nexport const Select: React.FC = ({\n 'aria-label': ariaLabel,\n options,\n value,\n onChange,\n prefix,\n}) => {\n return (\n {\n if (newValue !== null) {\n onChange(newValue);\n }\n }}\n >\n \n \n {(val) => {\n const selectedOption = options.find(opt => opt.value === val);\n return (\n <>\n {prefix}\n {selectedOption?.label ?? val}\n \n );\n }}\n \n \n \n \n \n \n \n \n {options.map(option => (\n \n \n \n \n {option.label}\n \n ))}\n \n \n \n \n );\n};\n","import { isPlainObject } from '@stoplight/json';\nimport { RegularNode, SchemaNodeKind } from '@stoplight/json-schema-tree';\n\nimport { COMMON_JSON_SCHEMA_AND_OAS_FORMATS } from '../consts';\n\nexport function getApplicableFormats(schemaNode: RegularNode): [type: SchemaNodeKind, format: string] | null {\n // JSON Schema itself doesn't directly support defining binary data types.\n // Within the http-spec repository, we address this limitation using\n // OpenAPI features i.e. `contentMediaType: 'application/octet-stream'`.\n // which is specific to OpenAPI and not supported by JSON Schema itself.\n\n const fragment = schemaNode.fragment;\n if (\n isPlainObject(fragment) &&\n (fragment as Record)['contentMediaType'] === 'application/octet-stream' &&\n schemaNode.types &&\n schemaNode.types.length > 0\n ) {\n return [schemaNode.types[0], 'binary'];\n }\n\n if (schemaNode.format === null) {\n return null;\n }\n\n if (schemaNode.types !== null) {\n for (const type of schemaNode.types) {\n if (!(type in COMMON_JSON_SCHEMA_AND_OAS_FORMATS)) continue;\n\n if (COMMON_JSON_SCHEMA_AND_OAS_FORMATS[type].includes(schemaNode.format)) {\n return [type, schemaNode.format];\n }\n }\n }\n\n return [SchemaNodeKind.String, schemaNode.format];\n}\n","import { getLastPathSegment } from '@stoplight/json';\nimport { isReferenceNode, isRegularNode, RegularNode, SchemaNodeKind } from '@stoplight/json-schema-tree';\n\nimport { isNonNullable } from '../guards/isNonNullable';\nimport {\n isComplexArray,\n isComplexDictionary,\n isDictionaryNode,\n isFlattenableNode,\n isPrimitiveArray,\n isPrimitiveDictionary,\n} from '../tree';\nimport { getApplicableFormats } from './getApplicableFormats';\n\nfunction upperFirst(str: string): string {\n return str.charAt(0).toUpperCase() + str.slice(1);\n}\n\ntype PrintNameOptions = {\n shouldUseRefNameFallback?: boolean;\n};\n\nexport function printName(\n schemaNode: RegularNode,\n { shouldUseRefNameFallback = false }: PrintNameOptions = {},\n): string | undefined {\n if (!isFlattenableNode(schemaNode)) {\n return schemaNode.title ?? (shouldUseRefNameFallback ? getNodeNameFromOriginalRef(schemaNode) : undefined);\n }\n\n return printFlattenedName(schemaNode, { shouldUseRefNameFallback });\n}\n\nfunction printFlattenedName(\n schemaNode: RegularNode,\n { shouldUseRefNameFallback = false }: PrintNameOptions,\n): string | undefined {\n if (!isNonNullable(schemaNode.children) || schemaNode.children.length === 0) {\n return schemaNode.title ?? (shouldUseRefNameFallback ? getNodeNameFromOriginalRef(schemaNode) : undefined);\n }\n\n if (schemaNode.children.length === 1 && isReferenceNode(schemaNode.children[0])) {\n const value = `$ref(${schemaNode.children[0].value})`;\n return isDictionaryNode(schemaNode) ? `dictionary[string, ${value}]` : `${value}[]`;\n }\n\n const format = isDictionaryNode(schemaNode) ? 'dictionary[string, %s]' : 'array[%s]';\n\n if (isPrimitiveArray(schemaNode) || isPrimitiveDictionary(schemaNode)) {\n const val =\n schemaNode.children?.reduce<(SchemaNodeKind | `${SchemaNodeKind}<${string}>`)[] | null>((mergedTypes, child) => {\n if (mergedTypes === null) return null;\n\n if (!isRegularNode(child)) return null;\n\n if (child.types !== null && child.types.length > 0) {\n const formats = getApplicableFormats(child);\n for (const type of child.types) {\n if (mergedTypes.includes(type)) continue;\n\n if (formats !== null && formats[0] === type) {\n mergedTypes.push(`${type}<${formats[1]}>`);\n } else {\n mergedTypes.push(type);\n }\n }\n }\n\n return mergedTypes;\n }, []) ?? null;\n\n if (val !== null && val.length > 0) {\n return format.replace('%s', val.join(' or '));\n }\n\n return isDictionaryNode(schemaNode) ? 'dictionary[string, any]' : 'array';\n }\n\n if (isComplexArray(schemaNode) || isComplexDictionary(schemaNode)) {\n const firstChild = schemaNode.children[0];\n if (firstChild.title) {\n return format.replace('%s', firstChild.title);\n } else if (shouldUseRefNameFallback && getNodeNameFromOriginalRef(schemaNode)) {\n return format.replace('%s', getNodeNameFromOriginalRef(schemaNode) ?? 'any');\n } else if (firstChild.primaryType) {\n return format.replace('%s', firstChild.primaryType);\n } else if (firstChild.combiners?.length) {\n return format.replace('%s', firstChild.combiners.join(' '));\n }\n return isComplexArray(schemaNode) ? 'array' : format.replace('%s', 'any');\n }\n\n return undefined;\n}\n\nfunction getNodeNameFromOriginalRef(node: RegularNode) {\n if (typeof node.originalFragment.$ref === 'string') {\n return upperFirst(getLastPathSegment(node.originalFragment.$ref));\n }\n return undefined;\n}\n","import {\n isBooleanishNode,\n isReferenceNode,\n isRegularNode,\n RegularNode,\n SchemaCombinerName,\n SchemaNode,\n SchemaNodeKind,\n} from '@stoplight/json-schema-tree';\nimport * as React from 'react';\n\nimport { printName } from '../../utils';\nimport { getApplicableFormats } from '../../utils/getApplicableFormats';\n\nfunction shouldRenderName(type: SchemaNodeKind | SchemaCombinerName | '$ref'): boolean {\n return type === SchemaNodeKind.Array || type === SchemaNodeKind.Object || type === '$ref';\n}\n\nfunction getTypes(schemaNode: RegularNode): Array {\n return [schemaNode.types, schemaNode.combiners].reduce>(\n (values, value) => {\n if (value === null) {\n return values;\n }\n\n values.push(...value);\n return values;\n },\n [],\n );\n}\n\nexport const Types: React.FC<{ schemaNode: SchemaNode }> = ({ schemaNode }) => {\n if (isReferenceNode(schemaNode)) {\n return (\n \n {schemaNode.value ?? '$ref'}\n \n );\n }\n\n if (isBooleanishNode(schemaNode)) {\n return (\n \n {schemaNode.fragment ? 'any' : 'never'}\n \n );\n }\n\n if (!isRegularNode(schemaNode)) {\n return null;\n }\n\n const formats = getApplicableFormats(schemaNode);\n const types = getTypes(schemaNode);\n\n if (types.length === 0) {\n return (\n \n {formats === null ? 'any' : `<${formats[1]}>`}\n \n );\n }\n\n const rendered = types.map((type, i, { length }) => {\n let printedName;\n if (shouldRenderName(type)) {\n printedName = printName(schemaNode);\n }\n\n printedName ??= type + (formats === null || formats[0] !== type ? '' : `<${formats[1]}>`);\n\n return (\n \n \n {printedName}\n \n\n {i < length - 1 && (\n \n {' or '}\n \n )}\n \n );\n });\n\n return rendered.length > 1 ? {rendered} : <>{rendered};\n};\n\nTypes.displayName = 'JsonSchemaViewer.Types';\n","import { isRegularNode, RegularNode } from '@stoplight/json-schema-tree';\nimport * as React from 'react';\n\nexport interface ValidationsProps {\n validations: Record;\n hideExamples?: boolean;\n}\n\ntype ValidationFormat = {\n name: string;\n values: string[];\n};\n\nexport const numberValidationNames = [\n 'minimum',\n 'maximum',\n 'minLength',\n 'maxLength',\n 'minItems',\n 'maxItems',\n 'exclusiveMinimum',\n 'exclusiveMaximum',\n];\n\ntype NumberValidationNames = typeof numberValidationNames;\n\nconst exampleValidationNames = ['examples'];\n\nconst excludedValidations = ['exclusiveMinimum', 'exclusiveMaximum', 'readOnly', 'writeOnly'];\n\nconst numberValidationFormatters: Record string> = {\n minimum: value => `>= ${value}`,\n exclusiveMinimum: value => `> ${value}`,\n minItems: value => `>= ${value} items`,\n minLength: value => `>= ${value} characters`,\n maximum: value => `<= ${value}`,\n exclusiveMaximum: value => `< ${value}`,\n maxItems: value => `<= ${value} items`,\n maxLength: value => `<= ${value} characters`,\n};\n\nconst createStringFormatter = (nowrap: boolean | undefined) => (value: unknown) => {\n return nowrap && typeof value === 'string' ? value : JSON.stringify(value);\n};\n\nconst createValidationsFormatter =\n (name: string, options?: { exact?: boolean; nowrap?: boolean }) =>\n (value: unknown[] | unknown): ValidationFormat | null => {\n const values = Array.isArray(value) ? value : [value];\n if (values.length) {\n return {\n name: options?.exact ? name : values.length > 1 ? `${name}s` : `${name}`,\n values: values.map(createStringFormatter(options?.nowrap)),\n };\n }\n return null;\n };\n\nconst validationFormatters: Record ValidationFormat | null> = {\n enum: createValidationsFormatter('Allowed value', { nowrap: true }),\n examples: createValidationsFormatter('Example', { nowrap: true }),\n multipleOf: createValidationsFormatter('Multiple of', { exact: true }),\n pattern: createValidationsFormatter('Match pattern', { exact: true, nowrap: true }),\n default: createValidationsFormatter('Default', { exact: true, nowrap: true }),\n style: createValidationsFormatter('Style', { exact: true, nowrap: true }),\n};\n\nconst oasFormats = {\n int32: {\n minimum: 0 - 2 ** 31,\n maximum: 2 ** 31 - 1,\n },\n int64: {\n minimum: Number.MIN_SAFE_INTEGER,\n maximum: Number.MAX_SAFE_INTEGER,\n },\n float: {\n minimum: 0 - 2 ** 128,\n maximum: 2 ** 128 - 1,\n },\n double: {\n minimum: 0 - Number.MAX_VALUE,\n maximum: Number.MAX_VALUE,\n },\n byte: {\n pattern: '^[\\\\w\\\\d+\\\\/=]*$',\n },\n};\n\nfunction isOasFormat(format: string): format is keyof typeof oasFormats {\n return format in oasFormats;\n}\n\nfunction filterOutOasFormatValidations(format: string, values: Record) {\n if (!isOasFormat(format)) {\n return values;\n }\n\n const newValues = { ...values };\n\n for (const [key, value] of Object.entries(oasFormats[format])) {\n if (value === newValues[key]) {\n delete newValues[key];\n }\n }\n\n return newValues;\n}\n\nfunction pick>(obj: T, keys: string[]): Partial {\n const result: Partial = {};\n for (const key of keys) {\n if (key in obj) {\n result[key as keyof T] = obj[key as keyof T];\n }\n }\n return result;\n}\n\nfunction omit>(obj: T, keys: string[]): Partial {\n const result = { ...obj };\n for (const key of keys) {\n delete result[key as keyof T];\n }\n return result;\n}\n\nfunction capitalize(str: string): string {\n return str.charAt(0).toUpperCase() + str.slice(1);\n}\n\nfunction uniq(arr: T[]): T[] {\n return [...new Set(arr)];\n}\n\nexport const Validations: React.FC = ({ validations, hideExamples }) => {\n const numberValidations = pick(validations, numberValidationNames);\n const keyValueValidations = omit(validations, [\n ...Object.keys(numberValidations),\n ...excludedValidations,\n ...(hideExamples ? exampleValidationNames : []),\n ]);\n\n return (\n
\n \n \n
\n );\n};\n\nconst NumberValidations: React.FC<{\n validations: Partial>;\n}> = ({ validations }) => {\n const entries = Object.entries(validations);\n if (!entries.length) {\n return null;\n }\n return (\n
\n {entries\n .map(([key, value]) => numberValidationFormatters[key](value))\n .map((value, i) => (\n \n ))}\n
\n );\n};\n\nconst KeyValueValidations: React.FC<{ validations: Record }> = ({ validations }) => (\n <>\n {Object.keys(validations)\n .filter(key => Object.keys(validationFormatters).includes(key) && validations[key] !== void 0)\n .map(key => {\n const validation = validationFormatters[key](validations[key]);\n if (validation) {\n return ;\n } else {\n return null;\n }\n })}\n \n);\n\nconst KeyValueValidation: React.FC<{ name: string; values: string[] }> = ({ name, values }) => {\n return (\n
\n {capitalize(name)}:\n
\n {uniq(values).map(value => (\n \n ))}\n
\n
\n );\n};\n\nconst Value: React.FC<{ name: string }> = ({ name }) => (\n {name}\n);\n\nexport function validationCount(schemaNode: RegularNode) {\n const validations = getValidationsFromSchema(schemaNode);\n const validationKeys = Object.keys(omit(validations, excludedValidations));\n return uniq(validationKeys.map(key => ([...numberValidationNames].includes(key) ? 'number' : key))).length;\n}\n\nconst getArrayValidations = (schemaNode: RegularNode) => {\n if (schemaNode.children?.length === 1 && isRegularNode(schemaNode.children[0])) {\n if (schemaNode.children[0].enum !== null) {\n return { enum: schemaNode.children[0].enum };\n } else if (schemaNode.children[0].fragment.pattern !== void 0) {\n return { pattern: schemaNode.children[0].fragment.pattern };\n }\n }\n return null;\n};\n\nexport function getValidationsFromSchema(schemaNode: RegularNode) {\n return {\n ...(schemaNode.enum !== null\n ? { enum: schemaNode.enum }\n : schemaNode.primaryType === 'array'\n ? // in case schemaNode is type: \"array\", check if its child has an additional validation\n getArrayValidations(schemaNode)\n : null),\n ...('annotations' in schemaNode\n ? {\n ...(schemaNode.annotations.default !== void 0 ? { default: schemaNode.annotations.default } : null),\n ...(schemaNode.annotations.examples ? { examples: schemaNode.annotations.examples } : null),\n }\n : null),\n ...getFilteredValidations(schemaNode),\n };\n}\n\nfunction getFilteredValidations(schemaNode: RegularNode) {\n if (schemaNode.format !== null) {\n return filterOutOasFormatValidations(schemaNode.format, schemaNode.validations);\n }\n\n return schemaNode.validations;\n}\n","import { extractPointerFromRef, pointerToPath } from '@stoplight/json';\nimport { isReferenceNode, isRegularNode, SchemaNode } from '@stoplight/json-schema-tree';\nimport * as React from 'react';\n\nimport { isComplexArray, isNonEmptyParentNode } from '../../tree';\nimport { printName } from '../../utils';\n\n/** one option among several mutually exclusive sub-schemas */\nexport type Choice = {\n title: string;\n type: SchemaNode;\n};\n\nfunction last(arr: T[]): T | undefined {\n return arr[arr.length - 1];\n}\n\nfunction calculateChoiceTitle(node: SchemaNode, isPlural: boolean): string {\n const primitiveSuffix = isPlural ? 's' : '';\n if (isRegularNode(node)) {\n // Check for explicit title first\n const fragment = node.originalFragment as { \n title?: string; \n properties?: Record;\n oneOf?: Array<{ title?: string }>;\n anyOf?: Array<{ title?: string }>;\n };\n if (fragment.title) {\n return fragment.title;\n }\n \n const realName = printName(node, { shouldUseRefNameFallback: true });\n if (realName) {\n return realName;\n }\n \n // For objects without a title, try to create a meaningful name\n if (node.primaryType === 'object') {\n // If this object contains a nested oneOf/anyOf, use titles from those\n const nestedCombiner = fragment.oneOf || fragment.anyOf;\n if (nestedCombiner && nestedCombiner.length > 0) {\n const nestedTitles = nestedCombiner\n .map(item => item.title)\n .filter((t): t is string => typeof t === 'string');\n if (nestedTitles.length > 0) {\n return nestedTitles.join(' / ');\n }\n }\n \n if (fragment.properties) {\n const propKeys = Object.keys(fragment.properties);\n if (propKeys.length > 0) {\n // Try to find a distinguishing property by looking at the first property's type\n const firstProp = fragment.properties[propKeys[0]] as { type?: string } | undefined;\n if (firstProp?.type && propKeys.length <= 3) {\n // e.g., \"object (audio: object)\" or \"object (audio: string)\"\n return `object (${propKeys[0]}: ${firstProp.type})`;\n }\n // Just list the property names if there are few\n if (propKeys.length <= 2) {\n return `object {${propKeys.join(', ')}}`;\n }\n }\n }\n // Fall back to \"object\" for plain objects without distinguishing features\n return 'object' + primitiveSuffix;\n }\n \n return node.primaryType !== null\n ? node.primaryType + primitiveSuffix\n : 'any';\n }\n if (isReferenceNode(node)) {\n if (node.value) {\n const value = extractPointerFromRef(node.value);\n const lastPiece = !node.error && value ? last(pointerToPath(value)) : null;\n if (typeof lastPiece === 'string') {\n return lastPiece.split('.')[0];\n }\n }\n return '$ref' + primitiveSuffix;\n }\n\n return 'any';\n}\n\nfunction makeChoice(node: SchemaNode): Choice {\n return {\n type: node,\n title: calculateChoiceTitle(node, false),\n };\n}\n\nfunction makeArrayChoice(node: SchemaNode, combiner?: string): Choice {\n const itemTitle = calculateChoiceTitle(node, true);\n const title = itemTitle !== 'any' ? `array ${combiner ? `(${combiner})` : null} [${itemTitle}]` : 'array';\n return {\n type: node,\n title,\n };\n}\n\n/**\n * Enumerates the sub-schema type for a given node.\n *\n * Usually a node has one choice, only one possible type: itself. If a node is\n * a oneOf or anyOf combiner, the possible types are the sub-types of the\n * combiner.\n */\nexport const useChoices = (schemaNode: SchemaNode) => {\n const choices: Choice[] = React.useMemo(() => {\n // handle flattening of arrays that contain oneOfs, same logic as below\n if (\n isComplexArray(schemaNode) &&\n isNonEmptyParentNode(schemaNode.children[0]) &&\n shouldShowChildSelector(schemaNode.children[0])\n ) {\n return schemaNode.children[0].children.map(child =>\n makeArrayChoice(child, schemaNode.children[0].combiners?.[0]),\n );\n }\n\n // if current node is a combiner, offer its children\n if (isNonEmptyParentNode(schemaNode) && shouldShowChildSelector(schemaNode)) {\n return schemaNode.children.map(child => makeChoice(child));\n }\n // regular node, single choice - itself\n return [makeChoice(schemaNode)];\n }, [schemaNode]);\n\n const defaultChoice = choices[0];\n\n const [selectedChoice, setSelectedChoice] = React.useState(defaultChoice);\n\n React.useEffect(() => {\n setSelectedChoice(defaultChoice);\n }, [defaultChoice]);\n\n const actualSelectedChoice = selectedChoice && choices.includes(selectedChoice) ? selectedChoice : defaultChoice;\n\n return { selectedChoice: actualSelectedChoice, setSelectedChoice, choices };\n};\n\nconst shouldShowChildSelector = (schemaNode: SchemaNode) =>\n isNonEmptyParentNode(schemaNode) && ['anyOf', 'oneOf'].includes(schemaNode.combiners?.[0] ?? '');\n","import { isMirroredNode, isReferenceNode, isRegularNode, SchemaNode } from '@stoplight/json-schema-tree';\nimport { clsx } from 'clsx';\nimport { useSetAtom } from 'jotai';\nimport * as React from 'react';\n\nimport { COMBINER_NAME_MAP } from '../../consts';\nimport { useJSVOptionsContext } from '../../contexts';\nimport { getNodeId, getOriginalNodeId } from '../../hash';\nimport { isPropertyRequired, visibleChildren } from '../../tree';\nimport { extractVendorExtensions } from '../../utils/extractVendorExtensions';\nimport {\n Caret,\n ChildStack,\n Description,\n Divider,\n Error,\n getValidationsFromSchema,\n NodeAnnotation,\n Properties,\n Select,\n Types,\n useHasProperties,\n Validations,\n} from '../shared';\nimport { hoveredNodeAtom, isNodeHoveredAtom } from './state';\nimport { useChoices } from './useChoices';\n\ntype ChangeType = 'added' | 'removed' | 'modified';\n\nexport interface SchemaRowProps {\n schemaNode: SchemaNode;\n nestingLevel: number;\n pl?: number;\n parentNodeId?: string;\n parentChangeType?: ChangeType;\n}\n\nexport const SchemaRow: React.FC = React.memo(\n ({ schemaNode, nestingLevel, pl, parentNodeId, parentChangeType }) => {\n const {\n defaultExpandedDepth,\n renderRowAddon,\n renderExtensionAddon,\n onGoToRef,\n hideExamples,\n renderRootTreeLines,\n nodeHasChanged,\n viewMode,\n } = useJSVOptionsContext();\n\n const setHoveredNode = useSetAtom(hoveredNodeAtom);\n\n const nodeId = getNodeId(schemaNode, parentNodeId);\n\n // @ts-expect-error originalFragment does exist...\n const originalNodeId = schemaNode.originalFragment?.$ref ? getOriginalNodeId(schemaNode, parentNodeId) : nodeId;\n const mode = viewMode === 'standalone' ? undefined : viewMode;\n const hasChanged = nodeHasChanged?.({ nodeId: originalNodeId, mode });\n\n const [isExpanded, setExpanded] = React.useState(\n !isMirroredNode(schemaNode) && nestingLevel <= defaultExpandedDepth,\n );\n\n const { selectedChoice, setSelectedChoice, choices } = useChoices(schemaNode);\n const typeToShow = selectedChoice.type;\n const description = isRegularNode(typeToShow) ? typeToShow.annotations.description : null;\n\n const rootLevel = renderRootTreeLines ? 1 : 2;\n const childNodes = React.useMemo(() => visibleChildren(typeToShow), [typeToShow]);\n const combiner = isRegularNode(schemaNode) && schemaNode.combiners?.length ? schemaNode.combiners[0] : null;\n const isCollapsible = childNodes.length > 0;\n const isRootLevel = nestingLevel < rootLevel;\n\n const required = isPropertyRequired(schemaNode);\n const deprecated = isRegularNode(schemaNode) && schemaNode.deprecated;\n const validations = isRegularNode(schemaNode) ? schemaNode.validations : {};\n const hasProperties = useHasProperties({ required, deprecated, validations });\n\n const [totalVendorExtensions, vendorExtensions] = React.useMemo(\n () => extractVendorExtensions(schemaNode.fragment),\n [schemaNode.fragment],\n );\n const hasVendorProperties = totalVendorExtensions > 0;\n\n const annotationRootOffset = renderRootTreeLines ? 0 : 8;\n let annotationLeftOffset = -20 - annotationRootOffset;\n if (nestingLevel > 1) {\n annotationLeftOffset =\n -1 * 29 * Math.max(nestingLevel - 1, 1) - Math.min(nestingLevel, 2) * 2 - 16 - annotationRootOffset;\n\n if (!renderRootTreeLines) {\n annotationLeftOffset += 27;\n }\n }\n\n if (parentChangeType === 'added' && hasChanged && hasChanged.type === 'removed') {\n return null;\n }\n\n if (parentChangeType === 'removed' && hasChanged && hasChanged.type === 'added') {\n return null;\n }\n\n const lastSubpath = schemaNode.subpath.length > 0 ? schemaNode.subpath[schemaNode.subpath.length - 1] : null;\n const isHoveredAtom = isNodeHoveredAtom(schemaNode);\n\n return (\n <>\n {\n e.stopPropagation();\n setHoveredNode(selectedChoice.type);\n }}\n >\n {!isRootLevel && (\n \n )}\n {parentChangeType !== 'added' && parentChangeType !== 'removed' ? (\n \n ) : null}\n
\n setExpanded(!isExpanded) : undefined}\n >\n {isCollapsible ? : null}\n
\n {schemaNode.subpath.length > 0 && shouldShowPropertyName(schemaNode) && (\n \n {lastSubpath}\n \n )}\n\n {choices.length === 1 && }\n\n {onGoToRef && isReferenceNode(schemaNode) && schemaNode.external ? (\n {\n e.preventDefault();\n e.stopPropagation();\n onGoToRef(schemaNode);\n }}\n >\n (go to ref)\n \n ) : null}\n\n {schemaNode.subpath.length > 1 && schemaNode.subpath[0] === 'patternProperties' ? (\n (pattern property)\n ) : null}\n\n {choices.length > 1 && (\n ({\n value: String(index),\n label: choice.title,\n }))}\n value={String(choices.indexOf(selectedChoice))}\n onChange={selectedIndex => setSelectedChoice(choices[Number(selectedIndex)])}\n />\n )}\n
\n {hasProperties && }\n \n
\n {typeof description === 'string' &&\n (!combiner || schemaNode.parent?.fragment.description !== description) &&\n description.length > 0 && }\n \n {hasVendorProperties && renderExtensionAddon ? (\n
{renderExtensionAddon({ schemaNode, nestingLevel, vendorExtensions })}
\n ) : null}\n \n \n {renderRowAddon ?
{renderRowAddon({ schemaNode, nestingLevel })}
: null}\n \n {isCollapsible && isExpanded ? (\n \n ) : null}\n \n );\n },\n);\n\nSchemaRow.displayName = 'SchemaRow';\n\nfunction shouldShowPropertyName(schemaNode: SchemaNode) {\n return (\n schemaNode.subpath.length === 2 &&\n (schemaNode.subpath[0] === 'properties' || schemaNode.subpath[0] === 'patternProperties')\n );\n}\n","import { isPlainObject } from '@stoplight/json';\nimport { isRegularNode, RegularNode, SchemaFragment } from '@stoplight/json-schema-tree';\nimport { Menu } from '@base-ui/react/menu';\nimport { CaretDown } from '@phosphor-icons/react';\nimport * as React from 'react';\n\nimport { COMBINER_NAME_MAP } from '../../consts';\nimport { useJSVOptionsContext } from '../../contexts';\nimport { isComplexArray, isDictionaryNode, visibleChildren } from '../../tree';\nimport { extractVendorExtensions } from '../../utils/extractVendorExtensions';\nimport { ChildStack, Description, Error, getValidationsFromSchema, Validations } from '../shared';\nimport { SchemaRow, SchemaRowProps } from './SchemaRow';\nimport { useChoices } from './useChoices';\n\nfunction isEmpty(obj: Record): boolean {\n return Object.keys(obj).length === 0;\n}\n\nfunction getStoplightId(fragment: SchemaFragment | boolean): string | undefined {\n if (typeof fragment === 'boolean') return undefined;\n const xStoplight = fragment['x-stoplight' as keyof typeof fragment];\n if (isPlainObject(xStoplight)) {\n const id = (xStoplight as Record).id;\n return typeof id === 'string' ? id : undefined;\n }\n return undefined;\n}\n\nexport const TopLevelSchemaRow: React.FC & { skipDescription?: boolean }> = ({\n schemaNode,\n skipDescription,\n}) => {\n const { renderExtensionAddon } = useJSVOptionsContext();\n\n const { selectedChoice, setSelectedChoice, choices } = useChoices(schemaNode);\n const childNodes = React.useMemo(() => visibleChildren(selectedChoice.type), [selectedChoice.type]);\n const nestingLevel = 0;\n\n const nodeId = getStoplightId(schemaNode.fragment);\n \n const [totalVendorExtensions, vendorExtensions] = React.useMemo(\n () => extractVendorExtensions(schemaNode.fragment),\n [schemaNode.fragment],\n );\n const hasVendorProperties = totalVendorExtensions > 0;\n\n // oneOf/anyOf combiners get a dropdown selector - check this before object flattening\n if (isRegularNode(schemaNode) && choices.length > 1) {\n const combiner = isRegularNode(schemaNode) && schemaNode.combiners?.length ? schemaNode.combiners[0] : null;\n\n return (\n <>\n {schemaNode.annotations.description !== schemaNode.parent?.fragment.description && (\n \n )}\n
\n \n \n {selectedChoice.title}\n \n \n \n \n \n {choices.map((choice, index) => (\n setSelectedChoice(choice)}\n >\n {choice.title}\n \n ))}\n \n \n \n \n\n {combiner !== null ? (\n \n {`(${COMBINER_NAME_MAP[combiner]})`}\n \n ) : null}\n
\n {childNodes.length > 0 ? (\n \n ) : combiner ? (\n \n ) : null}\n \n );\n }\n\n // regular objects are flattened at the top level\n if (isRegularNode(schemaNode) && isPureObjectNode(schemaNode)) {\n return (\n <>\n {!skipDescription ? : null}\n {hasVendorProperties && renderExtensionAddon\n ? renderExtensionAddon({ schemaNode, nestingLevel, vendorExtensions })\n : null}\n \n \n \n );\n }\n\n if (isComplexArray(schemaNode) && isPureObjectNode(schemaNode.children[0])) {\n const validations = isRegularNode(schemaNode) ? getValidationsFromSchema(schemaNode) : {};\n return (\n <>\n \n\n
array of:
\n\n {!isEmpty(validations) && (\n
\n \n
\n )}\n\n {childNodes.length > 0 ? (\n \n ) : null}\n \n );\n }\n\n return ;\n};\n\nfunction isPureObjectNode(schemaNode: RegularNode) {\n return schemaNode.primaryType === 'object' && schemaNode.types?.length === 1 && !isDictionaryNode(schemaNode);\n}\n","import {\n isRegularNode,\n RootNode,\n SchemaTree as JsonSchemaTree,\n SchemaTreeRefDereferenceFn,\n} from '@stoplight/json-schema-tree';\nimport { clsx } from 'clsx';\nimport { Provider, useSetAtom } from 'jotai';\nimport * as React from 'react';\n\nimport { JSVOptions, JSVOptionsContextProvider } from '../contexts';\nimport { shouldNodeBeIncluded } from '../tree/utils';\nimport { JSONSchema } from '../types';\nimport { PathCrumbs } from './PathCrumbs';\nimport { TopLevelSchemaRow } from './SchemaRow';\nimport { hoveredNodeAtom } from './SchemaRow/state';\n\nexport type JsonSchemaProps = Partial & {\n schema: JSONSchema;\n emptyText?: string;\n className?: string;\n resolveRef?: SchemaTreeRefDereferenceFn;\n /** Controls the level of recursion of refs. Prevents overly complex trees and running out of stack depth. */\n maxRefDepth?: number;\n onTreePopulated?: (props: { rootNode: RootNode; nodeCount: number }) => void;\n maxHeight?: number;\n parentCrumbs?: string[];\n skipTopLevelDescription?: boolean;\n /** Theme mode - set to \"dark\" for dark mode styling */\n 'data-theme'?: 'dark' | 'light';\n};\n\nexport const JsonSchemaViewer: React.FC = ({\n viewMode = 'standalone',\n defaultExpandedDepth = 1,\n onGoToRef,\n renderRowAddon,\n renderExtensionAddon,\n hideExamples,\n renderRootTreeLines,\n disableCrumbs,\n nodeHasChanged,\n skipTopLevelDescription,\n markup,\n ...rest\n}) => {\n const options = React.useMemo(\n () => ({\n defaultExpandedDepth,\n viewMode,\n onGoToRef,\n renderRowAddon,\n renderExtensionAddon,\n hideExamples,\n renderRootTreeLines,\n disableCrumbs,\n nodeHasChanged,\n markup\n }),\n [\n defaultExpandedDepth,\n viewMode,\n onGoToRef,\n renderRowAddon,\n renderExtensionAddon,\n hideExamples,\n renderRootTreeLines,\n disableCrumbs,\n nodeHasChanged,\n markup\n ],\n );\n\n return (\n \n \n \n \n \n );\n};\n\nconst JsonSchemaViewerInner: React.FC<\n Pick<\n JsonSchemaProps,\n | 'schema'\n | 'viewMode'\n | 'className'\n | 'resolveRef'\n | 'maxRefDepth'\n | 'emptyText'\n | 'onTreePopulated'\n | 'maxHeight'\n | 'parentCrumbs'\n | 'skipTopLevelDescription'\n | 'data-theme'\n >\n> = ({\n schema,\n viewMode,\n className,\n resolveRef,\n maxRefDepth,\n emptyText = 'No schema defined',\n onTreePopulated,\n maxHeight,\n parentCrumbs,\n skipTopLevelDescription,\n 'data-theme': dataTheme,\n}) => {\n const setHoveredNode = useSetAtom(hoveredNodeAtom);\n const onMouseLeave = React.useCallback(() => {\n setHoveredNode(null);\n }, [setHoveredNode]);\n\n const { jsonSchemaTreeRoot, nodeCount } = React.useMemo(() => {\n const jsonSchemaTree = new JsonSchemaTree(schema, {\n mergeAllOf: true,\n refResolver: resolveRef,\n maxRefDepth,\n });\n\n let nodeCount = 0;\n\n jsonSchemaTree.walker.hookInto('filter', node => {\n if (shouldNodeBeIncluded(node, viewMode)) {\n nodeCount++;\n return true;\n }\n return false;\n });\n jsonSchemaTree.populate();\n\n return {\n jsonSchemaTreeRoot: jsonSchemaTree.root,\n nodeCount,\n };\n }, [schema, resolveRef, maxRefDepth, viewMode]);\n\n React.useEffect(() => {\n onTreePopulated?.({\n rootNode: jsonSchemaTreeRoot,\n nodeCount: nodeCount,\n });\n }, [jsonSchemaTreeRoot, onTreePopulated, nodeCount]);\n\n const isEmpty = React.useMemo(\n () => jsonSchemaTreeRoot.children.every(node => !isRegularNode(node) || node.unknown),\n [jsonSchemaTreeRoot],\n );\n\n if (isEmpty) {\n return (\n
\n {emptyText}\n
\n );\n }\n\n return (\n \n \n
\n \n
\n \n );\n};\n\n// Error boundary wrapper\nexport class JsonSchemaViewerErrorBoundary extends React.Component<\n { children: React.ReactNode; fallback?: React.ReactNode },\n { hasError: boolean; error: Error | null }\n> {\n constructor(props: { children: React.ReactNode; fallback?: React.ReactNode }) {\n super(props);\n this.state = { hasError: false, error: null };\n }\n\n static getDerivedStateFromError(error: Error) {\n return { hasError: true, error };\n }\n\n render() {\n if (this.state.hasError) {\n if (this.props.fallback) {\n return this.props.fallback;\n }\n return (\n
\n Error\n {this.state.error !== null ? `: ${this.state.error.message}` : null}\n
\n );\n }\n\n return this.props.children;\n }\n}\n"]} +\ No newline at end of file diff --git a/docsite/src/components/GenericConfiguration.mdx b/docsite/src/components/GenericConfiguration.mdx index 837e6f2f..6ead7bdd 100644 --- a/docsite/src/components/GenericConfiguration.mdx +++ b/docsite/src/components/GenericConfiguration.mdx @@ -1,6 +1,9 @@ import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import CodeBlock from '@theme/CodeBlock'; +import ExplorerFetch from '@site/src/components/Schema/ExplorerFetch'; +import EditorFetch from '@site/src/components/Schema/SchemaEditorFetch'; +import './GenericConfiguration.scss'; @@ -10,10 +13,20 @@ import CodeBlock from '@theme/CodeBlock'; - - - - or +
+
+ +
+
+ + {/* */} +
+
@@ -25,4 +38,4 @@ import CodeBlock from '@theme/CodeBlock'; or -
+ \ No newline at end of file diff --git a/docsite/src/components/GenericConfiguration.scss b/docsite/src/components/GenericConfiguration.scss new file mode 100644 index 00000000..1e76e977 --- /dev/null +++ b/docsite/src/components/GenericConfiguration.scss @@ -0,0 +1,19 @@ +.schemaWrapper { + margin-top: 1em; + display: flex; + flex-direction: row; + row-gap: 1em; + column-gap: 1em; +} + +@media screen and (max-width: 1378px) { + .schemaWrapper { + flex-direction: column; + } +} + +@media screen and (max-width: 500px) { + .fileEditor { + display: none; + } +} \ No newline at end of file diff --git a/docsite/src/components/JSONSchemaData.tsx b/docsite/src/components/JSONSchemaData.tsx deleted file mode 100644 index 76414edc..00000000 --- a/docsite/src/components/JSONSchemaData.tsx +++ /dev/null @@ -1,44 +0,0 @@ -import React from "react" -import BrowserOnly from "@docusaurus/BrowserOnly" -import { useColorMode } from "@docusaurus/theme-common" - -import JSONSchemaEditor from "@theme/JSONSchemaEditor" -// Context -import { usePlaygroundContext } from "@site/src/contexts/PlaygroundContext" - -// Common stringify of the JSON -const STRINGIFY_JSON = (json: unknown) => JSON.stringify(json, null, "\t") - -function JSONSchemaDataInner(): JSX.Element { - const { - state: { userSchema, editorRef, data: value }, - updateState, - } = usePlaygroundContext() - - const { colorMode } = useColorMode() - - return ( -
- { - updateState({ editorRef: editor }) - }} - height={"70vh"} - key={STRINGIFY_JSON(userSchema)} - /> -
- ) -} - -export default function JSONSchemaDataComponent(): JSX.Element { - return ( - Loading...}> - {() => { - return - }} - - ) -} diff --git a/docsite/src/components/Playground.scss b/docsite/src/components/Playground.scss new file mode 100644 index 00000000..729a41db --- /dev/null +++ b/docsite/src/components/Playground.scss @@ -0,0 +1,19 @@ +.schemaWrapper2 { + margin: 1em; + display: flex; + flex-direction: row; + row-gap: 1em; + column-gap: 1em; +} + +@media screen and (max-width: 1280px) { + .schemaWrapper2 { + flex-direction: column; + } +} + +@media screen and (max-width: 500px) { + .fileEditor2 { + display: none; + } +} \ No newline at end of file diff --git a/docsite/src/components/PlaygroundInner.tsx b/docsite/src/components/PlaygroundInner.tsx index e0f15bd6..9fce549f 100644 --- a/docsite/src/components/PlaygroundInner.tsx +++ b/docsite/src/components/PlaygroundInner.tsx @@ -1,50 +1,63 @@ -import React from "react" +import React, {useEffect, useState} from "react" import BrowserOnly from "@docusaurus/BrowserOnly" +import {useColorMode} from '@docusaurus/theme-common'; import Schema from "@site/static/aio.json"; import ConfigExample from "@site/static/configExample.json"; -import JSONSchemaViewer from "@theme/JSONSchemaViewer" -import JSONSchemaEditor from "@theme/JSONSchemaEditor"; -import {useColorMode} from "@docusaurus/theme-common"; -const STRINGIFY_JSON = (json: unknown) => JSON.stringify(json, null, "\t") +import './Playground.scss'; +import { JsonSchemaViewer } from 'cf-json-schema-viz'; +import "./json-schema-viewer-styles.css"; +import "./modern-json-react-styles.css"; +import { ReactJsonEditor, createAjvValidator, type Content } from 'modern-react-json-editor'; +import f from "ajv-formats" + +const validator = createAjvValidator({ + schema: Schema, + ajvOptions: { + strict: "log", + strictSchema: "log", + allowUnionTypes: true, + }, + onCreateAjv: (ajv) => { + ajv.addKeyword('deprecationMessage'); + f.default(ajv); + return ajv; + } +}); -// based on https://github.com/jy95/docusaurus-json-schema-plugin/blob/main/testsite/src/components/PlaygroundInner.tsx function PlaygroundInner(): JSX.Element { - const { colorMode } = useColorMode() + const { + colorMode, // the "effective" color mode, never null + // colorModeChoice, // the color mode chosen by the user, can be null + // setColorMode, // set the color mode chosen by the user + } = useColorMode(); + + const [data, setData] = useState({json: ConfigExample }); return ( -
-
-
- +
+
+
-
- +
+ +
-
) } diff --git a/docsite/src/components/Schema/Explorer.tsx b/docsite/src/components/Schema/Explorer.tsx new file mode 100644 index 00000000..5f576e79 --- /dev/null +++ b/docsite/src/components/Schema/Explorer.tsx @@ -0,0 +1,38 @@ +import React, {useEffect, useState} from "react" +import BrowserOnly from "@docusaurus/BrowserOnly" + +//import './Explorer.scss'; +import { JsonSchemaViewer } from 'cf-json-schema-viz'; +import '../json-schema-viewer-styles.css' + +export interface ExplorerProps { + schema: object +} + +// based on https://github.com/jy95/docusaurus-json-schema-plugin/blob/main/testsite/src/components/PlaygroundInner.tsx +export default function Explorer(props: ExplorerProps): JSX.Element { + + //injectStyles(); + + return ( +
+ +
+ ) +} + +// export default function PlaygroundComponent(): JSX.Element { +// return ( +// Loading...
}> +// {() => { +// return +// }} +// +// ) +// } diff --git a/docsite/src/components/Schema/ExplorerFetch.tsx b/docsite/src/components/Schema/ExplorerFetch.tsx new file mode 100644 index 00000000..feb58d7e --- /dev/null +++ b/docsite/src/components/Schema/ExplorerFetch.tsx @@ -0,0 +1,48 @@ +import React, {useEffect, useState, Fragment} from "react" +//import BrowserOnly from "@docusaurus/BrowserOnly" + +import Explorer from './Explorer'; +import useBaseUrl from '@docusaurus/useBaseUrl'; + +export interface ExplorerFetchProps { + name: string +} + +export default function ExplorerFetchFunc(props: ExplorerFetchProps): JSX.Element { + + const [schema, setSchema] = useState(undefined as undefined | Error | object); + + const url = useBaseUrl(`/${props.name}.json`); + + useEffect( () => { + fetch( + url, + { + headers: { + 'Accept': 'application/json', + } + } + ) + .then((response) => response.json()) + .then((data) => setSchema(data)) + .catch( (err) => setSchema(err) ) + }, [setSchema, url]) + + return ( + + {schema === undefined &&
Loading ...
} + {schema !== undefined && schema instanceof Error &&
Houston we have a problem : {schema.message}
} + {schema !== undefined && !(schema instanceof Error) && } +
+ ) +} + +// export default function ExplorerFetch(props: ExplorerFetchProps): JSX.Element { +// return ( +// Loading...
}> +// {() => { +// return +// }} +// +// ) +// } diff --git a/docsite/src/components/Schema/ExplorerSSR.tsx b/docsite/src/components/Schema/ExplorerSSR.tsx new file mode 100644 index 00000000..75e4a493 --- /dev/null +++ b/docsite/src/components/Schema/ExplorerSSR.tsx @@ -0,0 +1,7 @@ +import Schema from "@site/static/aio.json"; +import Explorer from './Explorer'; + +export default function ExplorerSSR(): JSX.Element { + + return +} \ No newline at end of file diff --git a/docsite/src/components/Schema/SchemaEditor.tsx b/docsite/src/components/Schema/SchemaEditor.tsx new file mode 100644 index 00000000..3f7c61a4 --- /dev/null +++ b/docsite/src/components/Schema/SchemaEditor.tsx @@ -0,0 +1,62 @@ +import React, {useEffect, useState, useMemo} from "react" +import BrowserOnly from "@docusaurus/BrowserOnly" +import {useColorMode} from '@docusaurus/theme-common'; + +const STRINGIFY_JSON = (json: unknown) => JSON.stringify(json, null, "\t"); +import "../modern-json-react-styles.css"; +import { ReactJsonEditor, createAjvValidator, type Content } from 'modern-react-json-editor'; +import f from "ajv-formats" + +export interface SchemaEditorProps { + config: object | string + schema: object + height?: string +} + +// based on https://github.com/jy95/docusaurus-json-schema-plugin/blob/main/testsite/src/components/PlaygroundInner.tsx +function SchemaEditorInner(props: SchemaEditorProps): JSX.Element { + + const validator = useMemo(() => { + return createAjvValidator({ + schema: props.schema, + ajvOptions: { + strict: "log", + strictSchema: "log", + allowUnionTypes: true, + }, + onCreateAjv: (ajv) => { + ajv.addKeyword('deprecationMessage'); + f.default(ajv); + return ajv; + } +}); + },[props.schema]); + + + const [data, setData] = useState({json: props.config }); + + const { + colorMode, // the "effective" color mode, never null + } = useColorMode(); + + const val = typeof props.config === 'object' ? STRINGIFY_JSON(props.config) : props.config; + return ( +
+ +
+ ) +} + +export default function SchemaEditor(props: SchemaEditorProps): JSX.Element { + return ( + Loading...
}> + {() => { + return + }} + + ) +} diff --git a/docsite/src/components/Schema/SchemaEditorFetch.tsx b/docsite/src/components/Schema/SchemaEditorFetch.tsx new file mode 100644 index 00000000..70d7ec45 --- /dev/null +++ b/docsite/src/components/Schema/SchemaEditorFetch.tsx @@ -0,0 +1,65 @@ +import React, {useEffect, useState, Fragment} from "react" + +import useBaseUrl from '@docusaurus/useBaseUrl'; +import SchemaEditor from "./SchemaEditor"; +import json5 from 'json5'; + +export interface SchemdEditorFetchProps { + configName?: string + configContent?: string + schemaName: string +} + +export default function ExplorerFetchFunc(props: SchemdEditorFetchProps): JSX.Element { + + const [schema, setSchema] = useState(undefined as undefined | Error | object); + const [config, setConfig] = useState(undefined as undefined | Error | object); + + const schemaUrl = useBaseUrl(`/${props.schemaName}.json`); + const configUrl = props.configName !== undefined ? useBaseUrl(`/${props.configName}.json`) : undefined; + + useEffect( () => { + fetch( + schemaUrl, + { + headers: { + 'Accept': 'application/json', + } + } + ) + .then((response) => response.json()) + .then((data) => setSchema(data)) + .catch( (err) => setSchema(err) ) + }, [setSchema, schemaUrl]) + + useEffect( () => { + if(configUrl !== undefined) { + fetch( + configUrl, + { + headers: { + 'Accept': 'application/json', + } + } + ) + .then((response) => response.json()) + .then((data) => setConfig(data)) + .catch( (err) => setConfig(err) ) + } else if(props.configContent !== undefined) { + if(typeof props.configContent === 'string') { + setConfig(json5.parse(props.configContent)); + } else { + setConfig(props.configContent); + } + } + }, [setConfig, configUrl, props.configContent]) + + return ( + + {schema === undefined || config === undefined &&
Loading ...
} + {schema !== undefined && schema instanceof Error &&
Houston we have a problem : {schema.message}
} + {config !== undefined && config instanceof Error &&
Houston we have a problem : {config.message}
} + {schema !== undefined && !(schema instanceof Error) && config !== undefined && !(config instanceof Error) && } +
+ ) +} \ No newline at end of file diff --git a/docsite/src/components/json-schema-viewer-styles.css b/docsite/src/components/json-schema-viewer-styles.css new file mode 100644 index 00000000..5437fe72 --- /dev/null +++ b/docsite/src/components/json-schema-viewer-styles.css @@ -0,0 +1,480 @@ +/* JSON Schema Viewer - Pure CSS with CSS Custom Properties */ + +/* ======================================== + Theme Variables - Light Mode (default) + Define at :root so portaled elements inherit them + ======================================== */ +:root { + --jsv-font-sans: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; + --jsv-font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace; + --jsv-font-size: 0.875rem; + + /* Colors - Light Mode defaults */ + --jsv-color-body: #1a1a1a; + --jsv-color-muted: #6b7280; + --jsv-color-border: #e5e7eb; + --jsv-color-canvas: #f4f4f5; + --jsv-color-canvas-tint: #f4f4f5; + --jsv-color-bg: #ffffff; + + /* Semantic colors - Cloudflare orange as primary */ + --jsv-color-primary: #f6821f; + --jsv-color-danger: #dc2626; + --jsv-color-warning: #f97316; + --jsv-color-success: #16a34a; +} + +/* ======================================== + Theme Variables - Dark Mode + Cloudflare docs dark theme colors + ======================================== */ +:root[data-theme="dark"], +[data-theme="dark"] { + --jsv-color-body: #e4e4e7; + --jsv-color-muted: #a1a1aa; + --jsv-color-border: #3f3f46; + --jsv-color-canvas: #27272a; + --jsv-color-canvas-tint: #3f3f46; + --jsv-color-bg: #18181b; + + --jsv-color-primary: #f6821f; + --jsv-color-danger: #f87171; + --jsv-color-warning: #fb923c; + --jsv-color-success: #4ade80; +} + +/* ======================================== + Base Styles + ======================================== */ +.jsv-root { + font-size: var(--jsv-font-size); + font-family: var(--jsv-font-sans); + color: var(--jsv-color-body); + line-height: 1.5; + position: relative; +} + +.jsv-content { + padding-left: 2rem; + padding-right: 1rem; + padding-bottom: 0.5rem; + padding-top: 0.375rem; +} + +/* ======================================== + Schema Row + ======================================== */ +.jsv-row { + position: relative; + padding-top: 0.25rem; + padding-bottom: 0.25rem; + display: flex; + align-items: flex-start; + max-width: 100%; +} + +.jsv-row-content { + display: flex; + flex-direction: column; + gap: 0.125rem; + max-width: 100%; + flex: 1; + min-width: 0; +} + +.jsv-row-header { + display: flex; + align-items: center; + max-width: 100%; + gap: 0.25rem; +} + +/* Nubbin - horizontal connector from left border to property */ +.jsv-nubbin { + width: 0.75rem; + height: 0; + border-top: 1px solid var(--jsv-color-border); + flex-shrink: 0; + margin-top: 0.5rem; + margin-right: 0.5rem; + margin-left: -1rem; +} + +.jsv-nubbin-short { + width: 0.25rem; +} + +/* ======================================== + Child Stack (nested content with left border) + ======================================== */ +.jsv-child-stack { + font-size: var(--jsv-font-size); +} + +.jsv-child-stack-nested { + border-left: 1px solid var(--jsv-color-border); + margin-left: 0.5rem; + padding-left: 1rem; + margin-top: 0.25rem; +} + +/* ======================================== + Property Name + ======================================== */ +.jsv-property-name { + font-family: var(--jsv-font-mono); + font-weight: 600; + margin-right: 0.5rem; + flex-shrink: 0; +} + +/* ======================================== + Type Display + ======================================== */ +.jsv-type { + color: var(--jsv-color-muted); + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.jsv-types-container { + display: flex; + align-items: baseline; + font-size: var(--jsv-font-size); + min-width: 0; +} + +/* ======================================== + Badges (required, deprecated, read-only) + ======================================== */ +.jsv-badges { + display: flex; + align-items: center; + gap: 0.5rem; + flex-shrink: 0; +} + +.jsv-badge { + font-size: 0.75rem; +} + +.jsv-badge-required { + color: var(--jsv-color-warning); +} + +.jsv-badge-deprecated { + color: var(--jsv-color-warning); +} + +.jsv-badge-readonly { + color: var(--jsv-color-muted); +} + +/* ======================================== + Divider (horizontal line on hover) + ======================================== */ +.jsv-divider { + height: 1px; + flex: 1; + margin-left: 0.75rem; + margin-right: 0.75rem; + min-width: 1rem; + background-color: transparent; + transition: background-color 0.15s ease; +} + +.jsv-divider-visible { + background-color: var(--jsv-color-border); +} + +/* ======================================== + Description + ======================================== */ +.jsv-description { + font-size: var(--jsv-font-size); + color: var(--jsv-color-muted); + margin-top: 0.0625rem; + line-height: 1.4; +} + +/* ======================================== + Validations + ======================================== */ +.jsv-validations { + display: flex; + flex-wrap: wrap; + gap: 0.25rem; + align-items: center; + margin-top: 0.125rem; +} + +.jsv-validations-row { + display: flex; + flex-wrap: wrap; + gap: 0.25rem; + align-items: center; +} + +.jsv-validation { + display: flex; + align-items: baseline; + gap: 0.375rem; + color: var(--jsv-color-muted); + font-size: 0.75rem; +} + +.jsv-validation-label { + flex-shrink: 0; +} + +.jsv-validation-values { + display: flex; + flex-wrap: wrap; + gap: 0.25rem; + flex: 1; +} + +.jsv-validation-value { + padding: 0.0625rem 0.375rem; + background-color: var(--jsv-color-canvas-tint); + color: var(--jsv-color-muted); + border: 1px solid var(--jsv-color-border); + border-radius: 0.25rem; + font-family: var(--jsv-font-mono); + font-size: 0.75rem; + word-break: break-all; +} + +/* ======================================== + Caret (expand/collapse icon) + ======================================== */ +.jsv-caret { + width: 1.25rem; + height: 1.25rem; + margin-left: -1.5rem; + margin-right: 0.25rem; + color: var(--jsv-color-muted); + display: flex; + justify-content: center; + align-items: center; + cursor: pointer; + flex-shrink: 0; + transition: transform 0.15s ease; +} + +.jsv-caret:hover { + color: var(--jsv-color-body); +} + +.jsv-caret-expanded { + transform: rotate(90deg); +} + +/* ======================================== + Error Display + ======================================== */ +.jsv-error { + color: var(--jsv-color-danger); + display: flex; + align-items: center; + gap: 0.25rem; + font-size: 0.75rem; +} + +/* ======================================== + Change Annotations (added/removed/modified) + ======================================== */ +.jsv-annotation { + position: absolute; + width: 0.25rem; + height: 1rem; + border-radius: 0.125rem; + top: 50%; + transform: translateY(-50%); +} + +.jsv-annotation-added { + background-color: var(--jsv-color-success); +} + +.jsv-annotation-removed { + background-color: var(--jsv-color-danger); +} + +.jsv-annotation-modified { + background-color: var(--jsv-color-warning); +} + +/* ======================================== + Path Crumbs (sticky breadcrumb header) + Wrapper is sticky with height:0 (no layout impact) + Inner crumbs div is absolute, overlays content + ======================================== */ +.jsv-crumbs { + height: 2rem; + padding-left: 2rem; + padding-right: 1rem; + font-family: var(--jsv-font-mono); + font-size: var(--jsv-font-size); + line-height: 1; + z-index: 20; + background-color: var(--sl-color-bg, var(--jsv-color-bg, #fff)); + color: var(--jsv-color-muted); + display: flex; + align-items: center; + gap: 0.25rem; + border-bottom: 1px solid var(--jsv-color-border); + border-top-left-radius: 0.5rem; + border-top-right-radius: 0.5rem; + box-sizing: border-box; + /* Hidden by default */ + opacity: 0; + pointer-events: none; +} + +[data-theme="dark"] .jsv-crumbs, +:root[data-theme="dark"] .jsv-crumbs { + border-bottom-color: var(--sl-color-gray-5, #52525b); +} + +.jsv-crumbs[data-visible="true"] { + opacity: 1; + pointer-events: auto; +} + +.jsv-crumb-current { + color: var(--jsv-color-body); + font-weight: 600; +} + +/* ======================================== + Select / Menu Dropdown + ======================================== */ +.jsv-select-trigger { + display: inline-flex; + align-items: center; + gap: 0.375rem; + padding: 0.125rem 0.5rem; + font-size: var(--jsv-font-size); + font-family: var(--jsv-font-sans); + background-color: transparent; + border: 1px solid var(--jsv-color-border); + border-radius: 0.25rem; + cursor: pointer; + color: var(--jsv-color-muted); + line-height: 1.4; + transition: background-color 0.15s ease, border-color 0.15s ease; +} + +.jsv-select-trigger:hover { + background-color: var(--jsv-color-canvas); + border-color: var(--jsv-color-muted); +} + +.jsv-select-trigger:focus { + outline: none; + box-shadow: 0 0 0 2px var(--jsv-color-primary); +} + +.jsv-select-positioner { + z-index: 9999 !important; + position: relative; +} + +.jsv-select-popup { + background-color: var(--jsv-color-bg); + border: 1px solid var(--jsv-color-border); + border-radius: 0.375rem; + box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15), 0 2px 4px rgba(0, 0, 0, 0.1); + padding: 0.25rem 0; + min-width: 10rem; + overflow: hidden; + font-family: var(--jsv-font-sans); + font-size: var(--jsv-font-size); +} + +.jsv-select-item { + padding: 0.5rem 0.75rem; + padding-left: 2rem; + font-size: var(--jsv-font-size); + cursor: pointer; + display: flex; + align-items: center; + gap: 0.5rem; + outline: none; + color: var(--jsv-color-body); + background-color: var(--jsv-color-bg); + position: relative; + transition: background-color 0.1s ease; +} + +.jsv-select-item:hover, +.jsv-select-item:focus, +.jsv-select-item[data-highlighted] { + background-color: var(--jsv-color-canvas); +} + +.jsv-select-item[data-selected] { + font-weight: 600; +} + +.jsv-select-item-indicator { + position: absolute; + left: 0.625rem; + top: 50%; + transform: translateY(-50%); + display: flex; + align-items: center; + justify-content: center; + color: var(--jsv-color-primary); +} + +/* ======================================== + Top Level Styles + ======================================== */ +.jsv-top-label { + font-family: var(--jsv-font-mono); + font-weight: 600; + font-size: var(--jsv-font-size); + padding-bottom: 0.5rem; +} + +.jsv-top-section { + display: flex; + align-items: center; + gap: 0.75rem; + padding-bottom: 0.5rem; +} + +.jsv-combiner-label { + display: flex; + align-items: center; + color: var(--jsv-color-muted); + font-size: var(--jsv-font-size); +} + +/* ======================================== + Link Styles + ======================================== */ +.jsv-link { + color: var(--jsv-color-primary); + cursor: pointer; + text-decoration: none; + margin-left: 0.5rem; +} + +.jsv-link:hover { + text-decoration: underline; +} + +/* ======================================== + Misc Helpers + ======================================== */ +.jsv-cursor-pointer { + cursor: pointer; +} + +.jsv-ml-2 { + margin-left: 0.5rem; +} diff --git a/docsite/src/components/modern-json-react-styles.css b/docsite/src/components/modern-json-react-styles.css new file mode 100644 index 00000000..535a43d8 --- /dev/null +++ b/docsite/src/components/modern-json-react-styles.css @@ -0,0 +1 @@ +.jse-theme-dark{--jse-theme: dark;--jse-theme-color: #2f6dd0;--jse-theme-color-highlight: #467cd2;--jse-background-color: #1e1e1e;--jse-text-color: #d4d4d4;--jse-text-color-inverse: #4d4d4d;--jse-main-border: 1px solid #4f4f4f;--jse-menu-color: #fff;--jse-modal-background: #2f2f2f;--jse-modal-overlay-background: rgba(0, 0, 0, .5);--jse-modal-code-background: #2f2f2f;--jse-tooltip-color: var(--jse-text-color);--jse-tooltip-background: #4b4b4b;--jse-tooltip-border: 1px solid #737373;--jse-tooltip-action-button-color: inherit;--jse-tooltip-action-button-background: #737373;--jse-panel-background: #333333;--jse-panel-background-border: 1px solid #464646;--jse-panel-color: var(--jse-text-color);--jse-panel-color-readonly: #737373;--jse-panel-border: 1px solid #3c3c3c;--jse-panel-button-color-highlight: #e5e5e5;--jse-panel-button-background-highlight: #464646;--jse-navigation-bar-background: #656565;--jse-navigation-bar-background-highlight: #7e7e7e;--jse-navigation-bar-dropdown-color: var(--jse-text-color);--jse-context-menu-background: #4b4b4b;--jse-context-menu-background-highlight: #595959;--jse-context-menu-separator-color: #595959;--jse-context-menu-color: var(--jse-text-color);--jse-context-menu-pointer-background: #737373;--jse-context-menu-pointer-background-highlight: #818181;--jse-context-menu-pointer-color: var(--jse-context-menu-color);--jse-key-color: #9cdcfe;--jse-value-color: var(--jse-text-color);--jse-value-color-number: #b5cea8;--jse-value-color-boolean: #569cd6;--jse-value-color-null: #569cd6;--jse-value-color-string: #ce9178;--jse-value-color-url: #ce9178;--jse-delimiter-color: #949494;--jse-edit-outline: 2px solid var(--jse-text-color);--jse-selection-background-color: #464646;--jse-selection-background-inactive-color: #333333;--jse-hover-background-color: #343434;--jse-active-line-background-color: rgba(255, 255, 255, .06);--jse-search-match-background-color: #343434;--jse-collapsed-items-background-color: #333333;--jse-collapsed-items-selected-background-color: #565656;--jse-collapsed-items-link-color: #b2b2b2;--jse-collapsed-items-link-color-highlight: #ec8477;--jse-search-match-color: #724c27;--jse-search-match-outline: 1px solid #966535;--jse-search-match-active-color: #9f6c39;--jse-search-match-active-outline: 1px solid #bb7f43;--jse-tag-background: #444444;--jse-tag-color: #bdbdbd;--jse-table-header-background: #333333;--jse-table-header-background-highlight: #424242;--jse-table-row-odd-background: rgba(255, 255, 255, .1);--jse-input-background: #3d3d3d;--jse-input-border: var(--jse-main-border);--jse-button-background: #808080;--jse-button-background-highlight: #7a7a7a;--jse-button-color: #e0e0e0;--jse-button-secondary-background: #494949;--jse-button-secondary-background-highlight: #5d5d5d;--jse-button-secondary-background-disabled: #9d9d9d;--jse-button-secondary-color: var(--jse-text-color);--jse-a-color: #55abff;--jse-a-color-highlight: #4387c9;--jse-svelte-select-background: #3d3d3d;--jse-svelte-select-border: 1px solid #4f4f4f;--list-background: #3d3d3d;--item-hover-bg: #505050;--multi-item-bg: #5b5b5b;--input-color: #d4d4d4;--multi-clear-bg: #8a8a8a;--multi-item-clear-icon-color: #d4d4d4;--multi-item-outline: 1px solid #696969;--list-shadow: 0 2px 8px 0 rgba(0, 0, 0, .4);--jse-color-picker-background: #656565;--jse-color-picker-border-box-shadow: #8c8c8c 0 0 0 1px} diff --git a/docsite/src/pages/playground.tsx b/docsite/src/pages/playground.tsx index 97b8408e..6b5c13bf 100644 --- a/docsite/src/pages/playground.tsx +++ b/docsite/src/pages/playground.tsx @@ -32,7 +32,7 @@ export default function Playground(): JSX.Element { return ( diff --git a/docsite/static/aio.json b/docsite/static/aio.json index 05258fa9..908cffce 100644 --- a/docsite/static/aio.json +++ b/docsite/static/aio.json @@ -1 +1 @@ -{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"sourceDefaults":{"$ref":"#/definitions/SourceDefaults"},"clientDefaults":{"$ref":"#/definitions/ClientDefaults"},"sources":{"type":"array","items":{"$ref":"#/definitions/SourceAIOConfig"}},"clients":{"type":"array","items":{"$ref":"#/definitions/ClientAIOConfig"}},"webhooks":{"type":"array","items":{"$ref":"#/definitions/WebhookConfig"}},"port":{"type":"number","description":"Set the port the multi-scrobbler UI will be served from","default":9078,"examples":[9078]},"baseUrl":{"type":"string","description":"Set the Base URL the application should assume the UI is served from.\n\nThis will affect how default redirect URLs are generated (spotify, lastfm, deezer) and some logging messages.\n\nIt will NOT set the actual interface/IP that the application is listening on.\n\nThis can also be set using the BASE_URL environmental variable.","default":"http://localhost","examples":["http://localhost","http://192.168.0.101","https://ms.myDomain.tld"]},"logging":{"$ref":"#/definitions/LogOptions"},"disableWeb":{"type":"boolean","description":"Disable web server from running/listening on port.\n\nThis will also make any ingress sources (Plex, Jellyfin, Tautulli, etc...) unusable"},"debugMode":{"type":"boolean","description":"Enables ALL relevant logging and debug options for all sources/clients, when none are defined.\n\nThis is a convenience shortcut for enabling all output needed to troubleshoot an issue and does not need to be on for normal operation.\n\nIt can also be enabled with the environmental variable DEBUG_MODE=true","default":false,"examples":[false]},"cache":{"$ref":"#/definitions/CacheConfigOptions"},"transformers":{"type":"array","items":{"$ref":"#/definitions/TransformerCommonConfig"}}},"definitions":{"SourceDefaults":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"SourceDefaults"},"LogLevel":{"type":"string","enum":["silent","fatal","error","warn","info","log","verbose","debug"],"description":"Names of log levels that can be invoked on the logger\n\nFrom lowest to highest:\n\n* `debug`\n* `verbose`\n* `log`\n* `info`\n* `warn`\n* `error`\n* `fatal`\n* `silent` (will never output anything)\n\nWhen used in `LogOptions` specifies the **minimum** level the output should log at.","title":"LogLevel"},"FileLogOptions":{"type":"object","properties":{"timestamp":{"type":"string","enum":["unix","iso","auto"],"description":"For rolling log files\n\nWhen\n* value passed to rolling destination is a string (`path` from LogOptions is a string) and\n* `frequency` is defined\n\nThis determines the format of the datetime inserted into the log file name:\n\n* `unix` - unix epoch timestamp in milliseconds\n* `iso` - Full [ISO8601](https://en.wikipedia.org/wiki/ISO_8601) datetime IE '2024-03-07T20:11:34Z'\n* `auto`\n * When frequency is `daily` only inserts date IE YYYY-MM-DD\n * Otherwise inserts full ISO8601 datetime","default":"auto"},"size":{"type":["number","string"],"description":"The maximum size of a given rolling log file.\n\nCan be combined with frequency. Use k, m and g to express values in KB, MB or GB.\n\nNumerical values will be considered as MB.","default":"10MB"},"frequency":{"anyOf":[{"type":"string","enum":["daily"]},{"type":"string","enum":["hourly"]},{"type":"number"}],"description":"The amount of time a given rolling log file is used. Can be combined with size.\n\nUse `daily` or `hourly` to rotate file every day (or every hour). Existing file within the current day (or hour) will be re-used.\n\nNumerical values will be considered as a number of milliseconds. Using a numerical value will always create a new file upon startup.","default":"daily"},"path":{"anyOf":[{"type":"string"},{"$comment":"() => string"}],"description":"The path and filename to use for log files.\n\nIf using rolling files the filename will be appended with `.N` (a number) BEFORE the extension based on rolling status.\n\nMay also be specified using env LOG_PATH or a function that returns a string.\n\nIf path is relative the absolute path will be derived from `logBaseDir` (in `LoggerAppExtras`) which defaults to CWD","default":"./logs/app.log"},"level":{"anyOf":[{"$ref":"#/definitions/LogLevel"},{"type":"boolean","const":false}],"description":"Specify the minimum log level to output to rotating files. If `false` no log files will be created."}},"title":"FileLogOptions"},"ScrobbleThresholds":{"type":"object","properties":{"duration":{"type":["number","null"],"description":"The number of seconds a track has been listened to before it should be considered scrobbled.\n\nSet to null to disable.","default":240,"examples":[240]},"percent":{"type":["number","null"],"description":"The percentage (as an integer) of a track that should have been seen played before it should be scrobbled. Only used if the Source provides information about how long the track is.\n\nSet to null to disable.\n\nNOTE: This should be used with care when the Source is a \"polling\" type (has an 'interval' property). If the track is short and the interval is too high MS may ignore the track if percentage is high because it had not \"seen\" the track for long enough from first discovery, even if you have been playing the track for longer.","default":50,"examples":[50]}},"title":"ScrobbleThresholds"},"PlayTransformOptions":{"type":"object","properties":{"log":{"anyOf":[{"type":"boolean"},{"type":"string","enum":["all"]}]},"preCompare":{"$ref":"#/definitions/PlayTransformPartsConfig%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%3E"},"compare":{"type":"object","properties":{"candidate":{"$ref":"#/definitions/PlayTransformPartsConfig%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%3E"},"existing":{"$ref":"#/definitions/PlayTransformPartsConfig%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%3E"}}},"postCompare":{"$ref":"#/definitions/PlayTransformPartsConfig%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%3E"}},"title":"PlayTransformOptions"},"PlayTransformPartsConfig<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm)>":{"anyOf":[{"$ref":"#/definitions/PlayTransformPartsArray%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%2CMaybeStageTyped%3E"},{"$ref":"#/definitions/PlayTransformParts%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%2CMaybeStageTyped%3E"}],"description":"Represents the weakly-defined user config. May be an array of parts or one parts object","title":"PlayTransformPartsConfig<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm)>"},"PlayTransformPartsArray<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm),MaybeStageTyped>":{"type":"array","items":{"$ref":"#/definitions/PlayTransformParts%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%2CMaybeStageTyped%3E"},"title":"PlayTransformPartsArray<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm),MaybeStageTyped>"},"PlayTransformParts<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm),MaybeStageTyped>":{"anyOf":[{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"title":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"artists":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"albumArtists":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"album":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"duration":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"meta":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"onSuccess":{"$ref":"#/definitions/FlowControlTerm"},"onFailure":{"$ref":"#/definitions/FlowControlTerm"},"onSkip":{"$ref":"#/definitions/FlowControlTerm"},"failureReturnPartial":{"type":"boolean"},"type":{"$ref":"#/definitions/StageTypeMetadata"},"name":{"type":"string"},"stageHash":{"type":"string"},"score":{"type":"number"}},"required":["type"]},{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"title":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"artists":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"albumArtists":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"album":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"duration":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"meta":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"onSuccess":{"$ref":"#/definitions/FlowControlTerm"},"onFailure":{"$ref":"#/definitions/FlowControlTerm"},"onSkip":{"$ref":"#/definitions/FlowControlTerm"},"failureReturnPartial":{"type":"boolean"},"type":{"$ref":"#/definitions/StageTypeUser"},"name":{"type":"string"},"stageHash":{"type":"string"}},"required":["type"]},{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"title":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"artists":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"albumArtists":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"album":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"duration":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"meta":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"onSuccess":{"$ref":"#/definitions/FlowControlTerm"},"onFailure":{"$ref":"#/definitions/FlowControlTerm"},"onSkip":{"$ref":"#/definitions/FlowControlTerm"},"failureReturnPartial":{"type":"boolean"},"type":{"type":"string","enum":["native"]},"name":{"type":"string"},"stageHash":{"type":"string"}},"required":["type"]},{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"title":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"artists":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"albumArtists":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"album":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"duration":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"meta":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"onSuccess":{"$ref":"#/definitions/FlowControlTerm"},"onFailure":{"$ref":"#/definitions/FlowControlTerm"},"onSkip":{"$ref":"#/definitions/FlowControlTerm"},"failureReturnPartial":{"type":"boolean"},"name":{"type":"string"}}},{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"title":{},"artists":{},"albumArtists":{},"album":{},"duration":{},"meta":{},"onSuccess":{"$ref":"#/definitions/FlowControlTerm"},"onFailure":{"$ref":"#/definitions/FlowControlTerm"},"onSkip":{"$ref":"#/definitions/FlowControlTerm"},"failureReturnPartial":{"type":"boolean"},"type":{"type":"string"},"name":{"type":"string"},"stageHash":{"type":"string"}},"required":["type"]}],"title":"PlayTransformParts<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm),MaybeStageTyped>"},"WhenConditionsConfig":{"$ref":"#/definitions/WhenConditions%3Cstring%3E","title":"WhenConditionsConfig"},"WhenConditions":{"type":"array","items":{"$ref":"#/definitions/WhenParts%3Cstring%3E"},"title":"WhenConditions"},"WhenParts":{"$ref":"#/definitions/PlayTransformPartsAtomic%3Cstring%3E","title":"WhenParts"},"PlayTransformPartsAtomic":{"type":"object","properties":{"title":{"type":"string"},"artists":{"type":"string"},"albumArtists":{"type":"string"},"album":{"type":"string"},"duration":{"type":"string"},"meta":{"type":"string"}},"title":"PlayTransformPartsAtomic"},"Whennable":{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"}},"title":"Whennable"},"FlowControlTerm":{"type":"string","enum":["continue","stop"],"title":"FlowControlTerm"},"StageTypeMetadata":{"type":"string","enum":["spotify","musicbrainz","native"],"title":"StageTypeMetadata"},"SearchAndReplaceTerm":{"anyOf":[{"type":"string"},{"$ref":"#/definitions/ConditionalSearchAndReplaceTerm"}],"title":"SearchAndReplaceTerm"},"ConditionalSearchAndReplaceTerm":{"$ref":"#/definitions/ConditionalSearchAndReplaceRegExp","title":"ConditionalSearchAndReplaceTerm"},"ConditionalSearchAndReplaceRegExp":{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"search":{"anyOf":[{"type":"string"},{"type":"string","format":"regex"}],"description":"The search value to test for\n\nCan be a normal string (converted to a case-sensitive literal) or a valid regular expression as a string, or an actual RegExp object","examples":[["find this string","/some string*/ig"]]},"replace":{"type":"string","description":"The replacement string/value to use when search is found\n\nThis can be a literal string like `'replace with this`, an empty string to remove the search value (`''`), or a special regex value\n\nSee replacement here for more information: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace"},"test":{"$comment":"(obj: SearchAndReplaceRegExp) => boolean","type":"object","properties":{"namedArgs":{"type":"object","properties":{"obj":{"$ref":"#/definitions/SearchAndReplaceRegExp"}},"required":["obj"],"additionalProperties":false}},"description":"An optional function to execute before running this search-and-replace that decides if it should run at all"}},"required":["replace","search"],"title":"ConditionalSearchAndReplaceRegExp"},"SearchAndReplaceRegExp":{"type":"object","properties":{"search":{"anyOf":[{"type":"string"},{"type":"string","format":"regex"}],"description":"The search value to test for\n\nCan be a normal string (converted to a case-sensitive literal) or a valid regular expression as a string, or an actual RegExp object","examples":[["find this string","/some string*/ig"]]},"replace":{"type":"string","description":"The replacement string/value to use when search is found\n\nThis can be a literal string like `'replace with this`, an empty string to remove the search value (`''`), or a special regex value\n\nSee replacement here for more information: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace"},"test":{"$comment":"(obj: SearchAndReplaceRegExp) => boolean","type":"object","properties":{"namedArgs":{"type":"object","properties":{"obj":{"$ref":"#/definitions/SearchAndReplaceRegExp"}},"required":["obj"],"additionalProperties":false}},"description":"An optional function to execute before running this search-and-replace that decides if it should run at all"}},"required":["search","replace"],"title":"SearchAndReplaceRegExp"},"ExternalMetadataTerm":{"anyOf":[{"type":"boolean"},{"not":{}},{"$ref":"#/definitions/Whennable"}],"title":"ExternalMetadataTerm"},"StageTypeUser":{"type":"string","enum":["user"],"title":"StageTypeUser"},"ClientDefaults":{"type":"object","properties":{"refreshEnabled":{"type":"boolean","description":"Try to get fresh scrobble history from client when tracks to be scrobbled are newer than the last scrobble found in client history","default":true,"examples":[true]},"refreshStaleAfter":{"type":"number","description":"Refresh scrobbled plays from upstream service if last refresh was at least X seconds ago\n\n**In most case this setting does NOT need to be changed.** The default value is sufficient for the majority of use-cases. Increasing this setting may increase upstream service load and slow down scrobbles.\n\nThis setting should only be changed in specific scenarios where MS is handling multiple \"relaying\" client-services (IE lfm -> lz -> lfm) and there is the potential for a client to be out of sync after more than a few seconds.","examples":[60],"default":60},"refreshMinInterval":{"type":"number","description":"Minimum time (milliseconds) required to pass before upstream scrobbles can be refreshed.\n\n**In most case this setting does NOT need to be changed.** This will always be equal to or smaller than `refreshStaleAfter`.","default":5000,"examples":[5000]},"refreshInitialCount":{"type":"number","description":"The number of tracks to retrieve on initial refresh (related to scrobbleBacklogCount). If not specified this is the maximum supported by the client in 1 API call."},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"checkExistingScrobbles":{"type":"boolean","description":"Check client for an existing scrobble at the same recorded time as the \"new\" track to be scrobbled. If an existing scrobble is found this track is not track scrobbled.","default":true,"examples":[true]},"verbose":{"type":"object","properties":{"match":{"$ref":"#/definitions/MatchLoggingOptions"}},"description":"Options used for increasing verbosity of logging in MS (used for debugging)"},"deadLetterRetries":{"type":"number","description":"Number of times MS should automatically retry scrobbles in dead letter queue","default":1,"examples":[1]},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"ClientDefaults"},"MatchLoggingOptions":{"type":"object","properties":{"onNoMatch":{"type":"boolean","description":"Log to DEBUG when a new track does NOT match an existing scrobble","default":false,"examples":[false]},"onMatch":{"type":"boolean","description":"Log to DEBUG when a new track DOES match an existing scrobble","default":false,"examples":[false]},"confidenceBreakdown":{"type":"boolean","description":"Include confidence breakdowns in track match logging, if applicable","default":false,"examples":[false]}},"description":"Scrobble matching (between new source track and existing client scrobbles) logging options. Used for debugging.","title":"MatchLoggingOptions"},"SourceAIOConfig":{"anyOf":[{"$ref":"#/definitions/SpotifySourceAIOConfig"},{"$ref":"#/definitions/PlexApiSourceAIOConfig"},{"$ref":"#/definitions/DeezerSourceAIOConfig"},{"$ref":"#/definitions/DeezerInternalAIOConfig"},{"$ref":"#/definitions/ListenbrainzEndpointSourceAIOConfig"},{"$ref":"#/definitions/LastFMEndpointSourceAIOConfig"},{"$ref":"#/definitions/SubsonicSourceAIOConfig"},{"$ref":"#/definitions/JellyApiSourceAIOConfig"},{"$ref":"#/definitions/LastFmSouceAIOConfig"},{"$ref":"#/definitions/LibrefmSouceAIOConfig"},{"$ref":"#/definitions/YTMusicSourceAIOConfig"},{"$ref":"#/definitions/MPRISSourceAIOConfig"},{"$ref":"#/definitions/MopidySourceAIOConfig"},{"$ref":"#/definitions/ListenBrainzSourceAIOConfig"},{"$ref":"#/definitions/JRiverSourceAIOConfig"},{"$ref":"#/definitions/KodiSourceAIOConfig"},{"$ref":"#/definitions/WebScrobblerSourceAIOConfig"},{"$ref":"#/definitions/ChromecastSourceAIOConfig"},{"$ref":"#/definitions/MalojaSourceAIOConfig"},{"$ref":"#/definitions/MusikcubeSourceAIOConfig"},{"$ref":"#/definitions/MusicCastSourceAIOConfig"},{"$ref":"#/definitions/MPDSourceAIOConfig"},{"$ref":"#/definitions/VLCSourceAIOConfig"},{"$ref":"#/definitions/IcecastSourceAIOConfig"},{"$ref":"#/definitions/AzuracastSourceAIOConfig"},{"$ref":"#/definitions/KoitoSourceAIOConfig"},{"$ref":"#/definitions/TealSourceAIOConfig"},{"$ref":"#/definitions/RockskySourceAIOConfig"}],"title":"SourceAIOConfig"},"SpotifySourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/SpotifySourceData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"type":{"type":"string","enum":["spotify"]}},"required":["data","type"],"title":"SpotifySourceAIOConfig"},"SpotifySourceData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)\n\nIt is unlikely you should need to change this unless you scrobble many very short tracks often\n\nReading:\n* https://developer.spotify.com/documentation/web-api/guides/rate-limits/\n* https://medium.com/mendix/limiting-your-amount-of-calls-in-mendix-most-of-the-time-rest-835dde55b10e\n * Rate limit may ~180 req/min\n* https://community.spotify.com/t5/Spotify-for-Developers/Web-API-ratelimit/m-p/5503150/highlight/true#M7930\n * Informally indicated as 20 req/sec? Probably for burstiness","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"clientId":{"type":"string","description":"spotify client id","examples":["787c921a2a2ab42320831aba0c8f2fc2"]},"clientSecret":{"type":"string","description":"spotify client secret","examples":["ec42e09d5ae0ee0f0816ca151008412a"]},"redirectUri":{"type":"string","description":"spotify redirect URI -- required only if not the default shown here. URI must end in \"callback\"","default":"http://localhost:9078/callback","examples":["http://localhost:9078/callback"]}},"required":["clientId","clientSecret"],"title":"SpotifySourceData"},"CommonSourceOptions":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"CommonSourceOptions"},"PlexApiSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/PlexApiData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/PlexApiOptions"},"type":{"type":"string","enum":["plex"]}},"required":["data","type"],"title":"PlexApiSourceAIOConfig"},"PlexApiData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"token":{"type":"string"},"url":{"type":"string","description":"http(s)://HOST:PORT of the Plex server to connect to"},"usersAllow":{"anyOf":[{"type":"string"},{"type":"boolean","enum":[true]},{"type":"array","items":{"type":"string"}}],"description":"Only scrobble for specific users (case-insensitive)\n\nIf `true` MS will scrobble activity from all users"},"usersBlock":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Do not scrobble for these users (case-insensitive)"},"devicesAllow":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Only scrobble if device or application name contains strings from this list (case-insensitive)"},"devicesBlock":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Do not scrobble if device or application name contains strings from this list (case-insensitive)"},"librariesAllow":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Only scrobble if library name contains string from this list (case-insensitive)"},"librariesBlock":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Do not scrobble if library name contains strings from this list (case-insensitive)"}},"required":["url"],"title":"PlexApiData"},"PlexApiOptions":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"},"ignoreInvalidCert":{"type":"boolean","description":"Ignore invalid cert errors when connecting to Plex\n\nUseful for Plex servers using \"Required\" Secure Connections with self-signed certificates\n\nDo not enable unless you know you need this.","default":false}},"title":"PlexApiOptions"},"DeezerSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/DeezerData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"type":{"type":"string","enum":["deezer"]}},"required":["data","type"],"title":"DeezerSourceAIOConfig"},"DeezerData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"clientId":{"type":"string","description":"deezer client id","examples":["a89cba1569901a0671d5a9875fed4be1"]},"clientSecret":{"type":"string","description":"deezer client secret","examples":["ec42e09d5ae0ee0f0816ca151008412a"]},"redirectUri":{"type":"string","description":"deezer redirect URI -- required only if not the default shown here. URI must end in \"callback\"","default":"http://localhost:9078/deezer/callback","examples":["http://localhost:9078/deezer/callback"]}},"required":["clientId","clientSecret"],"title":"DeezerData"},"DeezerInternalAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/DeezerInternalData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/DeezerInternalSourceOptions"},"type":{"type":"string","enum":["deezer"]}},"required":["data","type"],"title":"DeezerInternalAIOConfig"},"DeezerInternalData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"arl":{"type":"string","description":"ARL retrieved from Deezer response header"},"userAgent":{"type":"string","description":"User agent","default":"Mozilla/5.0 (X11; Linux i686; rv:135.0) Gecko/20100101 Firefox/135.0"}},"required":["arl"],"title":"DeezerInternalData"},"DeezerInternalSourceOptions":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"},"fuzzyDiscoveryIgnore":{"anyOf":[{"type":"boolean"},{"type":"string","enum":["aggressive"]}]}},"title":"DeezerInternalSourceOptions"},"ListenbrainzEndpointSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/ListenbrainzEndpointData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"type":{"type":"string","enum":["endpointlz"]}},"required":["type"],"title":"ListenbrainzEndpointSourceAIOConfig"},"ListenbrainzEndpointData":{"type":"object","properties":{"slug":{"type":["string","null"],"description":"The URL ending that should be used to identify scrobbles for this source\n\nIf you are using multiple Listenbrainz endpoint sources (scrobbles for many users) you can use a slug to match Sources with individual users/origins\n\nExample:\n\n* slug: 'usera' => API URL: http://localhost:9078/api/listenbrainz/usera\n* slug: 'originb' => API URL: http://localhost:9078/api/listenbrainz/originb\n\nIf no slug is found from an extension's incoming webhook event the first Listenbrainz source without a slug will be used"},"token":{"type":["string","null"],"description":"If an LZ submission request contains this token in the Authorization Header it will be used to match the submission with this Source\n\nSee: https://listenbrainz.readthedocs.io/en/latest/users/api/index.html#add-the-user-token-to-your-requests"}},"title":"ListenbrainzEndpointData"},"LastFMEndpointSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/LastFMEndpointData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"type":{"type":"string","enum":["endpointlfm"]}},"required":["type"],"title":"LastFMEndpointSourceAIOConfig"},"LastFMEndpointData":{"type":"object","properties":{"slug":{"type":["string","null"],"description":"The URL ending that should be used to identify scrobbles for this source\n\nIf you are using multiple Last.fm endpoint sources (scrobbles for many users) you can use a slug to match Sources with individual users/origins\n\nExample:\n\n* slug: 'usera' => API URL: http://localhost:9078/api/lastfm/usera\n* slug: 'originb' => API URL: http://localhost:9078/api/lastfm/originb\n\nIf no slug is found from an extension's incoming webhook event the first Last.fm source without a slug will be used"}},"title":"LastFMEndpointData"},"SubsonicSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/SubsonicData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"type":{"type":"string","enum":["subsonic"]}},"required":["data","type"],"title":"SubsonicSourceAIOConfig"},"SubsonicData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"url":{"type":"string","description":"URL of the subsonic media server to query","examples":["http://airsonic.local"]},"user":{"type":"string","description":"Username to login to the server with","examples":[["MyUser"]]},"password":{"type":"string","description":"Password for the user to login to the server with","examples":["MyPassword"]},"ignoreTlsErrors":{"type":"boolean","description":"If your subsonic server is using self-signed certs you may need to disable TLS errors in order to get a connection\n\nWARNING: This should be used with caution as your traffic may not be encrypted.","default":false},"legacyAuthentication":{"type":"boolean","description":"Older Subsonic versions, and some badly implemented servers (Nextcloud), use legacy authentication which sends your password in CLEAR TEXT. This is less secure than the newer, recommended hashing authentication method but in some cases it is needed. See \"Authentication\" section here => https://www.subsonic.org/pages/api.jsp\n\nIf this option is not specified it will be turned on if the subsonic server responds with error code 41 \"Token authentication not supported for LDAP users.\" -- See Error Handling section => https://www.subsonic.org/pages/api.jsp","default":false},"usersAllow":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Only scrobble for specific users (case-insensitive)\n\nIf undefined or an empty string/list MS will scrobble activity from all users"}},"required":["url","user","password"],"title":"SubsonicData"},"JellyApiSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/JellyApiData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/JellyApiOptions"},"type":{"type":"string","enum":["jellyfin"]}},"required":["data","options","type"],"title":"JellyApiSourceAIOConfig"},"JellyApiData":{"type":"object","properties":{"url":{"type":"string","description":"HOST:PORT of the Jellyfin server to connect to"},"user":{"type":"string","description":"The username of the user to authenticate for or track scrobbles for"},"password":{"type":"string","description":"Password of the username to authenticate for\n\nRequired if `apiKey` is not provided."},"apiKey":{"type":"string","description":"API Key to authenticate with.\n\nRequired if `password` is not provided."},"usersAllow":{"anyOf":[{"type":"string"},{"type":"boolean","enum":[true]},{"type":"array","items":{"type":"string"}}],"description":"Only scrobble for specific users (case-insensitive)\n\nIf `true` MS will scrobble activity from all users"},"usersBlock":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Do not scrobble for these users (case-insensitive)"},"devicesAllow":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Only scrobble if device or application name contains strings from this list (case-insensitive)"},"devicesBlock":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Do not scrobble if device or application name contains strings from this list (case-insensitive)"},"librariesAllow":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Only scrobble if library name contains string from this list (case-insensitive)"},"librariesBlock":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Do not scrobble if library name contains strings from this list (case-insensitive)"},"additionalAllowedLibraryTypes":{"type":"array","items":{},"description":"Allow MS to scrobble audio media in libraries classified other than 'music'\n\n`librariesAllow` will achieve the same result as this but this is more convenient if you do not want to explicitly list every library name or are only using `librariesBlock`"},"allowUnknown":{"type":"boolean","description":"Force media with a type of \"Unknown\" to be counted as Audio","default":false},"frontendUrlOverride":{"type":"string","description":"HOST:PORT of the Jellyfin server that your browser will be able to access from the frontend (and thus load images and links from)\nIf unspecified it will use the normal server HOST and PORT from the `url`\nNecessary if you are using a reverse proxy or other network configuration that prevents the frontend from accessing the server directly\n\nENV: JELLYFIN_FRONTEND_URL_OVERRIDE"}},"required":["url","user"],"title":"JellyApiData"},"JellyApiOptions":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"JellyApiOptions"},"LastFmSouceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/LastFmSourceData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"configureAs":{"type":"string","enum":["source"],"description":"When used in `lastfm.config` this tells multi-scrobbler whether to use this data to configure a source or client.","default":"source","examples":["source"]},"type":{"type":"string","enum":["lastfm"]}},"required":["data","type"],"title":"LastFmSouceAIOConfig"},"LastFmSourceData":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"apiKey":{"type":"string","description":"API Key generated from Last.fm/Libre.fm account","examples":["787c921a2a2ab42320831aba0c8f2fc2"]},"secret":{"type":"string","description":"Secret generated from Last.fm/Libre.fm account","examples":["ec42e09d5ae0ee0f0816ca151008412a"]},"session":{"type":"string","description":"Optional session id returned from a completed auth flow"},"redirectUri":{"type":"string","description":"Optional URI to use for callback. Specify this if callback should be different than the default. MUST have \"lastfm/callback\" in the URL somewhere.","default":"http://localhost:9078/lastfm/callback","examples":["http://localhost:9078/lastfm/callback"]},"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"}},"required":["apiKey","secret"],"title":"LastFmSourceData"},"LibrefmSouceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/LibrefmData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"configureAs":{"type":"string","enum":["source"],"description":"When used in `librefm.config` this tells multi-scrobbler whether to use this data to configure a source or client.","default":"source","examples":["source"]},"type":{"type":"string","enum":["librefm"]}},"required":["data","type"],"title":"LibrefmSouceAIOConfig"},"LibrefmData":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"apiKey":{"type":"string","description":"Optional Secret for Libre.fm account\n\nThis can be anything, or it will be generated by multi-scrobbler","examples":["anyValue"]},"secret":{"type":"string","description":"Optional Secret for Libre.fm account\n\nThis can be anything, or it will be generated by multi-scrobbler","examples":["anyValue"]},"session":{"type":"string","description":"Optional session id returned from a completed auth flow"},"path":{"type":"string"},"urlBase":{"type":"string","description":"(Optional) The host and path prefix for your Libre.fm instance","default":"https://libre.fm/2.0/"},"redirectUri":{"type":"string","description":"Optional URI to use for callback. Specify this if callback should be different than the default. MUST have \"librefm/callback\" in the URL somewhere.","default":"http://localhost:9078/librefm/callback","examples":["http://localhost:9078/librefm/callback"]}},"title":"LibrefmData"},"YTMusicSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/YTMusicData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"type":"object","properties":{"logAuth":{"type":"boolean","description":"When true MS will log to DEBUG all of the credentials data it receives from YTM"},"logDiff":{"type":"boolean","description":"Always log history diff\n\nBy default MS will log to `WARN` if history diff is inconsistent but does not log if diff is expected (on new tracks found)\nSet this to `true` to ALWAYS log diff on new tracks. Expected diffs will log to `DEBUG` and inconsistent diffs will continue to log to `WARN`","default":false},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}}},"type":{"type":"string","enum":["ytmusic"]}},"required":["type"],"title":"YTMusicSourceAIOConfig"},"YTMusicData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"cookie":{"type":"string","description":"The cookie retrieved from the Request Headers of music.youtube.com after logging in.\n\nSee https://ytmusicapi.readthedocs.io/en/stable/setup/browser.html#copy-authentication-headers for how to retrieve this value.","examples":["VISITOR_INFO1_LIVE=jMp2xA1Xz2_PbVc; __Secure-3PAPISID=3AxsXpy0M/AkISpjek; ..."]},"clientId":{"type":"string","description":"Google Cloud Console project OAuth Client ID\n\nGenerated from a custom OAuth Client, see docs"},"clientSecret":{"type":"string","description":"Google Cloud Console project OAuth Client Secret\n\nGenerated from a custom OAuth Client, see docs"},"redirectUri":{"type":"string","description":"Google Cloud Console project OAuth Client Authorized redirect URI\n\nGenerated from a custom OAuth Client, see docs. multi-scrobbler will generate a default based on BASE_URL.\nOnly specify this if the default does not work for you."},"innertubeOptions":{"$ref":"#/definitions/InnertubeOptions","description":"Additional options for authorization and tailoring YTM client"}},"title":"YTMusicData"},"InnertubeOptions":{"type":"object","properties":{"po_token":{"type":"string","description":"Proof of Origin token\n\nMay be required if YTM starts returning 403"},"visitor_data":{"type":"string","description":"Visitor ID value found in VISITOR_INFO1_LIVE or visitorData cookie\n\nMay be required if YTM starts returning 403"},"account_index":{"type":"number","description":"If account login results in being able to choose multiple account, use a zero-based index to choose which one to monitor","examples":[0,1]},"location":{"type":"string"},"lang":{"type":"string"},"generate_session_locally":{"type":"boolean"},"device_category":{"type":"string"},"client_type":{"type":"string"},"timezone":{"type":"string"}},"title":"InnertubeOptions"},"MPRISSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/MPRISData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"type":{"type":"string","enum":["mpris"]}},"required":["data","type"],"title":"MPRISSourceAIOConfig"},"MPRISData":{"type":"object","properties":{"blacklist":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"DO NOT scrobble from any players that START WITH these values, case-insensitive","examples":[["spotify","vlc"]]},"whitelist":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"ONLY from any players that START WITH these values, case-insensitive\n\nIf whitelist is present then blacklist is ignored","examples":[["spotify","vlc"]]}},"title":"MPRISData"},"MopidySourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/MopidyData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"type":{"type":"string","enum":["mopidy"]}},"required":["data","type"],"title":"MopidySourceAIOConfig"},"MopidyData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"url":{"type":"string","description":"URL of the Mopidy HTTP server to connect to\n\nYou MUST have Mopidy-HTTP extension enabled: https://mopidy.com/ext/http\n\nmulti-scrobbler connects to the WebSocket endpoint that ultimately looks like this => `ws://localhost:6680/mopidy/ws/`\n\nThe URL you provide here will have all parts not explicitly defined filled in for you so if these are not the default you must define them.\n\nParts => [default value]\n\n* Protocol => `ws://`\n* Hostname => `localhost`\n* Port => `6680`\n* Path => `/mopidy/ws/`","examples":["ws://localhost:6680/mopidy/ws/"],"default":"ws://localhost:6680/mopidy/ws/"},"uriBlacklist":{"type":"array","items":{"type":"string"},"description":"Do not scrobble tracks whose URI STARTS WITH any of these strings, case-insensitive\n\nEX: Don't scrobble tracks from soundcloud by adding 'soundcloud' to this list.\n\nList is ignored if uriWhitelist is used."},"uriWhitelist":{"type":"array","items":{"type":"string"},"description":"Only scrobble tracks whose URI STARTS WITH any of these strings, case-insensitive\n\nEX: Only scrobble tracks from soundcloud by adding 'soundcloud' to this list."},"albumBlacklist":{"type":"array","items":{"type":"string"},"description":"Remove album data that matches any case-insensitive string from this list when scrobbling,\n\nFor certain sources (Soundcloud) Mopidy does not have all track info (Album) and will instead use \"Soundcloud\" as the Album name. You can prevent multi-scrobbler from using this bad Album data by adding the fake name to this list. Multi-scrobbler will still scrobble the track, just without the bad data.","examples":[["Soundcloud","Mixcloud"]],"default":["Soundcloud"]}},"title":"MopidyData"},"ListenBrainzSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/ListenBrainzSourceData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"configureAs":{"type":"string","enum":["source"],"description":"When used in `listenbrainz.config` this tells multi-scrobbler whether to use this data to configure a source or client.","default":"source","examples":["source"]},"type":{"type":"string","enum":["listenbrainz"]}},"required":["data","type"],"title":"ListenBrainzSourceAIOConfig"},"ListenBrainzSourceData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"url":{"type":"string","description":"URL for the ListenBrainz server, if not using the default","examples":["https://api.listenbrainz.org/"],"default":"https://api.listenbrainz.org/"},"token":{"type":"string","description":"User token for the user to scrobble for","examples":["6794186bf-1157-4de6-80e5-uvb411f3ea2b"]},"username":{"type":"string","description":"Username of the user to scrobble for"}},"required":["token","username"],"title":"ListenBrainzSourceData"},"JRiverSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/JRiverData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"type":{"type":"string","enum":["jriver"]}},"required":["data","type"],"title":"JRiverSourceAIOConfig"},"JRiverData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"url":{"type":"string","description":"URL of the JRiver HTTP server to connect to\n\nmulti-scrobbler connects to the Web Service Interface endpoint that ultimately looks like this => `http://yourDomain:52199/MCWS/v1/`\n\nThe URL you provide here will have all parts not explicitly defined filled in for you so if these are not the default you must define them.\n\nParts => [default value]\n\n* Protocol => `http://`\n* Hostname => `localhost`\n* Port => `52199`\n* Path => `/MCWS/v1/`","examples":["http://localhost:52199/MCWS/v1/"],"default":"http://localhost:52199/MCWS/v1/"},"username":{"type":"string","description":"If you have enabled authentication, the username you set"},"password":{"type":"string","description":"If you have enabled authentication, the password you set"}},"required":["url"],"title":"JRiverData"},"KodiSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/KodiData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"type":{"type":"string","enum":["kodi"]}},"required":["data","type"],"title":"KodiSourceAIOConfig"},"KodiData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"url":{"type":"string","description":"URL of the Kodi HTTP server to connect to\n\nmulti-scrobbler connects to the Web Service Interface endpoint that ultimately looks like this => `http://yourDomain:8080/jsonrpc`\n\nThe URL you provide here will have all parts not explicitly defined filled in for you so if these are not the default you must define them.\n\nParts => [default value]\n\n* Protocol => `http://`\n* Hostname => `localhost`\n* Port => `8080`\n* Path => `/jsonrpc`","examples":["http://localhost:8080/jsonrpc"],"default":"http://localhost:8080/jsonrpc"},"username":{"type":"string","description":"The username set for Remote Control via Web Sever"},"password":{"type":"string","description":"The password set for Remote Control via Web Sever"}},"required":["url","username","password"],"title":"KodiData"},"WebScrobblerSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/WebScrobblerData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"type":{"type":"string","enum":["webscrobbler"]}},"required":["type"],"title":"WebScrobblerSourceAIOConfig"},"WebScrobblerData":{"type":"object","properties":{"slug":{"type":["string","null"],"description":"The URL ending that should be used to identify scrobbles for this source\n\nIn WebScrobbler's Webhook you must set an 'API URL'. All MS WebScrobbler sources must start like:\n\nhttp://localhost:9078/api/webscrobbler\n\nIf you are using multiple WebScrobbler sources (scrobbles for many users) you must use a slug to match Sources with each users extension.\n\nExample:\n\n* slug: 'usera' => API URL: http://localhost:9078/api/webscrobbler/usera\n* slug: 'userb' => API URL: http://localhost:9078/api/webscrobbler/userb\n\nIf no slug is found from an extension's incoming webhook event the first WebScrobbler source without a slug will be used"},"blacklist":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Block scrobbling from specific WebScrobbler Connectors","examples":[["youtube"]]},"whitelist":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Only allow scrobbling from specific WebScrobbler Connectors","examples":[["mixcloud","soundcloud","bandcamp"]]}},"title":"WebScrobblerData"},"ChromecastSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/ChromecastData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"type":{"type":"string","enum":["chromecast"]}},"required":["data","type"],"title":"ChromecastSourceAIOConfig"},"ChromecastData":{"type":"object","properties":{"blacklistDevices":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"DO NOT scrobble from any cast devices that START WITH these values, case-insensitive\n\nUseful when used with auto discovery","examples":[["home-mini","family-tv"]]},"whitelistDevices":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"ONLY scrobble from any cast device that START WITH these values, case-insensitive\n\nIf whitelist is present then blacklist is ignored\n\nUseful when used with auto discovery","examples":[["home-mini","family-tv"]]},"blacklistApps":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"DO NOT scrobble from any application that START WITH these values, case-insensitive","examples":[["spotify","pandora"]]},"whitelistApps":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"ONLY scrobble from any application that START WITH these values, case-insensitive\n\nIf whitelist is present then blacklist is ignored","examples":[["spotify","pandora"]]},"useAvahi":{"type":"boolean","description":"Try to use Avahi and avahi-browse to resolve mDNS devices instead of native mDNS querying\n\nUseful for docker (alpine) container where mDNS resolution is not yet supported. Avahi socket must be exposed to the container and avahi-tools must be installed.","default":false},"useAutoDiscovery":{"type":"boolean","description":"Use mDNS to discovery Google Cast devices on your next automatically?\n\nIf not explicitly set then it is TRUE if `devices` is not set"},"devices":{"type":"array","items":{"$ref":"#/definitions/ChromecastDeviceInfo"},"description":"A list of Google Cast devices to monitor\n\nIf this is used then `useAutoDiscovery` is set to FALSE, if not explicitly set"},"allowUnknownMedia":{"anyOf":[{"type":"boolean"},{"type":"array","items":{"type":"string"}}],"description":"Chromecast Apps report a \"media type\" in the status info returned for whatever is currently playing\n\n* If set to TRUE then Music AND Generic/Unknown media will be tracked for ALL APPS\n* If set to FALSE then only media explicitly typed as Music will be tracked for ALL APPS\n* If set to a list then only Apps whose name contain one of these values, case-insensitive, will have Music AND Generic/Unknown tracked\n\nSee https://developers.google.com/cast/docs/media/messages#MediaInformation \"metadata\" property","default":false},"forceMediaRecognitionOn":{"type":"array","items":{"type":"string"},"description":"Media provided by any App whose name is listed here will ALWAYS be tracked, regardless of the \"media type\" reported\n\nApps will be recognized if they CONTAIN any of these values, case-insensitive"}},"title":"ChromecastData"},"ChromecastDeviceInfo":{"type":"object","properties":{"name":{"type":"string","description":"A friendly name to identify this device","examples":["MySmartTV"]},"address":{"type":"string","description":"The IP address of the device","examples":["192.168.0.115"]}},"required":["name","address"],"title":"ChromecastDeviceInfo"},"MalojaSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/MalojaSourceData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"configureAs":{"type":"string","enum":["source"],"description":"When used in `maloja.config` this tells multi-scrobbler whether to use this data to configure a source or client.","default":"source","examples":["source"]},"type":{"type":"string","enum":["maloja"]}},"required":["data","type"],"title":"MalojaSourceAIOConfig"},"MalojaSourceData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"url":{"type":"string","description":"URL for maloja server","examples":["http://localhost:42010"]},"apiKey":{"type":"string","description":"API Key for Maloja server","examples":["myApiKey"]}},"required":["apiKey","url"],"title":"MalojaSourceData"},"MusikcubeSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/MusikcubeData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"type":{"type":"string","enum":["musikcube"]}},"required":["data","type"],"title":"MusikcubeSourceAIOConfig"},"MusikcubeData":{"type":"object","properties":{"url":{"type":"string","description":"URL of the Musikcube Websocket (Metadata) server to connect to\n\nYou MUST have enabled 'metadata' server and set a password: https://github.com/clangen/musikcube/wiki/remote-api-documentation\n * musikcube -> settings -> server setup\n\nThe URL you provide here will have all parts not explicitly defined filled in for you so if these are not the default you must define them.\n\nParts => [default value]\n\n* Protocol => `ws://`\n* Hostname => `localhost`\n* Port => `7905`","examples":["ws://localhost:7905"],"default":"ws://localhost:7905"},"password":{"type":"string","description":"Password set in Musikcube https://github.com/clangen/musikcube/wiki/remote-api-documentation\n\n* musikcube -> settings -> server setup -> password"},"device_id":{"type":"string"}},"required":["password"],"title":"MusikcubeData"},"MusicCastSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/MusicCastData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"type":{"type":"string","enum":["musiccast"]}},"required":["data","type"],"title":"MusicCastSourceAIOConfig"},"MusicCastData":{"type":"object","properties":{"url":{"type":"string","description":"The host or URL of the YamahaExtendedControl endpoint to use","examples":[["192.168.0.101","http://192.168.0.101/YamahaExtendedControl"]]}},"required":["url"],"title":"MusicCastData"},"MPDSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/MPDData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/MPDSourceOptions"},"type":{"type":"string","enum":["mpd"]}},"required":["data","options","type"],"title":"MPDSourceAIOConfig"},"MPDData":{"type":"object","properties":{"url":{"type":"string","description":"URL:PORT of the MPD server to connect to\n\nTo use this you must have TCP connections enabled for your MPD server https://mpd.readthedocs.io/en/stable/user.html#client-connections","examples":["localhost:6600"],"default":"localhost:6600"},"path":{"type":"string","description":"If using socket specify the path instead of url.\n\ntrailing `~` is replaced by your home directory"},"password":{"type":"string","description":"Password for the server, if set https://mpd.readthedocs.io/en/stable/user.html#permissions-and-passwords"}},"title":"MPDData"},"MPDSourceOptions":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"MPDSourceOptions"},"VLCSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/VLCData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/VLCSourceOptions"},"type":{"type":"string","enum":["vlc"]}},"required":["data","type"],"title":"VLCSourceAIOConfig"},"VLCData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"url":{"type":"string","description":"URL:PORT of the VLC server to connect to\n\nTo use this you must have the Web (http) interface module enabled and a password set https://foxxmd.github.io/multi-scrobbler/docs/configuration#vlc","examples":["localhost:8080"],"default":"localhost:8080"},"password":{"type":"string","description":"Password for the server"}},"required":["password"],"title":"VLCData"},"VLCSourceOptions":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"},"filenamePatterns":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"A list of regular expressions to use to extract metadata (title, album, artist) from a filename\n\nUsed when VLC reports only the filename for the current audio track"},"logFilenamePatterns":{"type":"boolean","description":"Log to DEBUG when a filename-only track is matched or not matched by filenamePatterns","default":false},"dumpVlcMetadata":{"type":"boolean","description":"Dump all the metadata VLC reports for an audio track to DEBUG.\n\nUse this if reporting an issue with VLC not correctly capturing metadata for a track.","default":false}},"title":"VLCSourceOptions"},"IcecastSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/IcecastData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/IcecastSourceOptions"},"type":{"type":"string","enum":["icecast"]}},"required":["data","type"],"title":"IcecastSourceAIOConfig"},"IcecastData":{"type":"object","properties":{"sources":{"type":"array","items":{"$ref":"#/definitions/IcecastSource"}},"icestatsEndpoint":{"type":"string"},"statsEndpoint":{"type":"string"},"nextsongsEndpoint":{"type":"string"},"sevenhtmlEndpoint":{"type":"string"},"icyMetaInt":{"type":"number"},"url":{"type":"string","description":"The Icecast stream URL"}},"required":["url"],"title":"IcecastData"},"IcecastSource":{"type":"string","enum":["icy","ogg","icestats","stats","sevenhtml","nextsongs"],"title":"IcecastSource"},"IcecastSourceOptions":{"type":"object","properties":{"systemScrobble":{"type":"boolean","description":"For Sources that support manual listening, should MS default to scrobbling when no user interaction has occurred?\n\nIf not specified MS will use a Source's specific behavior, see Source's documentation."},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"IcecastSourceOptions"},"AzuracastSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/AzuracastData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"type":{"type":"string","enum":["azuracast"]}},"required":["data","type"],"title":"AzuracastSourceAIOConfig"},"AzuracastData":{"type":"object","properties":{"url":{"type":"string","description":"Base URL of the Azuracast instance\n\nThis does NOT include the station. If a station is included it will be ignored. Use `station` field to specify station, if necessary","examples":["https://radio.mydomain.tld","http://localhost:80"]},"station":{"type":"string","description":"The specific station to monitor\n\nScrobbling will only occur if any of the monitor conditions are met AND the station is ONLINE.\n\nTo monitor multiple stations create a Source for each station.","examples":["my-station-1"]},"monitorWhenListeners":{"type":["boolean","number"],"description":"Only activate scrobble monitoring if station\n\n* `true` => has any current listeners\n* `number` => has EQUAL TO or MORE THAN X number of listeners"},"monitorWhenLive":{"type":"boolean","description":"Only activate scrobble monitoring if station has a live DJ/Streamer","default":true},"apiKey":{"type":"string","description":"API Key used to access data about private streams\n\nhttps://www.azuracast.com/docs/developers/apis/#api-authentication"}},"required":["url","station"],"title":"AzuracastData"},"KoitoSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/KoitoSourceData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"configureAs":{"type":"string","enum":["source"],"description":"When used in `koito.config` this tells multi-scrobbler whether to use this data to configure a source or client.","default":"source","examples":["source"]},"type":{"type":"string","enum":["koito"]}},"required":["data","type"],"title":"KoitoSourceAIOConfig"},"KoitoSourceData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"url":{"type":"string","description":"URL for the Koito server","examples":["http://192.168.0.100:4110"]},"token":{"type":"string","description":"User token for the user to scrobble for","examples":["pM195xPV98CDpk0QW47FIIOR8AKATAX5DblBF-Jq0t1MbbKL"]},"username":{"type":"string","description":"Username of the user to scrobble for"}},"required":["token","url","username"],"title":"KoitoSourceData"},"TealSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/TealSourceData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/TealSourceOptions"},"configureAs":{"type":"string","enum":["source"],"description":"Should always be `souce` when using Tealfm as a Source","default":"source","examples":["source"]},"type":{"type":"string","enum":["tealfm"]}},"required":["data","type"],"title":"TealSourceAIOConfig"},"TealSourceData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"baseUri":{"type":"string","description":"The base URI of the Multi-Scrobbler to use for ATProto OAuth\n\nOnly include this if you want to use OAuth. The URI must be a non-IP/non-local domain using https: protocol."},"identifier":{"type":"string","description":"Identify the account to login as\n\n* For **App Password** Auth - your email\n* For **Oauth** - your handle minus the @"},"appPassword":{"type":"string","description":"The [App Password](https://atproto.com/specs/xrpc#app-passwords) you created for your account\n\nThis is created under https://bsky.app/settings/app-passwords\n\n**Use this if you are self-hosting Multi-Scrobbler on localhost or accessed like http://IP:PORT**"},"serviceAllow":{"type":"array","items":{"type":"string"}},"serviceDeny":{"type":"array","items":{"type":"string"}}},"required":["identifier"],"title":"TealSourceData"},"TealSourceOptions":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"TealSourceOptions"},"RockskySourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/RockskySourceData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/RockskySourceOptions"},"configureAs":{"type":"string","enum":["source"],"description":"When used in `rocksky.config` this tells multi-scrobbler whether to use this data to configure a source or client.","default":"source","examples":["source"]},"type":{"type":"string","enum":["rocksky"]}},"required":["data","type"],"title":"RockskySourceAIOConfig"},"RockskySourceData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"key":{"type":"string","description":"API Key generated from [API Applications](https://docs.rocksky.app/migrating-from-listenbrainz-to-rocksky-1040189m0) in Rocksky for your account","examples":["6794186bf-1157-4de6-80e5-uvb411f3ea2b"]},"handle":{"type":"string","description":"The **fully-qualified** handle for your ATPRoto/Bluesky account, like:\n\n* alice.bsky.social\n* foxxmd.com\n* mysuer.blacksky.app"}},"required":["handle","key"],"title":"RockskySourceData"},"RockskySourceOptions":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"},"audioScrobblerUrl":{"type":"string","description":"URL for the Rocksky *Listenbrainz* endpoint, if not using the default","examples":["https://audioscrobbler.rocksky.app"],"default":"https://audioscrobbler.rocksky.app"},"apiUrl":{"type":"string","description":"URL for the Rocksky *API* endpoint, if not using the default","examples":["https://api.rocksky.app"],"default":"https://api.rocksky.app"}},"title":"RockskySourceOptions"},"ClientAIOConfig":{"anyOf":[{"$ref":"#/definitions/MalojaClientAIOConfig"},{"$ref":"#/definitions/LastfmClientAIOConfig"},{"$ref":"#/definitions/LibrefmClientAIOConfig"},{"$ref":"#/definitions/ListenBrainzClientAIOConfig"},{"$ref":"#/definitions/KoitoClientAIOConfig"},{"$ref":"#/definitions/TealClientAIOConfig"},{"$ref":"#/definitions/RockSkyClientAIOConfig"}],"title":"ClientAIOConfig"},"MalojaClientAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this client. Used with sources to restrict where scrobbles are sent.","examples":["MyConfig"]},"data":{"$ref":"#/definitions/MalojaClientData","description":"Specific data required to configure this client"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"options":{"$ref":"#/definitions/CommonClientOptions"},"configureAs":{"type":"string","enum":["client","source"],"description":"Should always be `client` when using Maloja as a client","default":"client","examples":["client"]},"type":{"type":"string","enum":["maloja"]}},"required":["data","name","type"],"title":"MalojaClientAIOConfig"},"MalojaClientData":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"url":{"type":"string","description":"URL for maloja server","examples":["http://localhost:42010"]},"apiKey":{"type":"string","description":"API Key for Maloja server","examples":["myApiKey"]}},"required":["apiKey","url"],"title":"MalojaClientData"},"CommonClientOptions":{"type":"object","properties":{"refreshEnabled":{"type":"boolean","description":"Try to get fresh scrobble history from client when tracks to be scrobbled are newer than the last scrobble found in client history","default":true,"examples":[true]},"refreshStaleAfter":{"type":"number","description":"Refresh scrobbled plays from upstream service if last refresh was at least X seconds ago\n\n**In most case this setting does NOT need to be changed.** The default value is sufficient for the majority of use-cases. Increasing this setting may increase upstream service load and slow down scrobbles.\n\nThis setting should only be changed in specific scenarios where MS is handling multiple \"relaying\" client-services (IE lfm -> lz -> lfm) and there is the potential for a client to be out of sync after more than a few seconds.","examples":[60],"default":60},"refreshMinInterval":{"type":"number","description":"Minimum time (milliseconds) required to pass before upstream scrobbles can be refreshed.\n\n**In most case this setting does NOT need to be changed.** This will always be equal to or smaller than `refreshStaleAfter`.","default":5000,"examples":[5000]},"refreshInitialCount":{"type":"number","description":"The number of tracks to retrieve on initial refresh (related to scrobbleBacklogCount). If not specified this is the maximum supported by the client in 1 API call."},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"checkExistingScrobbles":{"type":"boolean","description":"Check client for an existing scrobble at the same recorded time as the \"new\" track to be scrobbled. If an existing scrobble is found this track is not track scrobbled.","default":true,"examples":[true]},"verbose":{"type":"object","properties":{"match":{"$ref":"#/definitions/MatchLoggingOptions"}},"description":"Options used for increasing verbosity of logging in MS (used for debugging)"},"deadLetterRetries":{"type":"number","description":"Number of times MS should automatically retry scrobbles in dead letter queue","default":1,"examples":[1]},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"CommonClientOptions"},"LastfmClientAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this client. Used with sources to restrict where scrobbles are sent.","examples":["MyConfig"]},"data":{"$ref":"#/definitions/LastfmData","description":"Specific data required to configure this client"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"options":{"$ref":"#/definitions/LastfmClientOptions"},"configureAs":{"type":"string","enum":["client","source"],"description":"Should always be `client` when using LastFM as a client","default":"client","examples":["client"]},"type":{"type":"string","enum":["lastfm"]}},"required":["data","name","type"],"title":"LastfmClientAIOConfig"},"LastfmData":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"apiKey":{"type":"string","description":"API Key generated from Last.fm/Libre.fm account","examples":["787c921a2a2ab42320831aba0c8f2fc2"]},"secret":{"type":"string","description":"Secret generated from Last.fm/Libre.fm account","examples":["ec42e09d5ae0ee0f0816ca151008412a"]},"session":{"type":"string","description":"Optional session id returned from a completed auth flow"},"redirectUri":{"type":"string","description":"Optional URI to use for callback. Specify this if callback should be different than the default. MUST have \"lastfm/callback\" in the URL somewhere.","default":"http://localhost:9078/lastfm/callback","examples":["http://localhost:9078/lastfm/callback"]}},"required":["apiKey","secret"],"title":"LastfmData"},"LastfmClientOptions":{"type":"object","properties":{"nowPlaying":{"anyOf":[{"type":"boolean"},{"type":"array","items":{"type":"string"}}],"description":"Configure if this Client should report Now Playing from Sources that can scrobble to it\n\n* `true` (default) => Report Now Playing from any eligible Source. \n * If multiple Sources are Playing then reported Play is based on alphabetical order of Source names\n* `false` => Do not report Now Playing\n* `string` list => list of Source `names` that should be allowed to report Now Playing. Order of list determine priority of Play to Report.","default":true},"refreshEnabled":{"type":"boolean","description":"Try to get fresh scrobble history from client when tracks to be scrobbled are newer than the last scrobble found in client history","default":true,"examples":[true]},"refreshStaleAfter":{"type":"number","description":"Refresh scrobbled plays from upstream service if last refresh was at least X seconds ago\n\n**In most case this setting does NOT need to be changed.** The default value is sufficient for the majority of use-cases. Increasing this setting may increase upstream service load and slow down scrobbles.\n\nThis setting should only be changed in specific scenarios where MS is handling multiple \"relaying\" client-services (IE lfm -> lz -> lfm) and there is the potential for a client to be out of sync after more than a few seconds.","examples":[60],"default":60},"refreshMinInterval":{"type":"number","description":"Minimum time (milliseconds) required to pass before upstream scrobbles can be refreshed.\n\n**In most case this setting does NOT need to be changed.** This will always be equal to or smaller than `refreshStaleAfter`.","default":5000,"examples":[5000]},"refreshInitialCount":{"type":"number","description":"The number of tracks to retrieve on initial refresh (related to scrobbleBacklogCount). If not specified this is the maximum supported by the client in 1 API call."},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"checkExistingScrobbles":{"type":"boolean","description":"Check client for an existing scrobble at the same recorded time as the \"new\" track to be scrobbled. If an existing scrobble is found this track is not track scrobbled.","default":true,"examples":[true]},"verbose":{"type":"object","properties":{"match":{"$ref":"#/definitions/MatchLoggingOptions"}},"description":"Options used for increasing verbosity of logging in MS (used for debugging)"},"deadLetterRetries":{"type":"number","description":"Number of times MS should automatically retry scrobbles in dead letter queue","default":1,"examples":[1]},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"LastfmClientOptions"},"LibrefmClientAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this client. Used with sources to restrict where scrobbles are sent.","examples":["MyConfig"]},"data":{"$ref":"#/definitions/LibrefmData","description":"Specific data required to configure this client"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"options":{"$ref":"#/definitions/LibrefmClientOptions"},"configureAs":{"type":"string","enum":["client","source"],"description":"Should always be `client` when using Librefm as a client","default":"client","examples":["client"]},"type":{"type":"string","enum":["librefm"]}},"required":["data","name","type"],"title":"LibrefmClientAIOConfig"},"LibrefmClientOptions":{"type":"object","properties":{"nowPlaying":{"anyOf":[{"type":"boolean"},{"type":"array","items":{"type":"string"}}],"description":"Configure if this Client should report Now Playing from Sources that can scrobble to it\n\n* `true` (default) => Report Now Playing from any eligible Source. \n * If multiple Sources are Playing then reported Play is based on alphabetical order of Source names\n* `false` => Do not report Now Playing\n* `string` list => list of Source `names` that should be allowed to report Now Playing. Order of list determine priority of Play to Report.","default":true},"refreshEnabled":{"type":"boolean","description":"Try to get fresh scrobble history from client when tracks to be scrobbled are newer than the last scrobble found in client history","default":true,"examples":[true]},"refreshStaleAfter":{"type":"number","description":"Refresh scrobbled plays from upstream service if last refresh was at least X seconds ago\n\n**In most case this setting does NOT need to be changed.** The default value is sufficient for the majority of use-cases. Increasing this setting may increase upstream service load and slow down scrobbles.\n\nThis setting should only be changed in specific scenarios where MS is handling multiple \"relaying\" client-services (IE lfm -> lz -> lfm) and there is the potential for a client to be out of sync after more than a few seconds.","examples":[60],"default":60},"refreshMinInterval":{"type":"number","description":"Minimum time (milliseconds) required to pass before upstream scrobbles can be refreshed.\n\n**In most case this setting does NOT need to be changed.** This will always be equal to or smaller than `refreshStaleAfter`.","default":5000,"examples":[5000]},"refreshInitialCount":{"type":"number","description":"The number of tracks to retrieve on initial refresh (related to scrobbleBacklogCount). If not specified this is the maximum supported by the client in 1 API call."},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"checkExistingScrobbles":{"type":"boolean","description":"Check client for an existing scrobble at the same recorded time as the \"new\" track to be scrobbled. If an existing scrobble is found this track is not track scrobbled.","default":true,"examples":[true]},"verbose":{"type":"object","properties":{"match":{"$ref":"#/definitions/MatchLoggingOptions"}},"description":"Options used for increasing verbosity of logging in MS (used for debugging)"},"deadLetterRetries":{"type":"number","description":"Number of times MS should automatically retry scrobbles in dead letter queue","default":1,"examples":[1]},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"LibrefmClientOptions"},"ListenBrainzClientAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this client. Used with sources to restrict where scrobbles are sent.","examples":["MyConfig"]},"data":{"$ref":"#/definitions/ListenBrainzClientData","description":"Specific data required to configure this client"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"options":{"$ref":"#/definitions/CommonClientOptions"},"configureAs":{"type":"string","enum":["client","source"],"description":"Should always be `client` when using Listenbrainz as a client","default":"client","examples":["client"]},"type":{"type":"string","enum":["listenbrainz"]}},"required":["data","name","type"],"title":"ListenBrainzClientAIOConfig"},"ListenBrainzClientData":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"url":{"type":"string","description":"URL for the ListenBrainz server, if not using the default","examples":["https://api.listenbrainz.org/"],"default":"https://api.listenbrainz.org/"},"token":{"type":"string","description":"User token for the user to scrobble for","examples":["6794186bf-1157-4de6-80e5-uvb411f3ea2b"]},"username":{"type":"string","description":"Username of the user to scrobble for"}},"required":["token","username"],"title":"ListenBrainzClientData"},"KoitoClientAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this client. Used with sources to restrict where scrobbles are sent.","examples":["MyConfig"]},"data":{"$ref":"#/definitions/KoitoClientData","description":"Specific data required to configure this client"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"options":{"$ref":"#/definitions/CommonClientOptions"},"configureAs":{"type":"string","enum":["client","source"],"description":"Should always be `client` when using Koito as a client","default":"client","examples":["client"]},"type":{"type":"string","enum":["koito"]}},"required":["data","name","type"],"title":"KoitoClientAIOConfig"},"KoitoClientData":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"url":{"type":"string","description":"URL for the Koito server","examples":["http://192.168.0.100:4110"]},"token":{"type":"string","description":"User token for the user to scrobble for","examples":["pM195xPV98CDpk0QW47FIIOR8AKATAX5DblBF-Jq0t1MbbKL"]},"username":{"type":"string","description":"Username of the user to scrobble for"}},"required":["token","url","username"],"title":"KoitoClientData"},"TealClientAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this client. Used with sources to restrict where scrobbles are sent.","examples":["MyConfig"]},"data":{"$ref":"#/definitions/TealClientData","description":"Specific data required to configure this client"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"options":{"$ref":"#/definitions/TealClientOptions"},"configureAs":{"type":"string","enum":["client","source"],"description":"Should always be `client` when using Tealfm as a client","default":"client","examples":["client"]},"type":{"type":"string","enum":["tealfm"]}},"required":["data","name","type"],"title":"TealClientAIOConfig"},"TealClientData":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"baseUri":{"type":"string","description":"The base URI of the Multi-Scrobbler to use for ATProto OAuth\n\nOnly include this if you want to use OAuth. The URI must be a non-IP/non-local domain using https: protocol."},"identifier":{"type":"string","description":"Identify the account to login as\n\n* For **App Password** Auth - your email\n* For **Oauth** - your handle minus the @"},"appPassword":{"type":"string","description":"The [App Password](https://atproto.com/specs/xrpc#app-passwords) you created for your account\n\nThis is created under https://bsky.app/settings/app-passwords\n\n**Use this if you are self-hosting Multi-Scrobbler on localhost or accessed like http://IP:PORT**"}},"required":["identifier"],"title":"TealClientData"},"TealClientOptions":{"type":"object","properties":{"refreshEnabled":{"type":"boolean","description":"Try to get fresh scrobble history from client when tracks to be scrobbled are newer than the last scrobble found in client history","default":true,"examples":[true]},"refreshStaleAfter":{"type":"number","description":"Refresh scrobbled plays from upstream service if last refresh was at least X seconds ago\n\n**In most case this setting does NOT need to be changed.** The default value is sufficient for the majority of use-cases. Increasing this setting may increase upstream service load and slow down scrobbles.\n\nThis setting should only be changed in specific scenarios where MS is handling multiple \"relaying\" client-services (IE lfm -> lz -> lfm) and there is the potential for a client to be out of sync after more than a few seconds.","examples":[60],"default":60},"refreshMinInterval":{"type":"number","description":"Minimum time (milliseconds) required to pass before upstream scrobbles can be refreshed.\n\n**In most case this setting does NOT need to be changed.** This will always be equal to or smaller than `refreshStaleAfter`.","default":5000,"examples":[5000]},"refreshInitialCount":{"type":"number","description":"The number of tracks to retrieve on initial refresh (related to scrobbleBacklogCount). If not specified this is the maximum supported by the client in 1 API call."},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"checkExistingScrobbles":{"type":"boolean","description":"Check client for an existing scrobble at the same recorded time as the \"new\" track to be scrobbled. If an existing scrobble is found this track is not track scrobbled.","default":true,"examples":[true]},"verbose":{"type":"object","properties":{"match":{"$ref":"#/definitions/MatchLoggingOptions"}},"description":"Options used for increasing verbosity of logging in MS (used for debugging)"},"deadLetterRetries":{"type":"number","description":"Number of times MS should automatically retry scrobbles in dead letter queue","default":1,"examples":[1]},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"TealClientOptions"},"RockSkyClientAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this client. Used with sources to restrict where scrobbles are sent.","examples":["MyConfig"]},"data":{"$ref":"#/definitions/RockSkyClientData","description":"Specific data required to configure this client"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"options":{"$ref":"#/definitions/RockSkyClientOptions"},"configureAs":{"type":"string","enum":["client","source"],"description":"Should always be `client` when using RockSky as a client","default":"client","examples":["client"]},"type":{"type":"string","enum":["rocksky"]}},"required":["data","name","type"],"title":"RockSkyClientAIOConfig"},"RockSkyClientData":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"key":{"type":"string","description":"API Key generated from [API Applications](https://docs.rocksky.app/migrating-from-listenbrainz-to-rocksky-1040189m0) in Rocksky for your account","examples":["6794186bf-1157-4de6-80e5-uvb411f3ea2b"]},"handle":{"type":"string","description":"The **fully-qualified** handle for your ATPRoto/Bluesky account, like:\n\n* alice.bsky.social\n* foxxmd.com\n* mysuer.blacksky.app"}},"required":["handle","key"],"title":"RockSkyClientData"},"RockSkyClientOptions":{"type":"object","properties":{"nowPlaying":{"anyOf":[{"type":"boolean"},{"type":"array","items":{"type":"string"}}],"description":"Configure if this Client should report Now Playing from Sources that can scrobble to it\n\n* `true` (default) => Report Now Playing from any eligible Source. \n * If multiple Sources are Playing then reported Play is based on alphabetical order of Source names\n* `false` => Do not report Now Playing\n* `string` list => list of Source `names` that should be allowed to report Now Playing. Order of list determine priority of Play to Report.","default":true},"refreshEnabled":{"type":"boolean","description":"Try to get fresh scrobble history from client when tracks to be scrobbled are newer than the last scrobble found in client history","default":true,"examples":[true]},"refreshStaleAfter":{"type":"number","description":"Refresh scrobbled plays from upstream service if last refresh was at least X seconds ago\n\n**In most case this setting does NOT need to be changed.** The default value is sufficient for the majority of use-cases. Increasing this setting may increase upstream service load and slow down scrobbles.\n\nThis setting should only be changed in specific scenarios where MS is handling multiple \"relaying\" client-services (IE lfm -> lz -> lfm) and there is the potential for a client to be out of sync after more than a few seconds.","examples":[60],"default":60},"refreshMinInterval":{"type":"number","description":"Minimum time (milliseconds) required to pass before upstream scrobbles can be refreshed.\n\n**In most case this setting does NOT need to be changed.** This will always be equal to or smaller than `refreshStaleAfter`.","default":5000,"examples":[5000]},"refreshInitialCount":{"type":"number","description":"The number of tracks to retrieve on initial refresh (related to scrobbleBacklogCount). If not specified this is the maximum supported by the client in 1 API call."},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"checkExistingScrobbles":{"type":"boolean","description":"Check client for an existing scrobble at the same recorded time as the \"new\" track to be scrobbled. If an existing scrobble is found this track is not track scrobbled.","default":true,"examples":[true]},"verbose":{"type":"object","properties":{"match":{"$ref":"#/definitions/MatchLoggingOptions"}},"description":"Options used for increasing verbosity of logging in MS (used for debugging)"},"deadLetterRetries":{"type":"number","description":"Number of times MS should automatically retry scrobbles in dead letter queue","default":1,"examples":[1]},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"},"audioScrobblerUrl":{"type":"string","description":"URL for the Rocksky *Listenbrainz* endpoint, if not using the default","examples":["https://audioscrobbler.rocksky.app"],"default":"https://audioscrobbler.rocksky.app"},"apiUrl":{"type":"string","description":"URL for the Rocksky *API* endpoint, if not using the default","examples":["https://api.rocksky.app"],"default":"https://api.rocksky.app"}},"title":"RockSkyClientOptions"},"WebhookConfig":{"anyOf":[{"$ref":"#/definitions/GotifyConfig"},{"$ref":"#/definitions/NtfyConfig"},{"$ref":"#/definitions/AppriseConfig"}],"title":"WebhookConfig"},"GotifyConfig":{"type":"object","properties":{"type":{"type":"string","enum":["gotify","ntfy","apprise"],"description":"Webhook type. Valid values are:\n\n* gotify\n* ntfy","examples":["gotify"]},"name":{"type":"string","description":"A friendly name used to identify webhook config in logs"},"url":{"type":"string","description":"The URL of the Gotify server. Same URL that would be used to reach the Gotify UI","examples":["http://192.168.0.100:8078"]},"token":{"type":"string","description":"The token created for this Application in Gotify","examples":["AQZI58fA.rfSZbm"]},"priorities":{"$ref":"#/definitions/PrioritiesConfig","description":"Priority of messages\n\n* Info -> 5\n* Warn -> 7\n* Error -> 10"}},"required":["token","type","url"],"title":"GotifyConfig"},"PrioritiesConfig":{"type":"object","properties":{"info":{"type":"number","examples":[5]},"warn":{"type":"number","examples":[7]},"error":{"type":"number","examples":[10]}},"required":["info","warn","error"],"title":"PrioritiesConfig"},"NtfyConfig":{"type":"object","properties":{"type":{"type":"string","enum":["gotify","ntfy","apprise"],"description":"Webhook type. Valid values are:\n\n* gotify\n* ntfy","examples":["gotify"]},"name":{"type":"string","description":"A friendly name used to identify webhook config in logs"},"url":{"type":"string","description":"The URL of the Ntfy server","examples":["http://192.168.0.100:8078"]},"topic":{"type":"string","description":"The topic mutli-scrobbler should POST to"},"username":{"type":"string","description":"Required if topic is protected"},"password":{"type":"string","description":"Required if topic is protected"},"token":{"type":"string","description":"Use instead of username/password, required if topic is protected"},"priorities":{"$ref":"#/definitions/PrioritiesConfig","description":"Priority of messages\n\n* Info -> 3\n* Warn -> 4\n* Error -> 5"}},"required":["topic","type","url"],"title":"NtfyConfig"},"AppriseConfig":{"type":"object","properties":{"type":{"type":"string","enum":["gotify","ntfy","apprise"],"description":"Webhook type. Valid values are:\n\n* gotify\n* ntfy","examples":["gotify"]},"name":{"type":"string","description":"A friendly name used to identify webhook config in logs"},"host":{"type":"string","description":"The URL of the apprise-api server","examples":["http://192.168.0.100:8078"]},"urls":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"If using [Stateless Endpoints](https://github.com/caronc/apprise-api?tab=readme-ov-file#stateless-solution) the Apprise config URL(s) to send"},"keys":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"If using [Persistent Store Endpoints](https://github.com/caronc/apprise-api?tab=readme-ov-file#persistent-storage-solution) the Configuration ID(s) to send to\n\nNote: If multiple keys are defined then MS will attempt to POST to each one individually"},"tags":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Optional [tag(s)](https://github.com/caronc/apprise-api?tab=readme-ov-file#tagging) to send in the notification payload"}},"required":["host","type"],"title":"AppriseConfig"},"LogOptions":{"type":"object","properties":{"level":{"$ref":"#/definitions/LogLevel","description":"Specify the minimum log level for all log outputs without their own level specified.\n\nDefaults to env `LOG_LEVEL` or `info` if not specified.","default":"info"},"file":{"anyOf":[{"$ref":"#/definitions/LogLevel"},{"type":"boolean","const":false},{"$ref":"#/definitions/FileLogOptions"}],"description":"Specify the minimum log level to output to rotating files or file output options. If `false` no log files will be created."},"console":{"$ref":"#/definitions/LogLevel","description":"Specify the minimum log level streamed to the console (or docker container)"}},"description":"Configure log levels and file options for an AppLogger.\n\n```ts\nconst infoLogger = loggerApp({\n level: 'info' // console and file will log any levels `info` and above\n});\n\nconst logger = loggerApp({\n console: 'debug', // console will log `debug` and higher\n file: 'warn' // file will log `warn` and higher\n});\n\nconst fileLogger = loggerRollingApp({\n console: 'debug', // console will log `debug` and higher\n file: {\n level: 'warn', // file will log `warn` and higher\n path: '/my/cool/path/output.log', // optionally, output to log file at this path\n frequency: 'hourly', // optionally, rotate hourly\n }\n});\n```","title":"LogOptions"},"CacheConfigOptions":{"type":"object","properties":{"metadata":{"$ref":"#/definitions/CacheMetadataConfig"},"scrobble":{"$ref":"#/definitions/CacheScrobbleConfig"},"auth":{"$ref":"#/definitions/CacheAuthConfig"},"regex":{"type":"number","description":"Number of regex functions to cache (LRU)","default":200}},"title":"CacheConfigOptions"},"CacheMetadataConfig":{"$ref":"#/definitions/CacheConfig%3CCacheMetadataProvider%3E","title":"CacheMetadataConfig"},"CacheConfig":{"type":"object","properties":{"provider":{"$ref":"#/definitions/CacheMetadataProvider"},"connection":{"type":"string"}},"required":["provider"],"title":"CacheConfig"},"CacheMetadataProvider":{"$ref":"#/definitions/CacheProvider","title":"CacheMetadataProvider"},"CacheProvider":{"type":["string","boolean"],"enum":["memory","valkey","file",false],"title":"CacheProvider"},"CacheScrobbleConfig":{"$ref":"#/definitions/CacheConfig%3CCacheScrobbleProvider%3E","title":"CacheScrobbleConfig"},"CacheConfig":{"type":"object","properties":{"provider":{"$ref":"#/definitions/CacheScrobbleProvider"},"connection":{"type":"string"}},"required":["provider"],"title":"CacheConfig"},"CacheScrobbleProvider":{"$ref":"#/definitions/CacheProvider","title":"CacheScrobbleProvider"},"CacheAuthConfig":{"$ref":"#/definitions/CacheConfig%3CCacheAuthProvider%3E","title":"CacheAuthConfig"},"CacheConfig":{"type":"object","properties":{"provider":{"$ref":"#/definitions/CacheAuthProvider"},"connection":{"type":"string"}},"required":["provider"],"title":"CacheConfig"},"CacheAuthProvider":{"$ref":"#/definitions/CacheProvider","title":"CacheAuthProvider"},"TransformerCommonConfig":{"type":"object","properties":{"defaults":{"type":"object"},"data":{"type":"object"},"type":{"type":"string"},"name":{"type":"string"},"options":{"$ref":"#/definitions/TransformOptions"}},"required":["type"],"title":"TransformerCommonConfig"},"TransformOptions":{"type":"object","properties":{"failOnFetch":{"type":"boolean"},"throwOnFailure":{"anyOf":[{"type":"boolean"},{"type":"array","items":{"type":"string","enum":["artists","title","albumArtists","album","duration","meta"]}}]},"ttl":{"type":"string"}},"title":"TransformOptions"}}} \ No newline at end of file +{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"sourceDefaults":{"$ref":"#/definitions/SourceDefaults"},"clientDefaults":{"$ref":"#/definitions/ClientDefaults"},"sources":{"type":"array","items":{"$ref":"#/definitions/SourceAIOConfig"}},"clients":{"type":"array","items":{"$ref":"#/definitions/ClientAIOConfig"}},"webhooks":{"type":"array","items":{"$ref":"#/definitions/WebhookConfig"}},"port":{"type":"number","description":"Set the port the multi-scrobbler UI will be served from","default":9078,"examples":[9078]},"baseUrl":{"type":"string","description":"Set the Base URL the application should assume the UI is served from.\n\nThis will affect how default redirect URLs are generated (spotify, lastfm, deezer) and some logging messages.\n\nIt will NOT set the actual interface/IP that the application is listening on.\n\nThis can also be set using the BASE_URL environmental variable.","default":"http://localhost","examples":["http://localhost","http://192.168.0.101","https://ms.myDomain.tld"]},"logging":{"$ref":"#/definitions/LogOptions"},"disableWeb":{"type":"boolean","description":"Disable web server from running/listening on port.\n\nThis will also make any ingress sources (Plex, Jellyfin, Tautulli, etc...) unusable"},"debugMode":{"type":"boolean","description":"Enables ALL relevant logging and debug options for all sources/clients, when none are defined.\n\nThis is a convenience shortcut for enabling all output needed to troubleshoot an issue and does not need to be on for normal operation.\n\nIt can also be enabled with the environmental variable DEBUG_MODE=true","default":false,"examples":[false]},"cache":{"$ref":"#/definitions/CacheConfigOptions"},"transformers":{"type":"array","items":{"$ref":"#/definitions/TransformerCommonConfig"}}},"definitions":{"SourceDefaults":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"SourceDefaults"},"LogLevel":{"type":"string","enum":["silent","fatal","error","warn","info","log","verbose","debug","trace"],"description":"Names of log levels that can be invoked on the logger\n\nFrom lowest to highest:\n\n* `trace`\n* `debug`\n* `verbose`\n* `log`\n* `info`\n* `warn`\n* `error`\n* `fatal`\n* `silent` (will never output anything)\n\nWhen used in `LogOptions` specifies the **minimum** level the output should log at.","title":"LogLevel"},"FileLogOptions":{"type":"object","properties":{"timestamp":{"type":"string","enum":["unix","iso","auto"],"description":"For rolling log files\n\nWhen\n* value passed to rolling destination is a string (`path` from LogOptions is a string) and\n* `frequency` is defined\n\nThis determines the format of the datetime inserted into the log file name:\n\n* `unix` - unix epoch timestamp in milliseconds\n* `iso` - Full [ISO8601](https://en.wikipedia.org/wiki/ISO_8601) datetime IE '2024-03-07T20:11:34Z'\n* `auto`\n * When frequency is `daily` only inserts date IE YYYY-MM-DD\n * Otherwise inserts full ISO8601 datetime","default":"auto"},"size":{"type":["number","string"],"description":"The maximum size of a given rolling log file.\n\nCan be combined with frequency. Use k, m and g to express values in KB, MB or GB.\n\nNumerical values will be considered as MB.","default":"10MB"},"frequency":{"anyOf":[{"type":"string","enum":["daily"]},{"type":"string","enum":["hourly"]},{"type":"number"}],"description":"The amount of time a given rolling log file is used. Can be combined with size.\n\nUse `daily` or `hourly` to rotate file every day (or every hour). Existing file within the current day (or hour) will be re-used.\n\nNumerical values will be considered as a number of milliseconds. Using a numerical value will always create a new file upon startup.","default":"daily"},"path":{"anyOf":[{"type":"string"},{"$comment":"() => string"}],"description":"The path and filename to use for log files.\n\nIf using rolling files the filename will be appended with `.N` (a number) BEFORE the extension based on rolling status.\n\nMay also be specified using env LOG_PATH or a function that returns a string.\n\nIf path is relative the absolute path will be derived from `logBaseDir` (in `LoggerAppExtras`) which defaults to CWD","default":"./logs/app.log"},"level":{"anyOf":[{"$ref":"#/definitions/LogLevel"},{"type":"boolean","const":false}],"description":"Specify the minimum log level to output to rotating files. If `false` no log files will be created."}},"title":"FileLogOptions"},"ScrobbleThresholds":{"type":"object","properties":{"duration":{"type":["number","null"],"description":"The number of seconds a track has been listened to before it should be considered scrobbled.\n\nSet to null to disable.","default":240,"examples":[240]},"percent":{"type":["number","null"],"description":"The percentage (as an integer) of a track that should have been seen played before it should be scrobbled. Only used if the Source provides information about how long the track is.\n\nSet to null to disable.\n\nNOTE: This should be used with care when the Source is a \"polling\" type (has an 'interval' property). If the track is short and the interval is too high MS may ignore the track if percentage is high because it had not \"seen\" the track for long enough from first discovery, even if you have been playing the track for longer.","default":50,"examples":[50]}},"title":"ScrobbleThresholds"},"PlayTransformOptions":{"type":"object","properties":{"log":{"anyOf":[{"type":"boolean"},{"type":"string","enum":["all"]}]},"preCompare":{"$ref":"#/definitions/PlayTransformPartsConfig%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%3E"},"compare":{"type":"object","properties":{"candidate":{"$ref":"#/definitions/PlayTransformPartsConfig%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%3E"},"existing":{"$ref":"#/definitions/PlayTransformPartsConfig%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%3E"}}},"postCompare":{"$ref":"#/definitions/PlayTransformPartsConfig%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%3E"}},"title":"PlayTransformOptions"},"PlayTransformPartsConfig<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm)>":{"anyOf":[{"$ref":"#/definitions/PlayTransformPartsArray%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%2CMaybeStageTyped%3E"},{"$ref":"#/definitions/PlayTransformParts%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%2CMaybeStageTyped%3E"}],"description":"Represents the weakly-defined user config. May be an array of parts or one parts object","title":"PlayTransformPartsConfig<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm)>"},"PlayTransformPartsArray<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm),MaybeStageTyped>":{"type":"array","items":{"$ref":"#/definitions/PlayTransformParts%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%2CMaybeStageTyped%3E"},"title":"PlayTransformPartsArray<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm),MaybeStageTyped>"},"PlayTransformParts<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm),MaybeStageTyped>":{"anyOf":[{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"title":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"artists":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"albumArtists":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"album":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"duration":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"meta":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"onSuccess":{"$ref":"#/definitions/FlowControlTerm"},"onFailure":{"$ref":"#/definitions/FlowControlTerm"},"onSkip":{"$ref":"#/definitions/FlowControlTerm"},"failureReturnPartial":{"type":"boolean"},"type":{"$ref":"#/definitions/StageTypeMetadata"},"name":{"type":"string"},"stageHash":{"type":"string"},"score":{"type":"number"}},"required":["type"]},{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"title":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"artists":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"albumArtists":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"album":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"duration":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"meta":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"onSuccess":{"$ref":"#/definitions/FlowControlTerm"},"onFailure":{"$ref":"#/definitions/FlowControlTerm"},"onSkip":{"$ref":"#/definitions/FlowControlTerm"},"failureReturnPartial":{"type":"boolean"},"type":{"$ref":"#/definitions/StageTypeUser"},"name":{"type":"string"},"stageHash":{"type":"string"}},"required":["type"]},{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"title":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"artists":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"albumArtists":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"album":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"duration":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"meta":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"onSuccess":{"$ref":"#/definitions/FlowControlTerm"},"onFailure":{"$ref":"#/definitions/FlowControlTerm"},"onSkip":{"$ref":"#/definitions/FlowControlTerm"},"failureReturnPartial":{"type":"boolean"},"type":{"type":"string","enum":["native"]},"name":{"type":"string"},"stageHash":{"type":"string"}},"required":["type"]},{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"title":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"artists":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"albumArtists":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"album":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"duration":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"meta":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"onSuccess":{"$ref":"#/definitions/FlowControlTerm"},"onFailure":{"$ref":"#/definitions/FlowControlTerm"},"onSkip":{"$ref":"#/definitions/FlowControlTerm"},"failureReturnPartial":{"type":"boolean"},"name":{"type":"string"}}},{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"title":{},"artists":{},"albumArtists":{},"album":{},"duration":{},"meta":{},"onSuccess":{"$ref":"#/definitions/FlowControlTerm"},"onFailure":{"$ref":"#/definitions/FlowControlTerm"},"onSkip":{"$ref":"#/definitions/FlowControlTerm"},"failureReturnPartial":{"type":"boolean"},"type":{"type":"string"},"name":{"type":"string"},"stageHash":{"type":"string"}},"required":["type"]}],"title":"PlayTransformParts<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm),MaybeStageTyped>"},"WhenConditionsConfig":{"$ref":"#/definitions/WhenConditions%3Cstring%3E","title":"WhenConditionsConfig"},"WhenConditions":{"type":"array","items":{"$ref":"#/definitions/WhenParts%3Cstring%3E"},"title":"WhenConditions"},"WhenParts":{"$ref":"#/definitions/PlayTransformPartsAtomic%3Cstring%3E","title":"WhenParts"},"PlayTransformPartsAtomic":{"type":"object","properties":{"title":{"type":"string"},"artists":{"type":"string"},"albumArtists":{"type":"string"},"album":{"type":"string"},"duration":{"type":"string"},"meta":{"type":"string"}},"title":"PlayTransformPartsAtomic"},"Whennable":{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"}},"title":"Whennable"},"FlowControlTerm":{"type":"string","enum":["continue","stop"],"title":"FlowControlTerm"},"StageTypeMetadata":{"type":"string","enum":["spotify","musicbrainz","native"],"title":"StageTypeMetadata"},"SearchAndReplaceTerm":{"anyOf":[{"type":"string"},{"$ref":"#/definitions/ConditionalSearchAndReplaceTerm"}],"title":"SearchAndReplaceTerm"},"ConditionalSearchAndReplaceTerm":{"$ref":"#/definitions/ConditionalSearchAndReplaceRegExp","title":"ConditionalSearchAndReplaceTerm"},"ConditionalSearchAndReplaceRegExp":{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"search":{"anyOf":[{"type":"string"},{"type":"string","format":"regex"}],"description":"The search value to test for\n\nCan be a normal string (converted to a case-sensitive literal) or a valid regular expression as a string, or an actual RegExp object","examples":[["find this string","/some string*/ig"]]},"replace":{"type":"string","description":"The replacement string/value to use when search is found\n\nThis can be a literal string like `'replace with this`, an empty string to remove the search value (`''`), or a special regex value\n\nSee replacement here for more information: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace"},"test":{"$comment":"(obj: SearchAndReplaceRegExp) => boolean","type":"object","properties":{"namedArgs":{"type":"object","properties":{"obj":{"$ref":"#/definitions/SearchAndReplaceRegExp"}},"required":["obj"],"additionalProperties":false}},"description":"An optional function to execute before running this search-and-replace that decides if it should run at all"}},"required":["replace","search"],"title":"ConditionalSearchAndReplaceRegExp"},"SearchAndReplaceRegExp":{"type":"object","properties":{"search":{"anyOf":[{"type":"string"},{"type":"string","format":"regex"}],"description":"The search value to test for\n\nCan be a normal string (converted to a case-sensitive literal) or a valid regular expression as a string, or an actual RegExp object","examples":[["find this string","/some string*/ig"]]},"replace":{"type":"string","description":"The replacement string/value to use when search is found\n\nThis can be a literal string like `'replace with this`, an empty string to remove the search value (`''`), or a special regex value\n\nSee replacement here for more information: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace"},"test":{"$comment":"(obj: SearchAndReplaceRegExp) => boolean","type":"object","properties":{"namedArgs":{"type":"object","properties":{"obj":{"$ref":"#/definitions/SearchAndReplaceRegExp"}},"required":["obj"],"additionalProperties":false}},"description":"An optional function to execute before running this search-and-replace that decides if it should run at all"}},"required":["search","replace"],"title":"SearchAndReplaceRegExp"},"ExternalMetadataTerm":{"anyOf":[{"type":"boolean"},{"not":{}},{"$ref":"#/definitions/Whennable"}],"title":"ExternalMetadataTerm"},"StageTypeUser":{"type":"string","enum":["user"],"title":"StageTypeUser"},"ClientDefaults":{"type":"object","properties":{"refreshEnabled":{"type":"boolean","description":"Try to get fresh scrobble history from client when tracks to be scrobbled are newer than the last scrobble found in client history","default":true,"examples":[true]},"refreshStaleAfter":{"type":"number","description":"Refresh scrobbled plays from upstream service if last refresh was at least X seconds ago\n\n**In most case this setting does NOT need to be changed.** The default value is sufficient for the majority of use-cases. Increasing this setting may increase upstream service load and slow down scrobbles.\n\nThis setting should only be changed in specific scenarios where MS is handling multiple \"relaying\" client-services (IE lfm -> lz -> lfm) and there is the potential for a client to be out of sync after more than a few seconds.","examples":[60],"default":60},"refreshMinInterval":{"type":"number","description":"Minimum time (milliseconds) required to pass before upstream scrobbles can be refreshed.\n\n**In most case this setting does NOT need to be changed.** This will always be equal to or smaller than `refreshStaleAfter`.","default":5000,"examples":[5000]},"refreshInitialCount":{"type":"number","description":"The number of tracks to retrieve on initial refresh (related to scrobbleBacklogCount). If not specified this is the maximum supported by the client in 1 API call."},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"checkExistingScrobbles":{"type":"boolean","description":"Check client for an existing scrobble at the same recorded time as the \"new\" track to be scrobbled. If an existing scrobble is found this track is not track scrobbled.","default":true,"examples":[true]},"verbose":{"type":"object","properties":{"match":{"$ref":"#/definitions/MatchLoggingOptions"}},"description":"Options used for increasing verbosity of logging in MS (used for debugging)"},"deadLetterRetries":{"type":"number","description":"Number of times MS should automatically retry scrobbles in dead letter queue","default":1,"examples":[1]},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"ClientDefaults"},"MatchLoggingOptions":{"type":"object","properties":{"onNoMatch":{"type":"boolean","description":"Log to DEBUG when a new track does NOT match an existing scrobble","default":false,"examples":[false]},"onMatch":{"type":"boolean","description":"Log to DEBUG when a new track DOES match an existing scrobble","default":false,"examples":[false]},"confidenceBreakdown":{"type":"boolean","description":"Include confidence breakdowns in track match logging, if applicable","default":false,"examples":[false]}},"description":"Scrobble matching (between new source track and existing client scrobbles) logging options. Used for debugging.","title":"MatchLoggingOptions"},"SourceAIOConfig":{"anyOf":[{"$ref":"#/definitions/SpotifySourceAIOConfig"},{"$ref":"#/definitions/PlexApiSourceAIOConfig"},{"$ref":"#/definitions/DeezerSourceAIOConfig"},{"$ref":"#/definitions/DeezerInternalAIOConfig"},{"$ref":"#/definitions/ListenbrainzEndpointSourceAIOConfig"},{"$ref":"#/definitions/LastFMEndpointSourceAIOConfig"},{"$ref":"#/definitions/SubsonicSourceAIOConfig"},{"$ref":"#/definitions/JellyApiSourceAIOConfig"},{"$ref":"#/definitions/LastFmSouceAIOConfig"},{"$ref":"#/definitions/LibrefmSouceAIOConfig"},{"$ref":"#/definitions/YTMusicSourceAIOConfig"},{"$ref":"#/definitions/MPRISSourceAIOConfig"},{"$ref":"#/definitions/MopidySourceAIOConfig"},{"$ref":"#/definitions/ListenBrainzSourceAIOConfig"},{"$ref":"#/definitions/JRiverSourceAIOConfig"},{"$ref":"#/definitions/KodiSourceAIOConfig"},{"$ref":"#/definitions/WebScrobblerSourceAIOConfig"},{"$ref":"#/definitions/ChromecastSourceAIOConfig"},{"$ref":"#/definitions/MalojaSourceAIOConfig"},{"$ref":"#/definitions/MusikcubeSourceAIOConfig"},{"$ref":"#/definitions/MusicCastSourceAIOConfig"},{"$ref":"#/definitions/MPDSourceAIOConfig"},{"$ref":"#/definitions/VLCSourceAIOConfig"},{"$ref":"#/definitions/IcecastSourceAIOConfig"},{"$ref":"#/definitions/AzuracastSourceAIOConfig"},{"$ref":"#/definitions/KoitoSourceAIOConfig"},{"$ref":"#/definitions/TealSourceAIOConfig"},{"$ref":"#/definitions/RockskySourceAIOConfig"},{"$ref":"#/definitions/SonosSourceAIOConfig"}],"title":"SourceAIOConfig"},"SpotifySourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/SpotifySourceData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"type":{"type":"string","enum":["spotify"]}},"required":["data","type"],"title":"SpotifySourceAIOConfig"},"SpotifySourceData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)\n\nIt is unlikely you should need to change this unless you scrobble many very short tracks often\n\nReading:\n* https://developer.spotify.com/documentation/web-api/guides/rate-limits/\n* https://medium.com/mendix/limiting-your-amount-of-calls-in-mendix-most-of-the-time-rest-835dde55b10e\n * Rate limit may ~180 req/min\n* https://community.spotify.com/t5/Spotify-for-Developers/Web-API-ratelimit/m-p/5503150/highlight/true#M7930\n * Informally indicated as 20 req/sec? Probably for burstiness","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"clientId":{"type":"string","description":"spotify client id","examples":["787c921a2a2ab42320831aba0c8f2fc2"]},"clientSecret":{"type":"string","description":"spotify client secret","examples":["ec42e09d5ae0ee0f0816ca151008412a"]},"redirectUri":{"type":"string","description":"spotify redirect URI -- required only if not the default shown here. URI must end in \"callback\"","default":"http://localhost:9078/callback","examples":["http://localhost:9078/callback"]}},"required":["clientId","clientSecret"],"title":"SpotifySourceData"},"CommonSourceOptions":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"CommonSourceOptions"},"PlexApiSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/PlexApiData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/PlexApiOptions"},"type":{"type":"string","enum":["plex"]}},"required":["data","type"],"title":"PlexApiSourceAIOConfig"},"PlexApiData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"token":{"type":"string"},"url":{"type":"string","description":"http(s)://HOST:PORT of the Plex server to connect to"},"usersAllow":{"anyOf":[{"type":"string"},{"type":"boolean","enum":[true]},{"type":"array","items":{"type":"string"}}],"description":"Only scrobble for specific users (case-insensitive)\n\nIf `true` MS will scrobble activity from all users"},"usersBlock":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Do not scrobble for these users (case-insensitive)"},"devicesAllow":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Only scrobble if device or application name contains strings from this list (case-insensitive)"},"devicesBlock":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Do not scrobble if device or application name contains strings from this list (case-insensitive)"},"librariesAllow":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Only scrobble if library name contains string from this list (case-insensitive)"},"librariesBlock":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Do not scrobble if library name contains strings from this list (case-insensitive)"}},"required":["url"],"title":"PlexApiData"},"PlexApiOptions":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"},"ignoreInvalidCert":{"type":"boolean","description":"Ignore invalid cert errors when connecting to Plex\n\nUseful for Plex servers using \"Required\" Secure Connections with self-signed certificates\n\nDo not enable unless you know you need this.","default":false}},"title":"PlexApiOptions"},"DeezerSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/DeezerData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"type":{"type":"string","enum":["deezer"]}},"required":["data","type"],"title":"DeezerSourceAIOConfig"},"DeezerData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"clientId":{"type":"string","description":"deezer client id","examples":["a89cba1569901a0671d5a9875fed4be1"]},"clientSecret":{"type":"string","description":"deezer client secret","examples":["ec42e09d5ae0ee0f0816ca151008412a"]},"redirectUri":{"type":"string","description":"deezer redirect URI -- required only if not the default shown here. URI must end in \"callback\"","default":"http://localhost:9078/deezer/callback","examples":["http://localhost:9078/deezer/callback"]}},"required":["clientId","clientSecret"],"title":"DeezerData"},"DeezerInternalAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/DeezerInternalData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/DeezerInternalSourceOptions"},"type":{"type":"string","enum":["deezer"]}},"required":["data","type"],"title":"DeezerInternalAIOConfig"},"DeezerInternalData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"arl":{"type":"string","description":"ARL retrieved from Deezer response header"},"userAgent":{"type":"string","description":"User agent","default":"Mozilla/5.0 (X11; Linux i686; rv:135.0) Gecko/20100101 Firefox/135.0"},"accountId":{"type":"string","description":"The ID (USER_ID) of the linked account to monitor. If not set, monitors the main ARL account"}},"required":["arl"],"title":"DeezerInternalData"},"DeezerInternalSourceOptions":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"},"fuzzyDiscoveryIgnore":{"anyOf":[{"type":"boolean"},{"type":"string","enum":["aggressive"]}]}},"title":"DeezerInternalSourceOptions"},"ListenbrainzEndpointSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/ListenbrainzEndpointData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"type":{"type":"string","enum":["endpointlz"]}},"required":["type"],"title":"ListenbrainzEndpointSourceAIOConfig"},"ListenbrainzEndpointData":{"type":"object","properties":{"slug":{"type":["string","null"],"description":"The URL ending that should be used to identify scrobbles for this source\n\nIf you are using multiple Listenbrainz endpoint sources (scrobbles for many users) you can use a slug to match Sources with individual users/origins\n\nExample:\n\n* slug: 'usera' => API URL: http://localhost:9078/api/listenbrainz/usera\n* slug: 'originb' => API URL: http://localhost:9078/api/listenbrainz/originb\n\nIf no slug is found from an extension's incoming webhook event the first Listenbrainz source without a slug will be used"},"token":{"type":["string","null"],"description":"If an LZ submission request contains this token in the Authorization Header it will be used to match the submission with this Source\n\nSee: https://listenbrainz.readthedocs.io/en/latest/users/api/index.html#add-the-user-token-to-your-requests"}},"title":"ListenbrainzEndpointData"},"LastFMEndpointSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/LastFMEndpointData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"type":{"type":"string","enum":["endpointlfm"]}},"required":["type"],"title":"LastFMEndpointSourceAIOConfig"},"LastFMEndpointData":{"type":"object","properties":{"slug":{"type":["string","null"],"description":"The URL ending that should be used to identify scrobbles for this source\n\nIf you are using multiple Last.fm endpoint sources (scrobbles for many users) you can use a slug to match Sources with individual users/origins\n\nExample:\n\n* slug: 'usera' => API URL: http://localhost:9078/api/lastfm/usera\n* slug: 'originb' => API URL: http://localhost:9078/api/lastfm/originb\n\nIf no slug is found from an extension's incoming webhook event the first Last.fm source without a slug will be used"}},"title":"LastFMEndpointData"},"SubsonicSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/SubsonicData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"type":{"type":"string","enum":["subsonic"]}},"required":["data","type"],"title":"SubsonicSourceAIOConfig"},"SubsonicData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"url":{"type":"string","description":"URL of the subsonic media server to query","examples":["http://airsonic.local"]},"user":{"type":"string","description":"Username to login to the server with","examples":[["MyUser"]]},"password":{"type":"string","description":"Password for the user to login to the server with","examples":["MyPassword"]},"ignoreTlsErrors":{"type":"boolean","description":"If your subsonic server is using self-signed certs you may need to disable TLS errors in order to get a connection\n\nWARNING: This should be used with caution as your traffic may not be encrypted.","default":false},"legacyAuthentication":{"type":"boolean","description":"Older Subsonic versions, and some badly implemented servers (Nextcloud), use legacy authentication which sends your password in CLEAR TEXT. This is less secure than the newer, recommended hashing authentication method but in some cases it is needed. See \"Authentication\" section here => https://www.subsonic.org/pages/api.jsp\n\nIf this option is not specified it will be turned on if the subsonic server responds with error code 41 \"Token authentication not supported for LDAP users.\" -- See Error Handling section => https://www.subsonic.org/pages/api.jsp","default":false},"usersAllow":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Only scrobble for specific users (case-insensitive)\n\nIf undefined or an empty string/list MS will scrobble activity from all users"}},"required":["url","user","password"],"title":"SubsonicData"},"JellyApiSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/JellyApiData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/JellyApiOptions"},"type":{"type":"string","enum":["jellyfin"]}},"required":["data","type"],"title":"JellyApiSourceAIOConfig"},"JellyApiData":{"type":"object","properties":{"url":{"type":"string","description":"HOST:PORT of the Jellyfin server to connect to"},"user":{"type":"string","description":"The username of the user to authenticate for or track scrobbles for"},"password":{"type":"string","description":"Password of the username to authenticate for\n\nRequired if `apiKey` is not provided."},"apiKey":{"type":"string","description":"API Key to authenticate with.\n\nRequired if `password` is not provided."},"usersAllow":{"anyOf":[{"type":"string"},{"type":"boolean","enum":[true]},{"type":"array","items":{"type":"string"}}],"description":"Only scrobble for specific users (case-insensitive)\n\nIf `true` MS will scrobble activity from all users"},"usersBlock":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Do not scrobble for these users (case-insensitive)"},"devicesAllow":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Only scrobble if device or application name contains strings from this list (case-insensitive)"},"devicesBlock":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Do not scrobble if device or application name contains strings from this list (case-insensitive)"},"librariesAllow":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Only scrobble if library name contains string from this list (case-insensitive)"},"librariesBlock":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Do not scrobble if library name contains strings from this list (case-insensitive)"},"additionalAllowedLibraryTypes":{"type":"array","items":{},"description":"Allow MS to scrobble audio media in libraries classified other than 'music'\n\n`librariesAllow` will achieve the same result as this but this is more convenient if you do not want to explicitly list every library name or are only using `librariesBlock`"},"allowUnknown":{"type":"boolean","description":"Force media with a type of \"Unknown\" to be counted as Audio","default":false,"deprecated":"use allowMediaTypes instead"},"allowMediaTypes":{"anyOf":[{"type":"array","items":{}},{"type":"string"}],"description":"Allow these media types to be scrobbled.\n\nIf not defined or empty, uses 'Audio' as default. If non-empty then *only* uses these types (make sure you include Audio!)\n\nValues are case-insensitive.\n\nSee https://github.com/jellyfin/jellyfin-sdk-typescript/blob/master/src/generated-client/models/media-type.ts#L22 for possible types"},"frontendUrlOverride":{"type":"string","description":"HOST:PORT of the Jellyfin server that your browser will be able to access from the frontend (and thus load images and links from)\nIf unspecified it will use the normal server HOST and PORT from the `url`\nNecessary if you are using a reverse proxy or other network configuration that prevents the frontend from accessing the server directly\n\nENV: JELLYFIN_FRONTEND_URL_OVERRIDE"}},"required":["url","user"],"title":"JellyApiData"},"JellyApiOptions":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"JellyApiOptions"},"LastFmSouceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/LastFmSourceData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"configureAs":{"type":"string","enum":["source"],"description":"When used in `lastfm.config` this tells multi-scrobbler whether to use this data to configure a source or client.","default":"source","examples":["source"]},"type":{"type":"string","enum":["lastfm"]}},"required":["data","type"],"title":"LastFmSouceAIOConfig"},"LastFmSourceData":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"apiKey":{"type":"string","description":"API Key generated from Last.fm/Libre.fm account","examples":["787c921a2a2ab42320831aba0c8f2fc2"]},"secret":{"type":"string","description":"Secret generated from Last.fm/Libre.fm account","examples":["ec42e09d5ae0ee0f0816ca151008412a"]},"session":{"type":"string","description":"Optional session id returned from a completed auth flow"},"redirectUri":{"type":"string","description":"Optional URI to use for callback. Specify this if callback should be different than the default. MUST have \"lastfm/callback\" in the URL somewhere.","default":"http://localhost:9078/lastfm/callback","examples":["http://localhost:9078/lastfm/callback"]},"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"}},"required":["apiKey","secret"],"title":"LastFmSourceData"},"LibrefmSouceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/LibrefmData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"configureAs":{"type":"string","enum":["source"],"description":"When used in `librefm.config` this tells multi-scrobbler whether to use this data to configure a source or client.","default":"source","examples":["source"]},"type":{"type":"string","enum":["librefm"]}},"required":["data","type"],"title":"LibrefmSouceAIOConfig"},"LibrefmData":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"apiKey":{"type":"string","description":"Optional Secret for Libre.fm account\n\nThis can be anything, or it will be generated by multi-scrobbler","examples":["anyValue"]},"secret":{"type":"string","description":"Optional Secret for Libre.fm account\n\nThis can be anything, or it will be generated by multi-scrobbler","examples":["anyValue"]},"session":{"type":"string","description":"Optional session id returned from a completed auth flow"},"path":{"type":"string"},"urlBase":{"type":"string","description":"(Optional) The host and path prefix for your Libre.fm instance","default":"https://libre.fm/2.0/"},"redirectUri":{"type":"string","description":"Optional URI to use for callback. Specify this if callback should be different than the default. MUST have \"librefm/callback\" in the URL somewhere.","default":"http://localhost:9078/librefm/callback","examples":["http://localhost:9078/librefm/callback"]}},"title":"LibrefmData"},"YTMusicSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/YTMusicData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"type":"object","properties":{"logAuth":{"type":"boolean","description":"When true MS will log to DEBUG all of the credentials data it receives from YTM"},"logDiff":{"type":"boolean","description":"Always log history diff\n\nBy default MS will log to `WARN` if history diff is inconsistent but does not log if diff is expected (on new tracks found)\nSet this to `true` to ALWAYS log diff on new tracks. Expected diffs will log to `DEBUG` and inconsistent diffs will continue to log to `WARN`","default":false},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}}},"type":{"type":"string","enum":["ytmusic"]}},"required":["type"],"title":"YTMusicSourceAIOConfig"},"YTMusicData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"cookie":{"type":"string","description":"The cookie retrieved from the Request Headers of music.youtube.com after logging in.\n\nSee https://ytmusicapi.readthedocs.io/en/stable/setup/browser.html#copy-authentication-headers for how to retrieve this value.","examples":["VISITOR_INFO1_LIVE=jMp2xA1Xz2_PbVc; __Secure-3PAPISID=3AxsXpy0M/AkISpjek; ..."]},"clientId":{"type":"string","description":"Google Cloud Console project OAuth Client ID\n\nGenerated from a custom OAuth Client, see docs"},"clientSecret":{"type":"string","description":"Google Cloud Console project OAuth Client Secret\n\nGenerated from a custom OAuth Client, see docs"},"redirectUri":{"type":"string","description":"Google Cloud Console project OAuth Client Authorized redirect URI\n\nGenerated from a custom OAuth Client, see docs. multi-scrobbler will generate a default based on BASE_URL.\nOnly specify this if the default does not work for you."},"innertubeOptions":{"$ref":"#/definitions/InnertubeOptions","description":"Additional options for authorization and tailoring YTM client"}},"title":"YTMusicData"},"InnertubeOptions":{"type":"object","properties":{"po_token":{"type":"string","description":"Proof of Origin token\n\nMay be required if YTM starts returning 403"},"visitor_data":{"type":"string","description":"Visitor ID value found in VISITOR_INFO1_LIVE or visitorData cookie\n\nMay be required if YTM starts returning 403"},"account_index":{"type":"number","description":"If account login results in being able to choose multiple account, use a zero-based index to choose which one to monitor","examples":[0,1]},"location":{"type":"string"},"lang":{"type":"string"},"generate_session_locally":{"type":"boolean"},"device_category":{"type":"string"},"client_type":{"type":"string"},"timezone":{"type":"string"}},"title":"InnertubeOptions"},"MPRISSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/MPRISData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"type":{"type":"string","enum":["mpris"]}},"required":["data","type"],"title":"MPRISSourceAIOConfig"},"MPRISData":{"type":"object","properties":{"blacklist":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"DO NOT scrobble from any players that START WITH these values, case-insensitive","examples":[["spotify","vlc"]]},"whitelist":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"ONLY from any players that START WITH these values, case-insensitive\n\nIf whitelist is present then blacklist is ignored","examples":[["spotify","vlc"]]}},"title":"MPRISData"},"MopidySourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/MopidyData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"type":{"type":"string","enum":["mopidy"]}},"required":["data","type"],"title":"MopidySourceAIOConfig"},"MopidyData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"url":{"type":"string","description":"URL of the Mopidy HTTP server to connect to\n\nYou MUST have Mopidy-HTTP extension enabled: https://mopidy.com/ext/http\n\nmulti-scrobbler connects to the WebSocket endpoint that ultimately looks like this => `ws://localhost:6680/mopidy/ws/`\n\nThe URL you provide here will have all parts not explicitly defined filled in for you so if these are not the default you must define them.\n\nParts => [default value]\n\n* Protocol => `ws://`\n* Hostname => `localhost`\n* Port => `6680`\n* Path => `/mopidy/ws/`","examples":["ws://localhost:6680/mopidy/ws/"],"default":"ws://localhost:6680/mopidy/ws/"},"uriBlacklist":{"type":"array","items":{"type":"string"},"description":"Do not scrobble tracks whose URI STARTS WITH any of these strings, case-insensitive\n\nEX: Don't scrobble tracks from soundcloud by adding 'soundcloud' to this list.\n\nList is ignored if uriWhitelist is used."},"uriWhitelist":{"type":"array","items":{"type":"string"},"description":"Only scrobble tracks whose URI STARTS WITH any of these strings, case-insensitive\n\nEX: Only scrobble tracks from soundcloud by adding 'soundcloud' to this list."},"albumBlacklist":{"type":"array","items":{"type":"string"},"description":"Remove album data that matches any case-insensitive string from this list when scrobbling,\n\nFor certain sources (Soundcloud) Mopidy does not have all track info (Album) and will instead use \"Soundcloud\" as the Album name. You can prevent multi-scrobbler from using this bad Album data by adding the fake name to this list. Multi-scrobbler will still scrobble the track, just without the bad data.","examples":[["Soundcloud","Mixcloud"]],"default":["Soundcloud"]}},"title":"MopidyData"},"ListenBrainzSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/ListenBrainzSourceData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"configureAs":{"type":"string","enum":["source"],"description":"When used in `listenbrainz.config` this tells multi-scrobbler whether to use this data to configure a source or client.","default":"source","examples":["source"]},"type":{"type":"string","enum":["listenbrainz"]}},"required":["data","type"],"title":"ListenBrainzSourceAIOConfig"},"ListenBrainzSourceData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"url":{"type":"string","description":"URL for the ListenBrainz server, if not using the default","examples":["https://api.listenbrainz.org/"],"default":"https://api.listenbrainz.org/"},"token":{"type":"string","description":"User token for the user to scrobble for","examples":["6794186bf-1157-4de6-80e5-uvb411f3ea2b"]},"username":{"type":"string","description":"Username of the user to scrobble for"}},"required":["token","username"],"title":"ListenBrainzSourceData"},"JRiverSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/JRiverData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"type":{"type":"string","enum":["jriver"]}},"required":["data","type"],"title":"JRiverSourceAIOConfig"},"JRiverData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"url":{"type":"string","description":"URL of the JRiver HTTP server to connect to\n\nmulti-scrobbler connects to the Web Service Interface endpoint that ultimately looks like this => `http://yourDomain:52199/MCWS/v1/`\n\nThe URL you provide here will have all parts not explicitly defined filled in for you so if these are not the default you must define them.\n\nParts => [default value]\n\n* Protocol => `http://`\n* Hostname => `localhost`\n* Port => `52199`\n* Path => `/MCWS/v1/`","examples":["http://localhost:52199/MCWS/v1/"],"default":"http://localhost:52199/MCWS/v1/"},"username":{"type":"string","description":"If you have enabled authentication, the username you set"},"password":{"type":"string","description":"If you have enabled authentication, the password you set"}},"required":["url"],"title":"JRiverData"},"KodiSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/KodiData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"type":{"type":"string","enum":["kodi"]}},"required":["data","type"],"title":"KodiSourceAIOConfig"},"KodiData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"url":{"type":"string","description":"URL of the Kodi HTTP server to connect to\n\nmulti-scrobbler connects to the Web Service Interface endpoint that ultimately looks like this => `http://yourDomain:8080/jsonrpc`\n\nThe URL you provide here will have all parts not explicitly defined filled in for you so if these are not the default you must define them.\n\nParts => [default value]\n\n* Protocol => `http://`\n* Hostname => `localhost`\n* Port => `8080`\n* Path => `/jsonrpc`","examples":["http://localhost:8080/jsonrpc"],"default":"http://localhost:8080/jsonrpc"},"username":{"type":"string","description":"The username set for Remote Control via Web Sever"},"password":{"type":"string","description":"The password set for Remote Control via Web Sever"}},"required":["url","username","password"],"title":"KodiData"},"WebScrobblerSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/WebScrobblerData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"type":{"type":"string","enum":["webscrobbler"]}},"required":["type"],"title":"WebScrobblerSourceAIOConfig"},"WebScrobblerData":{"type":"object","properties":{"slug":{"type":["string","null"],"description":"The URL ending that should be used to identify scrobbles for this source\n\nIn WebScrobbler's Webhook you must set an 'API URL'. All MS WebScrobbler sources must start like:\n\nhttp://localhost:9078/api/webscrobbler\n\nIf you are using multiple WebScrobbler sources (scrobbles for many users) you must use a slug to match Sources with each users extension.\n\nExample:\n\n* slug: 'usera' => API URL: http://localhost:9078/api/webscrobbler/usera\n* slug: 'userb' => API URL: http://localhost:9078/api/webscrobbler/userb\n\nIf no slug is found from an extension's incoming webhook event the first WebScrobbler source without a slug will be used"},"blacklist":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Block scrobbling from specific WebScrobbler Connectors","examples":[["youtube"]]},"whitelist":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Only allow scrobbling from specific WebScrobbler Connectors","examples":[["mixcloud","soundcloud","bandcamp"]]}},"title":"WebScrobblerData"},"ChromecastSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/ChromecastData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"type":{"type":"string","enum":["chromecast"]}},"required":["data","type"],"title":"ChromecastSourceAIOConfig"},"ChromecastData":{"type":"object","properties":{"blacklistDevices":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"DO NOT scrobble from any cast devices that START WITH these values, case-insensitive\n\nUseful when used with auto discovery","examples":[["home-mini","family-tv"]]},"whitelistDevices":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"ONLY scrobble from any cast device that START WITH these values, case-insensitive\n\nIf whitelist is present then blacklist is ignored\n\nUseful when used with auto discovery","examples":[["home-mini","family-tv"]]},"blacklistApps":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"DO NOT scrobble from any application that START WITH these values, case-insensitive","examples":[["spotify","pandora"]]},"whitelistApps":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"ONLY scrobble from any application that START WITH these values, case-insensitive\n\nIf whitelist is present then blacklist is ignored","examples":[["spotify","pandora"]]},"useAvahi":{"type":"boolean","description":"Try to use Avahi and avahi-browse to resolve mDNS devices instead of native mDNS querying\n\nUseful for docker (alpine) container where mDNS resolution is not yet supported. Avahi socket must be exposed to the container and avahi-tools must be installed.","default":false},"useAutoDiscovery":{"type":"boolean","description":"Use mDNS to discovery Google Cast devices on your next automatically?\n\nIf not explicitly set then it is TRUE if `devices` is not set"},"devices":{"type":"array","items":{"$ref":"#/definitions/ChromecastDeviceInfo"},"description":"A list of Google Cast devices to monitor\n\nIf this is used then `useAutoDiscovery` is set to FALSE, if not explicitly set"},"allowUnknownMedia":{"anyOf":[{"type":"boolean"},{"type":"array","items":{"type":"string"}}],"description":"Chromecast Apps report a \"media type\" in the status info returned for whatever is currently playing\n\n* If set to TRUE then Music AND Generic/Unknown media will be tracked for ALL APPS\n* If set to FALSE then only media explicitly typed as Music will be tracked for ALL APPS\n* If set to a list then only Apps whose name contain one of these values, case-insensitive, will have Music AND Generic/Unknown tracked\n\nSee https://developers.google.com/cast/docs/media/messages#MediaInformation \"metadata\" property","default":false},"forceMediaRecognitionOn":{"type":"array","items":{"type":"string"},"description":"Media provided by any App whose name is listed here will ALWAYS be tracked, regardless of the \"media type\" reported\n\nApps will be recognized if they CONTAIN any of these values, case-insensitive"}},"title":"ChromecastData"},"ChromecastDeviceInfo":{"type":"object","properties":{"name":{"type":"string","description":"A friendly name to identify this device","examples":["MySmartTV"]},"address":{"type":"string","description":"The IP address of the device","examples":["192.168.0.115"]}},"required":["name","address"],"title":"ChromecastDeviceInfo"},"MalojaSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/MalojaSourceData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"configureAs":{"type":"string","enum":["source"],"description":"When used in `maloja.config` this tells multi-scrobbler whether to use this data to configure a source or client.","default":"source","examples":["source"]},"type":{"type":"string","enum":["maloja"]}},"required":["data","type"],"title":"MalojaSourceAIOConfig"},"MalojaSourceData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"url":{"type":"string","description":"URL for maloja server","examples":["http://localhost:42010"]},"apiKey":{"type":"string","description":"API Key for Maloja server","examples":["myApiKey"]}},"required":["apiKey","url"],"title":"MalojaSourceData"},"MusikcubeSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/MusikcubeData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"type":{"type":"string","enum":["musikcube"]}},"required":["data","type"],"title":"MusikcubeSourceAIOConfig"},"MusikcubeData":{"type":"object","properties":{"url":{"type":"string","description":"URL of the Musikcube Websocket (Metadata) server to connect to\n\nYou MUST have enabled 'metadata' server and set a password: https://github.com/clangen/musikcube/wiki/remote-api-documentation\n * musikcube -> settings -> server setup\n\nThe URL you provide here will have all parts not explicitly defined filled in for you so if these are not the default you must define them.\n\nParts => [default value]\n\n* Protocol => `ws://`\n* Hostname => `localhost`\n* Port => `7905`","examples":["ws://localhost:7905"],"default":"ws://localhost:7905"},"password":{"type":"string","description":"Password set in Musikcube https://github.com/clangen/musikcube/wiki/remote-api-documentation\n\n* musikcube -> settings -> server setup -> password"},"device_id":{"type":"string"}},"required":["password"],"title":"MusikcubeData"},"MusicCastSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/MusicCastData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"type":{"type":"string","enum":["musiccast"]}},"required":["data","type"],"title":"MusicCastSourceAIOConfig"},"MusicCastData":{"type":"object","properties":{"url":{"type":"string","description":"The host or URL of the YamahaExtendedControl endpoint to use","examples":[["192.168.0.101","http://192.168.0.101/YamahaExtendedControl"]]}},"required":["url"],"title":"MusicCastData"},"MPDSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/MPDData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/MPDSourceOptions"},"type":{"type":"string","enum":["mpd"]}},"required":["data","options","type"],"title":"MPDSourceAIOConfig"},"MPDData":{"type":"object","properties":{"url":{"type":"string","description":"URL:PORT of the MPD server to connect to\n\nTo use this you must have TCP connections enabled for your MPD server https://mpd.readthedocs.io/en/stable/user.html#client-connections","examples":["localhost:6600"],"default":"localhost:6600"},"path":{"type":"string","description":"If using socket specify the path instead of url.\n\ntrailing `~` is replaced by your home directory"},"password":{"type":"string","description":"Password for the server, if set https://mpd.readthedocs.io/en/stable/user.html#permissions-and-passwords"}},"title":"MPDData"},"MPDSourceOptions":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"MPDSourceOptions"},"VLCSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/VLCData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/VLCSourceOptions"},"type":{"type":"string","enum":["vlc"]}},"required":["data","type"],"title":"VLCSourceAIOConfig"},"VLCData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"url":{"type":"string","description":"URL:PORT of the VLC server to connect to\n\nTo use this you must have the Web (http) interface module enabled and a password set https://foxxmd.github.io/multi-scrobbler/docs/configuration#vlc","examples":["localhost:8080"],"default":"localhost:8080"},"password":{"type":"string","description":"Password for the server"}},"required":["password"],"title":"VLCData"},"VLCSourceOptions":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"},"filenamePatterns":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"A list of regular expressions to use to extract metadata (title, album, artist) from a filename\n\nUsed when VLC reports only the filename for the current audio track"},"logFilenamePatterns":{"type":"boolean","description":"Log to DEBUG when a filename-only track is matched or not matched by filenamePatterns","default":false},"dumpVlcMetadata":{"type":"boolean","description":"Dump all the metadata VLC reports for an audio track to DEBUG.\n\nUse this if reporting an issue with VLC not correctly capturing metadata for a track.","default":false}},"title":"VLCSourceOptions"},"IcecastSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/IcecastData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/IcecastSourceOptions"},"type":{"type":"string","enum":["icecast"]}},"required":["data","type"],"title":"IcecastSourceAIOConfig"},"IcecastData":{"type":"object","properties":{"sources":{"type":"array","items":{"$ref":"#/definitions/IcecastSource"}},"icestatsEndpoint":{"type":"string"},"statsEndpoint":{"type":"string"},"nextsongsEndpoint":{"type":"string"},"sevenhtmlEndpoint":{"type":"string"},"icyMetaInt":{"type":"number"},"url":{"type":"string","description":"The Icecast stream URL"}},"required":["url"],"title":"IcecastData"},"IcecastSource":{"type":"string","enum":["icy","ogg","icestats","stats","sevenhtml","nextsongs"],"title":"IcecastSource"},"IcecastSourceOptions":{"type":"object","properties":{"systemScrobble":{"type":"boolean","description":"For Sources that support manual listening, should MS default to scrobbling when no user interaction has occurred?\n\nIf not specified MS will use a Source's specific behavior, see Source's documentation."},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"IcecastSourceOptions"},"AzuracastSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/AzuracastData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"type":{"type":"string","enum":["azuracast"]}},"required":["data","type"],"title":"AzuracastSourceAIOConfig"},"AzuracastData":{"type":"object","properties":{"url":{"type":"string","description":"Base URL of the Azuracast instance\n\nThis does NOT include the station. If a station is included it will be ignored. Use `station` field to specify station, if necessary","examples":["https://radio.mydomain.tld","http://localhost:80"]},"station":{"type":"string","description":"The specific station to monitor\n\nScrobbling will only occur if any of the monitor conditions are met AND the station is ONLINE.\n\nTo monitor multiple stations create a Source for each station.","examples":["my-station-1"]},"monitorWhenListeners":{"type":["boolean","number"],"description":"Only activate scrobble monitoring if station\n\n* `true` => has any current listeners\n* `number` => has EQUAL TO or MORE THAN X number of listeners"},"monitorWhenLive":{"type":"boolean","description":"Only activate scrobble monitoring if station has a live DJ/Streamer","default":true},"apiKey":{"type":"string","description":"API Key used to access data about private streams\n\nhttps://www.azuracast.com/docs/developers/apis/#api-authentication"}},"required":["url","station"],"title":"AzuracastData"},"KoitoSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/KoitoSourceData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"configureAs":{"type":"string","enum":["source"],"description":"When used in `koito.config` this tells multi-scrobbler whether to use this data to configure a source or client.","default":"source","examples":["source"]},"type":{"type":"string","enum":["koito"]}},"required":["data","type"],"title":"KoitoSourceAIOConfig"},"KoitoSourceData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"url":{"type":"string","description":"URL for the Koito server","examples":["http://192.168.0.100:4110"]},"token":{"type":"string","description":"User token for the user to scrobble for","examples":["pM195xPV98CDpk0QW47FIIOR8AKATAX5DblBF-Jq0t1MbbKL"]},"username":{"type":"string","description":"Username of the user to scrobble for"}},"required":["token","url","username"],"title":"KoitoSourceData"},"TealSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/TealSourceData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/TealSourceOptions"},"configureAs":{"type":"string","enum":["source"],"description":"Should always be `souce` when using Tealfm as a Source","default":"source","examples":["source"]},"type":{"type":"string","enum":["tealfm"]}},"required":["data","type"],"title":"TealSourceAIOConfig"},"TealSourceData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"baseUri":{"type":"string","description":"The base URI of the Multi-Scrobbler to use for ATProto OAuth\n\nOnly include this if you want to use OAuth. The URI must be a non-IP/non-local domain using https: protocol."},"identifier":{"type":"string","description":"Identify the account to login as\n\n* For **App Password** Auth - your email\n* For **Oauth** - your handle minus the @"},"appPassword":{"type":"string","description":"The [App Password](https://atproto.com/specs/xrpc#app-passwords) you created for your account\n\nThis is created under https://bsky.app/settings/app-passwords\n\n**Use this if you are self-hosting Multi-Scrobbler on localhost or accessed like http://IP:PORT**"},"serviceAllow":{"type":"array","items":{"type":"string"}},"serviceDeny":{"type":"array","items":{"type":"string"}}},"required":["identifier"],"title":"TealSourceData"},"TealSourceOptions":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"TealSourceOptions"},"RockskySourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/RockskySourceData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/RockskySourceOptions"},"configureAs":{"type":"string","enum":["source"],"description":"When used in `rocksky.config` this tells multi-scrobbler whether to use this data to configure a source or client.","default":"source","examples":["source"]},"type":{"type":"string","enum":["rocksky"]}},"required":["data","type"],"title":"RockskySourceAIOConfig"},"RockskySourceData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"key":{"type":"string","description":"API Key generated from [API Applications](https://docs.rocksky.app/migrating-from-listenbrainz-to-rocksky-1040189m0) in Rocksky for your account","examples":["6794186bf-1157-4de6-80e5-uvb411f3ea2b"]},"handle":{"type":"string","description":"The **fully-qualified** handle for your ATPRoto/Bluesky account, like:\n\n* alice.bsky.social\n* foxxmd.com\n* mysuer.blacksky.app"}},"required":["handle","key"],"title":"RockskySourceData"},"RockskySourceOptions":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"},"audioScrobblerUrl":{"type":"string","description":"URL for the Rocksky *Listenbrainz* endpoint, if not using the default","examples":["https://audioscrobbler.rocksky.app"],"default":"https://audioscrobbler.rocksky.app"},"apiUrl":{"type":"string","description":"URL for the Rocksky *API* endpoint, if not using the default","examples":["https://api.rocksky.app"],"default":"https://api.rocksky.app"}},"title":"RockskySourceOptions"},"SonosSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/SonosData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/SonosSourceOptions"},"type":{"type":"string","enum":["sonos"]}},"required":["data","type"],"title":"SonosSourceAIOConfig"},"SonosData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"host":{"type":"string","description":"IP address of any connected Sonos speaker or device","examples":["192.168.0.170"]},"devicesAllow":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Only scrobble if device name contains strings from this list (case-insensitive)"},"devicesBlock":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Do not scrobble if device name contains strings from this list (case-insensitive)"},"groupsAllow":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Only scrobble if the name of a group the playing device belongs to contains strings from this list (case-insensitive)"},"groupsBlock":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Do not scrobble if the name of a group the playing device belongs to contains strings from this list (case-insensitive)"}},"required":["host"],"title":"SonosData"},"SonosSourceOptions":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"},"logEmptyPlayer":{"type":"boolean"}},"title":"SonosSourceOptions"},"ClientAIOConfig":{"anyOf":[{"$ref":"#/definitions/MalojaClientAIOConfig"},{"$ref":"#/definitions/LastfmClientAIOConfig"},{"$ref":"#/definitions/LibrefmClientAIOConfig"},{"$ref":"#/definitions/ListenBrainzClientAIOConfig"},{"$ref":"#/definitions/KoitoClientAIOConfig"},{"$ref":"#/definitions/TealClientAIOConfig"},{"$ref":"#/definitions/RockSkyClientAIOConfig"},{"$ref":"#/definitions/DiscordClientAIOConfig"}],"title":"ClientAIOConfig"},"MalojaClientAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this client. Used with sources to restrict where scrobbles are sent.","examples":["MyConfig"]},"data":{"$ref":"#/definitions/MalojaClientData","description":"Specific data required to configure this client"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"options":{"$ref":"#/definitions/CommonClientOptions"},"configureAs":{"type":"string","enum":["client","source"],"description":"Should always be `client` when using Maloja as a client","default":"client","examples":["client"]},"type":{"type":"string","enum":["maloja"]}},"required":["data","name","type"],"title":"MalojaClientAIOConfig"},"MalojaClientData":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"url":{"type":"string","description":"URL for maloja server","examples":["http://localhost:42010"]},"apiKey":{"type":"string","description":"API Key for Maloja server","examples":["myApiKey"]}},"required":["apiKey","url"],"title":"MalojaClientData"},"CommonClientOptions":{"type":"object","properties":{"refreshEnabled":{"type":"boolean","description":"Try to get fresh scrobble history from client when tracks to be scrobbled are newer than the last scrobble found in client history","default":true,"examples":[true]},"refreshStaleAfter":{"type":"number","description":"Refresh scrobbled plays from upstream service if last refresh was at least X seconds ago\n\n**In most case this setting does NOT need to be changed.** The default value is sufficient for the majority of use-cases. Increasing this setting may increase upstream service load and slow down scrobbles.\n\nThis setting should only be changed in specific scenarios where MS is handling multiple \"relaying\" client-services (IE lfm -> lz -> lfm) and there is the potential for a client to be out of sync after more than a few seconds.","examples":[60],"default":60},"refreshMinInterval":{"type":"number","description":"Minimum time (milliseconds) required to pass before upstream scrobbles can be refreshed.\n\n**In most case this setting does NOT need to be changed.** This will always be equal to or smaller than `refreshStaleAfter`.","default":5000,"examples":[5000]},"refreshInitialCount":{"type":"number","description":"The number of tracks to retrieve on initial refresh (related to scrobbleBacklogCount). If not specified this is the maximum supported by the client in 1 API call."},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"checkExistingScrobbles":{"type":"boolean","description":"Check client for an existing scrobble at the same recorded time as the \"new\" track to be scrobbled. If an existing scrobble is found this track is not track scrobbled.","default":true,"examples":[true]},"verbose":{"type":"object","properties":{"match":{"$ref":"#/definitions/MatchLoggingOptions"}},"description":"Options used for increasing verbosity of logging in MS (used for debugging)"},"deadLetterRetries":{"type":"number","description":"Number of times MS should automatically retry scrobbles in dead letter queue","default":1,"examples":[1]},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"CommonClientOptions"},"LastfmClientAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this client. Used with sources to restrict where scrobbles are sent.","examples":["MyConfig"]},"data":{"$ref":"#/definitions/LastfmData","description":"Specific data required to configure this client"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"options":{"$ref":"#/definitions/LastfmClientOptions"},"configureAs":{"type":"string","enum":["client","source"],"description":"Should always be `client` when using LastFM as a client","default":"client","examples":["client"]},"type":{"type":"string","enum":["lastfm"]}},"required":["data","name","type"],"title":"LastfmClientAIOConfig"},"LastfmData":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"apiKey":{"type":"string","description":"API Key generated from Last.fm/Libre.fm account","examples":["787c921a2a2ab42320831aba0c8f2fc2"]},"secret":{"type":"string","description":"Secret generated from Last.fm/Libre.fm account","examples":["ec42e09d5ae0ee0f0816ca151008412a"]},"session":{"type":"string","description":"Optional session id returned from a completed auth flow"},"redirectUri":{"type":"string","description":"Optional URI to use for callback. Specify this if callback should be different than the default. MUST have \"lastfm/callback\" in the URL somewhere.","default":"http://localhost:9078/lastfm/callback","examples":["http://localhost:9078/lastfm/callback"]}},"required":["apiKey","secret"],"title":"LastfmData"},"LastfmClientOptions":{"type":"object","properties":{"nowPlaying":{"anyOf":[{"type":"boolean"},{"type":"array","items":{"type":"string"}}],"description":"Configure if this Client should report Now Playing from Sources that can scrobble to it\n\n* `true` (default) => Report Now Playing from any eligible Source. \n * If multiple Sources are Playing then reported Play is based on alphabetical order of Source names\n* `false` => Do not report Now Playing\n* `string` list => list of Source `names` that should be allowed to report Now Playing. Order of list determine priority of Play to Report.","default":true},"refreshEnabled":{"type":"boolean","description":"Try to get fresh scrobble history from client when tracks to be scrobbled are newer than the last scrobble found in client history","default":true,"examples":[true]},"refreshStaleAfter":{"type":"number","description":"Refresh scrobbled plays from upstream service if last refresh was at least X seconds ago\n\n**In most case this setting does NOT need to be changed.** The default value is sufficient for the majority of use-cases. Increasing this setting may increase upstream service load and slow down scrobbles.\n\nThis setting should only be changed in specific scenarios where MS is handling multiple \"relaying\" client-services (IE lfm -> lz -> lfm) and there is the potential for a client to be out of sync after more than a few seconds.","examples":[60],"default":60},"refreshMinInterval":{"type":"number","description":"Minimum time (milliseconds) required to pass before upstream scrobbles can be refreshed.\n\n**In most case this setting does NOT need to be changed.** This will always be equal to or smaller than `refreshStaleAfter`.","default":5000,"examples":[5000]},"refreshInitialCount":{"type":"number","description":"The number of tracks to retrieve on initial refresh (related to scrobbleBacklogCount). If not specified this is the maximum supported by the client in 1 API call."},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"checkExistingScrobbles":{"type":"boolean","description":"Check client for an existing scrobble at the same recorded time as the \"new\" track to be scrobbled. If an existing scrobble is found this track is not track scrobbled.","default":true,"examples":[true]},"verbose":{"type":"object","properties":{"match":{"$ref":"#/definitions/MatchLoggingOptions"}},"description":"Options used for increasing verbosity of logging in MS (used for debugging)"},"deadLetterRetries":{"type":"number","description":"Number of times MS should automatically retry scrobbles in dead letter queue","default":1,"examples":[1]},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"LastfmClientOptions"},"LibrefmClientAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this client. Used with sources to restrict where scrobbles are sent.","examples":["MyConfig"]},"data":{"$ref":"#/definitions/LibrefmData","description":"Specific data required to configure this client"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"options":{"$ref":"#/definitions/LibrefmClientOptions"},"configureAs":{"type":"string","enum":["client","source"],"description":"Should always be `client` when using Librefm as a client","default":"client","examples":["client"]},"type":{"type":"string","enum":["librefm"]}},"required":["data","name","type"],"title":"LibrefmClientAIOConfig"},"LibrefmClientOptions":{"type":"object","properties":{"nowPlaying":{"anyOf":[{"type":"boolean"},{"type":"array","items":{"type":"string"}}],"description":"Configure if this Client should report Now Playing from Sources that can scrobble to it\n\n* `true` (default) => Report Now Playing from any eligible Source. \n * If multiple Sources are Playing then reported Play is based on alphabetical order of Source names\n* `false` => Do not report Now Playing\n* `string` list => list of Source `names` that should be allowed to report Now Playing. Order of list determine priority of Play to Report.","default":true},"refreshEnabled":{"type":"boolean","description":"Try to get fresh scrobble history from client when tracks to be scrobbled are newer than the last scrobble found in client history","default":true,"examples":[true]},"refreshStaleAfter":{"type":"number","description":"Refresh scrobbled plays from upstream service if last refresh was at least X seconds ago\n\n**In most case this setting does NOT need to be changed.** The default value is sufficient for the majority of use-cases. Increasing this setting may increase upstream service load and slow down scrobbles.\n\nThis setting should only be changed in specific scenarios where MS is handling multiple \"relaying\" client-services (IE lfm -> lz -> lfm) and there is the potential for a client to be out of sync after more than a few seconds.","examples":[60],"default":60},"refreshMinInterval":{"type":"number","description":"Minimum time (milliseconds) required to pass before upstream scrobbles can be refreshed.\n\n**In most case this setting does NOT need to be changed.** This will always be equal to or smaller than `refreshStaleAfter`.","default":5000,"examples":[5000]},"refreshInitialCount":{"type":"number","description":"The number of tracks to retrieve on initial refresh (related to scrobbleBacklogCount). If not specified this is the maximum supported by the client in 1 API call."},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"checkExistingScrobbles":{"type":"boolean","description":"Check client for an existing scrobble at the same recorded time as the \"new\" track to be scrobbled. If an existing scrobble is found this track is not track scrobbled.","default":true,"examples":[true]},"verbose":{"type":"object","properties":{"match":{"$ref":"#/definitions/MatchLoggingOptions"}},"description":"Options used for increasing verbosity of logging in MS (used for debugging)"},"deadLetterRetries":{"type":"number","description":"Number of times MS should automatically retry scrobbles in dead letter queue","default":1,"examples":[1]},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"LibrefmClientOptions"},"ListenBrainzClientAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this client. Used with sources to restrict where scrobbles are sent.","examples":["MyConfig"]},"data":{"$ref":"#/definitions/ListenBrainzClientData","description":"Specific data required to configure this client"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"options":{"$ref":"#/definitions/CommonClientOptions"},"configureAs":{"type":"string","enum":["client","source"],"description":"Should always be `client` when using Listenbrainz as a client","default":"client","examples":["client"]},"type":{"type":"string","enum":["listenbrainz"]}},"required":["data","name","type"],"title":"ListenBrainzClientAIOConfig"},"ListenBrainzClientData":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"url":{"type":"string","description":"URL for the ListenBrainz server, if not using the default","examples":["https://api.listenbrainz.org/"],"default":"https://api.listenbrainz.org/"},"token":{"type":"string","description":"User token for the user to scrobble for","examples":["6794186bf-1157-4de6-80e5-uvb411f3ea2b"]},"username":{"type":"string","description":"Username of the user to scrobble for"}},"required":["token","username"],"title":"ListenBrainzClientData"},"KoitoClientAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this client. Used with sources to restrict where scrobbles are sent.","examples":["MyConfig"]},"data":{"$ref":"#/definitions/KoitoClientData","description":"Specific data required to configure this client"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"options":{"$ref":"#/definitions/CommonClientOptions"},"configureAs":{"type":"string","enum":["client","source"],"description":"Should always be `client` when using Koito as a client","default":"client","examples":["client"]},"type":{"type":"string","enum":["koito"]}},"required":["data","name","type"],"title":"KoitoClientAIOConfig"},"KoitoClientData":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"url":{"type":"string","description":"URL for the Koito server","examples":["http://192.168.0.100:4110"]},"token":{"type":"string","description":"User token for the user to scrobble for","examples":["pM195xPV98CDpk0QW47FIIOR8AKATAX5DblBF-Jq0t1MbbKL"]},"username":{"type":"string","description":"Username of the user to scrobble for"}},"required":["token","url","username"],"title":"KoitoClientData"},"TealClientAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this client. Used with sources to restrict where scrobbles are sent.","examples":["MyConfig"]},"data":{"$ref":"#/definitions/TealClientData","description":"Specific data required to configure this client"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"options":{"$ref":"#/definitions/TealClientOptions"},"configureAs":{"type":"string","enum":["client","source"],"description":"Should always be `client` when using Tealfm as a client","default":"client","examples":["client"]},"type":{"type":"string","enum":["tealfm"]}},"required":["data","name","type"],"title":"TealClientAIOConfig"},"TealClientData":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"baseUri":{"type":"string","description":"The base URI of the Multi-Scrobbler to use for ATProto OAuth\n\nOnly include this if you want to use OAuth. The URI must be a non-IP/non-local domain using https: protocol."},"identifier":{"type":"string","description":"Identify the account to login as\n\n* For **App Password** Auth - your email\n* For **Oauth** - your handle minus the @"},"appPassword":{"type":"string","description":"The [App Password](https://atproto.com/specs/xrpc#app-passwords) you created for your account\n\nThis is created under https://bsky.app/settings/app-passwords\n\n**Use this if you are self-hosting Multi-Scrobbler on localhost or accessed like http://IP:PORT**"}},"required":["identifier"],"title":"TealClientData"},"TealClientOptions":{"type":"object","properties":{"refreshEnabled":{"type":"boolean","description":"Try to get fresh scrobble history from client when tracks to be scrobbled are newer than the last scrobble found in client history","default":true,"examples":[true]},"refreshStaleAfter":{"type":"number","description":"Refresh scrobbled plays from upstream service if last refresh was at least X seconds ago\n\n**In most case this setting does NOT need to be changed.** The default value is sufficient for the majority of use-cases. Increasing this setting may increase upstream service load and slow down scrobbles.\n\nThis setting should only be changed in specific scenarios where MS is handling multiple \"relaying\" client-services (IE lfm -> lz -> lfm) and there is the potential for a client to be out of sync after more than a few seconds.","examples":[60],"default":60},"refreshMinInterval":{"type":"number","description":"Minimum time (milliseconds) required to pass before upstream scrobbles can be refreshed.\n\n**In most case this setting does NOT need to be changed.** This will always be equal to or smaller than `refreshStaleAfter`.","default":5000,"examples":[5000]},"refreshInitialCount":{"type":"number","description":"The number of tracks to retrieve on initial refresh (related to scrobbleBacklogCount). If not specified this is the maximum supported by the client in 1 API call."},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"checkExistingScrobbles":{"type":"boolean","description":"Check client for an existing scrobble at the same recorded time as the \"new\" track to be scrobbled. If an existing scrobble is found this track is not track scrobbled.","default":true,"examples":[true]},"verbose":{"type":"object","properties":{"match":{"$ref":"#/definitions/MatchLoggingOptions"}},"description":"Options used for increasing verbosity of logging in MS (used for debugging)"},"deadLetterRetries":{"type":"number","description":"Number of times MS should automatically retry scrobbles in dead letter queue","default":1,"examples":[1]},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"TealClientOptions"},"RockSkyClientAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this client. Used with sources to restrict where scrobbles are sent.","examples":["MyConfig"]},"data":{"$ref":"#/definitions/RockSkyClientData","description":"Specific data required to configure this client"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"options":{"$ref":"#/definitions/RockSkyClientOptions"},"configureAs":{"type":"string","enum":["client","source"],"description":"Should always be `client` when using RockSky as a client","default":"client","examples":["client"]},"type":{"type":"string","enum":["rocksky"]}},"required":["data","name","type"],"title":"RockSkyClientAIOConfig"},"RockSkyClientData":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"key":{"type":"string","description":"API Key generated from [API Applications](https://docs.rocksky.app/migrating-from-listenbrainz-to-rocksky-1040189m0) in Rocksky for your account","examples":["6794186bf-1157-4de6-80e5-uvb411f3ea2b"]},"handle":{"type":"string","description":"The **fully-qualified** handle for your ATPRoto/Bluesky account, like:\n\n* alice.bsky.social\n* foxxmd.com\n* mysuer.blacksky.app"}},"required":["handle","key"],"title":"RockSkyClientData"},"RockSkyClientOptions":{"type":"object","properties":{"nowPlaying":{"anyOf":[{"type":"boolean"},{"type":"array","items":{"type":"string"}}],"description":"Configure if this Client should report Now Playing from Sources that can scrobble to it\n\n* `true` (default) => Report Now Playing from any eligible Source. \n * If multiple Sources are Playing then reported Play is based on alphabetical order of Source names\n* `false` => Do not report Now Playing\n* `string` list => list of Source `names` that should be allowed to report Now Playing. Order of list determine priority of Play to Report.","default":true},"refreshEnabled":{"type":"boolean","description":"Try to get fresh scrobble history from client when tracks to be scrobbled are newer than the last scrobble found in client history","default":true,"examples":[true]},"refreshStaleAfter":{"type":"number","description":"Refresh scrobbled plays from upstream service if last refresh was at least X seconds ago\n\n**In most case this setting does NOT need to be changed.** The default value is sufficient for the majority of use-cases. Increasing this setting may increase upstream service load and slow down scrobbles.\n\nThis setting should only be changed in specific scenarios where MS is handling multiple \"relaying\" client-services (IE lfm -> lz -> lfm) and there is the potential for a client to be out of sync after more than a few seconds.","examples":[60],"default":60},"refreshMinInterval":{"type":"number","description":"Minimum time (milliseconds) required to pass before upstream scrobbles can be refreshed.\n\n**In most case this setting does NOT need to be changed.** This will always be equal to or smaller than `refreshStaleAfter`.","default":5000,"examples":[5000]},"refreshInitialCount":{"type":"number","description":"The number of tracks to retrieve on initial refresh (related to scrobbleBacklogCount). If not specified this is the maximum supported by the client in 1 API call."},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"checkExistingScrobbles":{"type":"boolean","description":"Check client for an existing scrobble at the same recorded time as the \"new\" track to be scrobbled. If an existing scrobble is found this track is not track scrobbled.","default":true,"examples":[true]},"verbose":{"type":"object","properties":{"match":{"$ref":"#/definitions/MatchLoggingOptions"}},"description":"Options used for increasing verbosity of logging in MS (used for debugging)"},"deadLetterRetries":{"type":"number","description":"Number of times MS should automatically retry scrobbles in dead letter queue","default":1,"examples":[1]},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"},"audioScrobblerUrl":{"type":"string","description":"URL for the Rocksky *Listenbrainz* endpoint, if not using the default","examples":["https://audioscrobbler.rocksky.app"],"default":"https://audioscrobbler.rocksky.app"},"apiUrl":{"type":"string","description":"URL for the Rocksky *API* endpoint, if not using the default","examples":["https://api.rocksky.app"],"default":"https://api.rocksky.app"}},"title":"RockSkyClientOptions"},"DiscordClientAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this client. Used with sources to restrict where scrobbles are sent.","examples":["MyConfig"]},"data":{"$ref":"#/definitions/DiscordClientData","description":"Specific data required to configure this client"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"options":{"$ref":"#/definitions/CommonClientOptions"},"configureAs":{"type":"string","enum":["client","source"],"description":"Should always be `client` when using Koito as a client","default":"client","examples":["client"]},"type":{"type":"string","enum":["discord"]}},"required":["data","name","type"],"title":"DiscordClientAIOConfig"},"DiscordClientData":{"type":"object","properties":{"token":{"type":"string"},"applicationId":{"type":"string"},"artwork":{"anyOf":[{"type":"boolean"},{"type":"string"},{"type":"array","items":{"type":"string"}}]},"artworkDefaultUrl":{"type":"string"},"statusOverrideAllow":{"anyOf":[{"type":"string"},{"type":"array","items":{"$ref":"#/definitions/StatusType"}}]},"listeningActivityAllow":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}]},"ipcLocations":{"anyOf":[{"type":"string"},{"type":"array","items":{"anyOf":[{"type":"string"},{"type":"array","minItems":2,"items":[{"type":"number"},{"type":"string"}],"maxItems":2}]}}]}},"title":"DiscordClientData"},"StatusType":{"type":"string","enum":["online","idle","dnd","invisible"],"title":"StatusType"},"WebhookConfig":{"anyOf":[{"$ref":"#/definitions/GotifyConfig"},{"$ref":"#/definitions/NtfyConfig"},{"$ref":"#/definitions/AppriseConfig"}],"title":"WebhookConfig"},"GotifyConfig":{"type":"object","properties":{"type":{"type":"string","enum":["gotify","ntfy","apprise"],"description":"Webhook type. Valid values are:\n\n* gotify\n* ntfy","examples":["gotify"]},"name":{"type":"string","description":"A friendly name used to identify webhook config in logs"},"url":{"type":"string","description":"The URL of the Gotify server. Same URL that would be used to reach the Gotify UI","examples":["http://192.168.0.100:8078"]},"token":{"type":"string","description":"The token created for this Application in Gotify","examples":["AQZI58fA.rfSZbm"]},"priorities":{"$ref":"#/definitions/PrioritiesConfig","description":"Priority of messages\n\n* Info -> 5\n* Warn -> 7\n* Error -> 10"}},"required":["token","type","url"],"title":"GotifyConfig"},"PrioritiesConfig":{"type":"object","properties":{"info":{"type":"number","examples":[5]},"warn":{"type":"number","examples":[7]},"error":{"type":"number","examples":[10]}},"required":["info","warn","error"],"title":"PrioritiesConfig"},"NtfyConfig":{"type":"object","properties":{"type":{"type":"string","enum":["gotify","ntfy","apprise"],"description":"Webhook type. Valid values are:\n\n* gotify\n* ntfy","examples":["gotify"]},"name":{"type":"string","description":"A friendly name used to identify webhook config in logs"},"url":{"type":"string","description":"The URL of the Ntfy server","examples":["http://192.168.0.100:8078"]},"topic":{"type":"string","description":"The topic mutli-scrobbler should POST to"},"username":{"type":"string","description":"Required if topic is protected"},"password":{"type":"string","description":"Required if topic is protected"},"token":{"type":"string","description":"Use instead of username/password, required if topic is protected"},"priorities":{"$ref":"#/definitions/PrioritiesConfig","description":"Priority of messages\n\n* Info -> 3\n* Warn -> 4\n* Error -> 5"}},"required":["topic","type","url"],"title":"NtfyConfig"},"AppriseConfig":{"type":"object","properties":{"type":{"type":"string","enum":["gotify","ntfy","apprise"],"description":"Webhook type. Valid values are:\n\n* gotify\n* ntfy","examples":["gotify"]},"name":{"type":"string","description":"A friendly name used to identify webhook config in logs"},"host":{"type":"string","description":"The URL of the apprise-api server","examples":["http://192.168.0.100:8078"]},"urls":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"If using [Stateless Endpoints](https://github.com/caronc/apprise-api?tab=readme-ov-file#stateless-solution) the Apprise config URL(s) to send"},"keys":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"If using [Persistent Store Endpoints](https://github.com/caronc/apprise-api?tab=readme-ov-file#persistent-storage-solution) the Configuration ID(s) to send to\n\nNote: If multiple keys are defined then MS will attempt to POST to each one individually"},"tags":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Optional [tag(s)](https://github.com/caronc/apprise-api?tab=readme-ov-file#tagging) to send in the notification payload"}},"required":["host","type"],"title":"AppriseConfig"},"LogOptions":{"type":"object","properties":{"level":{"$ref":"#/definitions/LogLevel","description":"Specify the minimum log level for all log outputs without their own level specified.\n\nDefaults to env `LOG_LEVEL` or `info` if not specified.","default":"info"},"file":{"anyOf":[{"$ref":"#/definitions/LogLevel"},{"type":"boolean","const":false},{"$ref":"#/definitions/FileLogOptions"}],"description":"Specify the minimum log level to output to rotating files or file output options. If `false` no log files will be created."},"console":{"$ref":"#/definitions/LogLevel","description":"Specify the minimum log level streamed to the console (or docker container)"}},"description":"Configure log levels and file options for an AppLogger.\n\n```ts\nconst infoLogger = loggerApp({\n level: 'info' // console and file will log any levels `info` and above\n});\n\nconst logger = loggerApp({\n console: 'debug', // console will log `debug` and higher\n file: 'warn' // file will log `warn` and higher\n});\n\nconst fileLogger = loggerRollingApp({\n console: 'debug', // console will log `debug` and higher\n file: {\n level: 'warn', // file will log `warn` and higher\n path: '/my/cool/path/output.log', // optionally, output to log file at this path\n frequency: 'hourly', // optionally, rotate hourly\n }\n});\n```","title":"LogOptions"},"CacheConfigOptions":{"type":"object","properties":{"metadata":{"$ref":"#/definitions/CacheMetadataConfig"},"scrobble":{"$ref":"#/definitions/CacheScrobbleConfig"},"auth":{"$ref":"#/definitions/CacheAuthConfig"},"regex":{"type":"number","description":"Number of regex functions to cache (LRU)","default":200}},"title":"CacheConfigOptions"},"CacheMetadataConfig":{"$ref":"#/definitions/CacheConfig%3CCacheMetadataProvider%3E","title":"CacheMetadataConfig"},"CacheConfig":{"type":"object","properties":{"provider":{"$ref":"#/definitions/CacheMetadataProvider"},"connection":{"type":"string"}},"required":["provider"],"title":"CacheConfig"},"CacheMetadataProvider":{"$ref":"#/definitions/CacheProvider","title":"CacheMetadataProvider"},"CacheProvider":{"type":["string","boolean"],"enum":["memory","valkey","file",false],"title":"CacheProvider"},"CacheScrobbleConfig":{"$ref":"#/definitions/CacheConfig%3CCacheScrobbleProvider%3E","title":"CacheScrobbleConfig"},"CacheConfig":{"type":"object","properties":{"provider":{"$ref":"#/definitions/CacheScrobbleProvider"},"connection":{"type":"string"}},"required":["provider"],"title":"CacheConfig"},"CacheScrobbleProvider":{"$ref":"#/definitions/CacheProvider","title":"CacheScrobbleProvider"},"CacheAuthConfig":{"$ref":"#/definitions/CacheConfig%3CCacheAuthProvider%3E","title":"CacheAuthConfig"},"CacheConfig":{"type":"object","properties":{"provider":{"$ref":"#/definitions/CacheAuthProvider"},"connection":{"type":"string"}},"required":["provider"],"title":"CacheConfig"},"CacheAuthProvider":{"$ref":"#/definitions/CacheProvider","title":"CacheAuthProvider"},"TransformerCommonConfig":{"type":"object","properties":{"defaults":{"type":"object"},"data":{"type":"object"},"type":{"type":"string"},"name":{"type":"string"},"options":{"$ref":"#/definitions/TransformOptions"}},"required":["type"],"title":"TransformerCommonConfig"},"TransformOptions":{"type":"object","properties":{"failOnFetch":{"type":"boolean"},"throwOnFailure":{"anyOf":[{"type":"boolean"},{"type":"array","items":{"type":"string","enum":["artists","title","albumArtists","album","duration","meta","art"]}}]},"ttl":{"type":"string"}},"title":"TransformOptions"}}} \ No newline at end of file diff --git a/docsite/static/client.json b/docsite/static/client.json index a3e19d98..c0af33ce 100644 --- a/docsite/static/client.json +++ b/docsite/static/client.json @@ -1 +1 @@ -{"$schema":"http://json-schema.org/draft-07/schema#","anyOf":[{"$ref":"#/definitions/MalojaClientConfig"},{"$ref":"#/definitions/LastfmClientConfig"},{"$ref":"#/definitions/LibrefmClientConfig"},{"$ref":"#/definitions/ListenBrainzClientConfig"},{"$ref":"#/definitions/KoitoClientConfig"},{"$ref":"#/definitions/TealClientConfig"},{"$ref":"#/definitions/RockSkyClientConfig"}],"definitions":{"MalojaClientConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this client. Used with sources to restrict where scrobbles are sent.","examples":["MyConfig"]},"data":{"$ref":"#/definitions/MalojaClientData","description":"Specific data required to configure this client"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"options":{"$ref":"#/definitions/CommonClientOptions"},"configureAs":{"type":"string","enum":["client","source"],"description":"Should always be `client` when using Maloja as a client","default":"client","examples":["client"]}},"required":["data","name"],"title":"MalojaClientConfig"},"MalojaClientData":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"url":{"type":"string","description":"URL for maloja server","examples":["http://localhost:42010"]},"apiKey":{"type":"string","description":"API Key for Maloja server","examples":["myApiKey"]}},"required":["apiKey","url"],"title":"MalojaClientData"},"CommonClientOptions":{"type":"object","properties":{"refreshEnabled":{"type":"boolean","description":"Try to get fresh scrobble history from client when tracks to be scrobbled are newer than the last scrobble found in client history","default":true,"examples":[true]},"refreshStaleAfter":{"type":"number","description":"Refresh scrobbled plays from upstream service if last refresh was at least X seconds ago\n\n**In most case this setting does NOT need to be changed.** The default value is sufficient for the majority of use-cases. Increasing this setting may increase upstream service load and slow down scrobbles.\n\nThis setting should only be changed in specific scenarios where MS is handling multiple \"relaying\" client-services (IE lfm -> lz -> lfm) and there is the potential for a client to be out of sync after more than a few seconds.","examples":[60],"default":60},"refreshMinInterval":{"type":"number","description":"Minimum time (milliseconds) required to pass before upstream scrobbles can be refreshed.\n\n**In most case this setting does NOT need to be changed.** This will always be equal to or smaller than `refreshStaleAfter`.","default":5000,"examples":[5000]},"refreshInitialCount":{"type":"number","description":"The number of tracks to retrieve on initial refresh (related to scrobbleBacklogCount). If not specified this is the maximum supported by the client in 1 API call."},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"checkExistingScrobbles":{"type":"boolean","description":"Check client for an existing scrobble at the same recorded time as the \"new\" track to be scrobbled. If an existing scrobble is found this track is not track scrobbled.","default":true,"examples":[true]},"verbose":{"type":"object","properties":{"match":{"$ref":"#/definitions/MatchLoggingOptions"}},"description":"Options used for increasing verbosity of logging in MS (used for debugging)"},"deadLetterRetries":{"type":"number","description":"Number of times MS should automatically retry scrobbles in dead letter queue","default":1,"examples":[1]},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"CommonClientOptions"},"MatchLoggingOptions":{"type":"object","properties":{"onNoMatch":{"type":"boolean","description":"Log to DEBUG when a new track does NOT match an existing scrobble","default":false,"examples":[false]},"onMatch":{"type":"boolean","description":"Log to DEBUG when a new track DOES match an existing scrobble","default":false,"examples":[false]},"confidenceBreakdown":{"type":"boolean","description":"Include confidence breakdowns in track match logging, if applicable","default":false,"examples":[false]}},"description":"Scrobble matching (between new source track and existing client scrobbles) logging options. Used for debugging.","title":"MatchLoggingOptions"},"PlayTransformOptions":{"type":"object","properties":{"log":{"anyOf":[{"type":"boolean"},{"type":"string","enum":["all"]}]},"preCompare":{"$ref":"#/definitions/PlayTransformPartsConfig%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%3E"},"compare":{"type":"object","properties":{"candidate":{"$ref":"#/definitions/PlayTransformPartsConfig%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%3E"},"existing":{"$ref":"#/definitions/PlayTransformPartsConfig%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%3E"}}},"postCompare":{"$ref":"#/definitions/PlayTransformPartsConfig%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%3E"}},"title":"PlayTransformOptions"},"PlayTransformPartsConfig<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm)>":{"anyOf":[{"$ref":"#/definitions/PlayTransformPartsArray%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%2CMaybeStageTyped%3E"},{"$ref":"#/definitions/PlayTransformParts%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%2CMaybeStageTyped%3E"}],"description":"Represents the weakly-defined user config. May be an array of parts or one parts object","title":"PlayTransformPartsConfig<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm)>"},"PlayTransformPartsArray<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm),MaybeStageTyped>":{"type":"array","items":{"$ref":"#/definitions/PlayTransformParts%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%2CMaybeStageTyped%3E"},"title":"PlayTransformPartsArray<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm),MaybeStageTyped>"},"PlayTransformParts<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm),MaybeStageTyped>":{"anyOf":[{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"title":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"artists":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"albumArtists":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"album":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"duration":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"meta":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"onSuccess":{"$ref":"#/definitions/FlowControlTerm"},"onFailure":{"$ref":"#/definitions/FlowControlTerm"},"onSkip":{"$ref":"#/definitions/FlowControlTerm"},"failureReturnPartial":{"type":"boolean"},"type":{"$ref":"#/definitions/StageTypeMetadata"},"name":{"type":"string"},"stageHash":{"type":"string"},"score":{"type":"number"}},"required":["type"]},{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"title":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"artists":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"albumArtists":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"album":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"duration":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"meta":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"onSuccess":{"$ref":"#/definitions/FlowControlTerm"},"onFailure":{"$ref":"#/definitions/FlowControlTerm"},"onSkip":{"$ref":"#/definitions/FlowControlTerm"},"failureReturnPartial":{"type":"boolean"},"type":{"$ref":"#/definitions/StageTypeUser"},"name":{"type":"string"},"stageHash":{"type":"string"}},"required":["type"]},{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"title":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"artists":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"albumArtists":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"album":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"duration":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"meta":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"onSuccess":{"$ref":"#/definitions/FlowControlTerm"},"onFailure":{"$ref":"#/definitions/FlowControlTerm"},"onSkip":{"$ref":"#/definitions/FlowControlTerm"},"failureReturnPartial":{"type":"boolean"},"type":{"type":"string","enum":["native"]},"name":{"type":"string"},"stageHash":{"type":"string"}},"required":["type"]},{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"title":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"artists":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"albumArtists":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"album":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"duration":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"meta":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"onSuccess":{"$ref":"#/definitions/FlowControlTerm"},"onFailure":{"$ref":"#/definitions/FlowControlTerm"},"onSkip":{"$ref":"#/definitions/FlowControlTerm"},"failureReturnPartial":{"type":"boolean"},"name":{"type":"string"}}},{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"title":{},"artists":{},"albumArtists":{},"album":{},"duration":{},"meta":{},"onSuccess":{"$ref":"#/definitions/FlowControlTerm"},"onFailure":{"$ref":"#/definitions/FlowControlTerm"},"onSkip":{"$ref":"#/definitions/FlowControlTerm"},"failureReturnPartial":{"type":"boolean"},"type":{"type":"string"},"name":{"type":"string"},"stageHash":{"type":"string"}},"required":["type"]}],"title":"PlayTransformParts<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm),MaybeStageTyped>"},"WhenConditionsConfig":{"$ref":"#/definitions/WhenConditions%3Cstring%3E","title":"WhenConditionsConfig"},"WhenConditions":{"type":"array","items":{"$ref":"#/definitions/WhenParts%3Cstring%3E"},"title":"WhenConditions"},"WhenParts":{"$ref":"#/definitions/PlayTransformPartsAtomic%3Cstring%3E","title":"WhenParts"},"PlayTransformPartsAtomic":{"type":"object","properties":{"title":{"type":"string"},"artists":{"type":"string"},"albumArtists":{"type":"string"},"album":{"type":"string"},"duration":{"type":"string"},"meta":{"type":"string"}},"title":"PlayTransformPartsAtomic"},"Whennable":{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"}},"title":"Whennable"},"FlowControlTerm":{"type":"string","enum":["continue","stop"],"title":"FlowControlTerm"},"StageTypeMetadata":{"type":"string","enum":["spotify","musicbrainz","native"],"title":"StageTypeMetadata"},"SearchAndReplaceTerm":{"anyOf":[{"type":"string"},{"$ref":"#/definitions/ConditionalSearchAndReplaceTerm"}],"title":"SearchAndReplaceTerm"},"ConditionalSearchAndReplaceTerm":{"$ref":"#/definitions/ConditionalSearchAndReplaceRegExp","title":"ConditionalSearchAndReplaceTerm"},"ConditionalSearchAndReplaceRegExp":{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"search":{"anyOf":[{"type":"string"},{"type":"string","format":"regex"}],"description":"The search value to test for\n\nCan be a normal string (converted to a case-sensitive literal) or a valid regular expression as a string, or an actual RegExp object","examples":[["find this string","/some string*/ig"]]},"replace":{"type":"string","description":"The replacement string/value to use when search is found\n\nThis can be a literal string like `'replace with this`, an empty string to remove the search value (`''`), or a special regex value\n\nSee replacement here for more information: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace"},"test":{"$comment":"(obj: SearchAndReplaceRegExp) => boolean","type":"object","properties":{"namedArgs":{"type":"object","properties":{"obj":{"$ref":"#/definitions/SearchAndReplaceRegExp"}},"required":["obj"],"additionalProperties":false}},"description":"An optional function to execute before running this search-and-replace that decides if it should run at all"}},"required":["replace","search"],"title":"ConditionalSearchAndReplaceRegExp"},"SearchAndReplaceRegExp":{"type":"object","properties":{"search":{"anyOf":[{"type":"string"},{"type":"string","format":"regex"}],"description":"The search value to test for\n\nCan be a normal string (converted to a case-sensitive literal) or a valid regular expression as a string, or an actual RegExp object","examples":[["find this string","/some string*/ig"]]},"replace":{"type":"string","description":"The replacement string/value to use when search is found\n\nThis can be a literal string like `'replace with this`, an empty string to remove the search value (`''`), or a special regex value\n\nSee replacement here for more information: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace"},"test":{"$comment":"(obj: SearchAndReplaceRegExp) => boolean","type":"object","properties":{"namedArgs":{"type":"object","properties":{"obj":{"$ref":"#/definitions/SearchAndReplaceRegExp"}},"required":["obj"],"additionalProperties":false}},"description":"An optional function to execute before running this search-and-replace that decides if it should run at all"}},"required":["search","replace"],"title":"SearchAndReplaceRegExp"},"ExternalMetadataTerm":{"anyOf":[{"type":"boolean"},{"not":{}},{"$ref":"#/definitions/Whennable"}],"title":"ExternalMetadataTerm"},"StageTypeUser":{"type":"string","enum":["user"],"title":"StageTypeUser"},"LastfmClientConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this client. Used with sources to restrict where scrobbles are sent.","examples":["MyConfig"]},"data":{"$ref":"#/definitions/LastfmData","description":"Specific data required to configure this client"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"options":{"$ref":"#/definitions/LastfmClientOptions"},"configureAs":{"type":"string","enum":["client","source"],"description":"Should always be `client` when using LastFM as a client","default":"client","examples":["client"]}},"required":["data","name"],"title":"LastfmClientConfig"},"LastfmData":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"apiKey":{"type":"string","description":"API Key generated from Last.fm/Libre.fm account","examples":["787c921a2a2ab42320831aba0c8f2fc2"]},"secret":{"type":"string","description":"Secret generated from Last.fm/Libre.fm account","examples":["ec42e09d5ae0ee0f0816ca151008412a"]},"session":{"type":"string","description":"Optional session id returned from a completed auth flow"},"redirectUri":{"type":"string","description":"Optional URI to use for callback. Specify this if callback should be different than the default. MUST have \"lastfm/callback\" in the URL somewhere.","default":"http://localhost:9078/lastfm/callback","examples":["http://localhost:9078/lastfm/callback"]}},"required":["apiKey","secret"],"title":"LastfmData"},"LastfmClientOptions":{"type":"object","properties":{"nowPlaying":{"anyOf":[{"type":"boolean"},{"type":"array","items":{"type":"string"}}],"description":"Configure if this Client should report Now Playing from Sources that can scrobble to it\n\n* `true` (default) => Report Now Playing from any eligible Source. \n * If multiple Sources are Playing then reported Play is based on alphabetical order of Source names\n* `false` => Do not report Now Playing\n* `string` list => list of Source `names` that should be allowed to report Now Playing. Order of list determine priority of Play to Report.","default":true},"refreshEnabled":{"type":"boolean","description":"Try to get fresh scrobble history from client when tracks to be scrobbled are newer than the last scrobble found in client history","default":true,"examples":[true]},"refreshStaleAfter":{"type":"number","description":"Refresh scrobbled plays from upstream service if last refresh was at least X seconds ago\n\n**In most case this setting does NOT need to be changed.** The default value is sufficient for the majority of use-cases. Increasing this setting may increase upstream service load and slow down scrobbles.\n\nThis setting should only be changed in specific scenarios where MS is handling multiple \"relaying\" client-services (IE lfm -> lz -> lfm) and there is the potential for a client to be out of sync after more than a few seconds.","examples":[60],"default":60},"refreshMinInterval":{"type":"number","description":"Minimum time (milliseconds) required to pass before upstream scrobbles can be refreshed.\n\n**In most case this setting does NOT need to be changed.** This will always be equal to or smaller than `refreshStaleAfter`.","default":5000,"examples":[5000]},"refreshInitialCount":{"type":"number","description":"The number of tracks to retrieve on initial refresh (related to scrobbleBacklogCount). If not specified this is the maximum supported by the client in 1 API call."},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"checkExistingScrobbles":{"type":"boolean","description":"Check client for an existing scrobble at the same recorded time as the \"new\" track to be scrobbled. If an existing scrobble is found this track is not track scrobbled.","default":true,"examples":[true]},"verbose":{"type":"object","properties":{"match":{"$ref":"#/definitions/MatchLoggingOptions"}},"description":"Options used for increasing verbosity of logging in MS (used for debugging)"},"deadLetterRetries":{"type":"number","description":"Number of times MS should automatically retry scrobbles in dead letter queue","default":1,"examples":[1]},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"LastfmClientOptions"},"LibrefmClientConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this client. Used with sources to restrict where scrobbles are sent.","examples":["MyConfig"]},"data":{"$ref":"#/definitions/LibrefmData","description":"Specific data required to configure this client"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"options":{"$ref":"#/definitions/LibrefmClientOptions"},"configureAs":{"type":"string","enum":["client","source"],"description":"Should always be `client` when using Librefm as a client","default":"client","examples":["client"]}},"required":["data","name"],"title":"LibrefmClientConfig"},"LibrefmData":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"apiKey":{"type":"string","description":"Optional Secret for Libre.fm account\n\nThis can be anything, or it will be generated by multi-scrobbler","examples":["anyValue"]},"secret":{"type":"string","description":"Optional Secret for Libre.fm account\n\nThis can be anything, or it will be generated by multi-scrobbler","examples":["anyValue"]},"session":{"type":"string","description":"Optional session id returned from a completed auth flow"},"path":{"type":"string"},"urlBase":{"type":"string","description":"(Optional) The host and path prefix for your Libre.fm instance","default":"https://libre.fm/2.0/"},"redirectUri":{"type":"string","description":"Optional URI to use for callback. Specify this if callback should be different than the default. MUST have \"librefm/callback\" in the URL somewhere.","default":"http://localhost:9078/librefm/callback","examples":["http://localhost:9078/librefm/callback"]}},"title":"LibrefmData"},"LibrefmClientOptions":{"type":"object","properties":{"nowPlaying":{"anyOf":[{"type":"boolean"},{"type":"array","items":{"type":"string"}}],"description":"Configure if this Client should report Now Playing from Sources that can scrobble to it\n\n* `true` (default) => Report Now Playing from any eligible Source. \n * If multiple Sources are Playing then reported Play is based on alphabetical order of Source names\n* `false` => Do not report Now Playing\n* `string` list => list of Source `names` that should be allowed to report Now Playing. Order of list determine priority of Play to Report.","default":true},"refreshEnabled":{"type":"boolean","description":"Try to get fresh scrobble history from client when tracks to be scrobbled are newer than the last scrobble found in client history","default":true,"examples":[true]},"refreshStaleAfter":{"type":"number","description":"Refresh scrobbled plays from upstream service if last refresh was at least X seconds ago\n\n**In most case this setting does NOT need to be changed.** The default value is sufficient for the majority of use-cases. Increasing this setting may increase upstream service load and slow down scrobbles.\n\nThis setting should only be changed in specific scenarios where MS is handling multiple \"relaying\" client-services (IE lfm -> lz -> lfm) and there is the potential for a client to be out of sync after more than a few seconds.","examples":[60],"default":60},"refreshMinInterval":{"type":"number","description":"Minimum time (milliseconds) required to pass before upstream scrobbles can be refreshed.\n\n**In most case this setting does NOT need to be changed.** This will always be equal to or smaller than `refreshStaleAfter`.","default":5000,"examples":[5000]},"refreshInitialCount":{"type":"number","description":"The number of tracks to retrieve on initial refresh (related to scrobbleBacklogCount). If not specified this is the maximum supported by the client in 1 API call."},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"checkExistingScrobbles":{"type":"boolean","description":"Check client for an existing scrobble at the same recorded time as the \"new\" track to be scrobbled. If an existing scrobble is found this track is not track scrobbled.","default":true,"examples":[true]},"verbose":{"type":"object","properties":{"match":{"$ref":"#/definitions/MatchLoggingOptions"}},"description":"Options used for increasing verbosity of logging in MS (used for debugging)"},"deadLetterRetries":{"type":"number","description":"Number of times MS should automatically retry scrobbles in dead letter queue","default":1,"examples":[1]},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"LibrefmClientOptions"},"ListenBrainzClientConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this client. Used with sources to restrict where scrobbles are sent.","examples":["MyConfig"]},"data":{"$ref":"#/definitions/ListenBrainzClientData","description":"Specific data required to configure this client"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"options":{"$ref":"#/definitions/CommonClientOptions"},"configureAs":{"type":"string","enum":["client","source"],"description":"Should always be `client` when using Listenbrainz as a client","default":"client","examples":["client"]}},"required":["data","name"],"title":"ListenBrainzClientConfig"},"ListenBrainzClientData":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"url":{"type":"string","description":"URL for the ListenBrainz server, if not using the default","examples":["https://api.listenbrainz.org/"],"default":"https://api.listenbrainz.org/"},"token":{"type":"string","description":"User token for the user to scrobble for","examples":["6794186bf-1157-4de6-80e5-uvb411f3ea2b"]},"username":{"type":"string","description":"Username of the user to scrobble for"}},"required":["token","username"],"title":"ListenBrainzClientData"},"KoitoClientConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this client. Used with sources to restrict where scrobbles are sent.","examples":["MyConfig"]},"data":{"$ref":"#/definitions/KoitoClientData","description":"Specific data required to configure this client"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"options":{"$ref":"#/definitions/CommonClientOptions"},"configureAs":{"type":"string","enum":["client","source"],"description":"Should always be `client` when using Koito as a client","default":"client","examples":["client"]}},"required":["data","name"],"title":"KoitoClientConfig"},"KoitoClientData":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"url":{"type":"string","description":"URL for the Koito server","examples":["http://192.168.0.100:4110"]},"token":{"type":"string","description":"User token for the user to scrobble for","examples":["pM195xPV98CDpk0QW47FIIOR8AKATAX5DblBF-Jq0t1MbbKL"]},"username":{"type":"string","description":"Username of the user to scrobble for"}},"required":["token","url","username"],"title":"KoitoClientData"},"TealClientConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this client. Used with sources to restrict where scrobbles are sent.","examples":["MyConfig"]},"data":{"$ref":"#/definitions/TealClientData","description":"Specific data required to configure this client"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"options":{"$ref":"#/definitions/TealClientOptions"},"configureAs":{"type":"string","enum":["client","source"],"description":"Should always be `client` when using Tealfm as a client","default":"client","examples":["client"]}},"required":["data","name"],"title":"TealClientConfig"},"TealClientData":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"baseUri":{"type":"string","description":"The base URI of the Multi-Scrobbler to use for ATProto OAuth\n\nOnly include this if you want to use OAuth. The URI must be a non-IP/non-local domain using https: protocol."},"identifier":{"type":"string","description":"Identify the account to login as\n\n* For **App Password** Auth - your email\n* For **Oauth** - your handle minus the @"},"appPassword":{"type":"string","description":"The [App Password](https://atproto.com/specs/xrpc#app-passwords) you created for your account\n\nThis is created under https://bsky.app/settings/app-passwords\n\n**Use this if you are self-hosting Multi-Scrobbler on localhost or accessed like http://IP:PORT**"}},"required":["identifier"],"title":"TealClientData"},"TealClientOptions":{"type":"object","properties":{"refreshEnabled":{"type":"boolean","description":"Try to get fresh scrobble history from client when tracks to be scrobbled are newer than the last scrobble found in client history","default":true,"examples":[true]},"refreshStaleAfter":{"type":"number","description":"Refresh scrobbled plays from upstream service if last refresh was at least X seconds ago\n\n**In most case this setting does NOT need to be changed.** The default value is sufficient for the majority of use-cases. Increasing this setting may increase upstream service load and slow down scrobbles.\n\nThis setting should only be changed in specific scenarios where MS is handling multiple \"relaying\" client-services (IE lfm -> lz -> lfm) and there is the potential for a client to be out of sync after more than a few seconds.","examples":[60],"default":60},"refreshMinInterval":{"type":"number","description":"Minimum time (milliseconds) required to pass before upstream scrobbles can be refreshed.\n\n**In most case this setting does NOT need to be changed.** This will always be equal to or smaller than `refreshStaleAfter`.","default":5000,"examples":[5000]},"refreshInitialCount":{"type":"number","description":"The number of tracks to retrieve on initial refresh (related to scrobbleBacklogCount). If not specified this is the maximum supported by the client in 1 API call."},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"checkExistingScrobbles":{"type":"boolean","description":"Check client for an existing scrobble at the same recorded time as the \"new\" track to be scrobbled. If an existing scrobble is found this track is not track scrobbled.","default":true,"examples":[true]},"verbose":{"type":"object","properties":{"match":{"$ref":"#/definitions/MatchLoggingOptions"}},"description":"Options used for increasing verbosity of logging in MS (used for debugging)"},"deadLetterRetries":{"type":"number","description":"Number of times MS should automatically retry scrobbles in dead letter queue","default":1,"examples":[1]},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"TealClientOptions"},"RockSkyClientConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this client. Used with sources to restrict where scrobbles are sent.","examples":["MyConfig"]},"data":{"$ref":"#/definitions/RockSkyClientData","description":"Specific data required to configure this client"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"options":{"$ref":"#/definitions/RockSkyClientOptions"},"configureAs":{"type":"string","enum":["client","source"],"description":"Should always be `client` when using RockSky as a client","default":"client","examples":["client"]}},"required":["data","name"],"title":"RockSkyClientConfig"},"RockSkyClientData":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"key":{"type":"string","description":"API Key generated from [API Applications](https://docs.rocksky.app/migrating-from-listenbrainz-to-rocksky-1040189m0) in Rocksky for your account","examples":["6794186bf-1157-4de6-80e5-uvb411f3ea2b"]},"handle":{"type":"string","description":"The **fully-qualified** handle for your ATPRoto/Bluesky account, like:\n\n* alice.bsky.social\n* foxxmd.com\n* mysuer.blacksky.app"}},"required":["handle","key"],"title":"RockSkyClientData"},"RockSkyClientOptions":{"type":"object","properties":{"nowPlaying":{"anyOf":[{"type":"boolean"},{"type":"array","items":{"type":"string"}}],"description":"Configure if this Client should report Now Playing from Sources that can scrobble to it\n\n* `true` (default) => Report Now Playing from any eligible Source. \n * If multiple Sources are Playing then reported Play is based on alphabetical order of Source names\n* `false` => Do not report Now Playing\n* `string` list => list of Source `names` that should be allowed to report Now Playing. Order of list determine priority of Play to Report.","default":true},"refreshEnabled":{"type":"boolean","description":"Try to get fresh scrobble history from client when tracks to be scrobbled are newer than the last scrobble found in client history","default":true,"examples":[true]},"refreshStaleAfter":{"type":"number","description":"Refresh scrobbled plays from upstream service if last refresh was at least X seconds ago\n\n**In most case this setting does NOT need to be changed.** The default value is sufficient for the majority of use-cases. Increasing this setting may increase upstream service load and slow down scrobbles.\n\nThis setting should only be changed in specific scenarios where MS is handling multiple \"relaying\" client-services (IE lfm -> lz -> lfm) and there is the potential for a client to be out of sync after more than a few seconds.","examples":[60],"default":60},"refreshMinInterval":{"type":"number","description":"Minimum time (milliseconds) required to pass before upstream scrobbles can be refreshed.\n\n**In most case this setting does NOT need to be changed.** This will always be equal to or smaller than `refreshStaleAfter`.","default":5000,"examples":[5000]},"refreshInitialCount":{"type":"number","description":"The number of tracks to retrieve on initial refresh (related to scrobbleBacklogCount). If not specified this is the maximum supported by the client in 1 API call."},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"checkExistingScrobbles":{"type":"boolean","description":"Check client for an existing scrobble at the same recorded time as the \"new\" track to be scrobbled. If an existing scrobble is found this track is not track scrobbled.","default":true,"examples":[true]},"verbose":{"type":"object","properties":{"match":{"$ref":"#/definitions/MatchLoggingOptions"}},"description":"Options used for increasing verbosity of logging in MS (used for debugging)"},"deadLetterRetries":{"type":"number","description":"Number of times MS should automatically retry scrobbles in dead letter queue","default":1,"examples":[1]},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"},"audioScrobblerUrl":{"type":"string","description":"URL for the Rocksky *Listenbrainz* endpoint, if not using the default","examples":["https://audioscrobbler.rocksky.app"],"default":"https://audioscrobbler.rocksky.app"},"apiUrl":{"type":"string","description":"URL for the Rocksky *API* endpoint, if not using the default","examples":["https://api.rocksky.app"],"default":"https://api.rocksky.app"}},"title":"RockSkyClientOptions"}}} \ No newline at end of file +{"$schema":"http://json-schema.org/draft-07/schema#","anyOf":[{"$ref":"#/definitions/MalojaClientConfig"},{"$ref":"#/definitions/LastfmClientConfig"},{"$ref":"#/definitions/LibrefmClientConfig"},{"$ref":"#/definitions/ListenBrainzClientConfig"},{"$ref":"#/definitions/KoitoClientConfig"},{"$ref":"#/definitions/TealClientConfig"},{"$ref":"#/definitions/RockSkyClientConfig"},{"$ref":"#/definitions/DiscordClientConfig"}],"definitions":{"MalojaClientConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this client. Used with sources to restrict where scrobbles are sent.","examples":["MyConfig"]},"data":{"$ref":"#/definitions/MalojaClientData","description":"Specific data required to configure this client"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"options":{"$ref":"#/definitions/CommonClientOptions"},"configureAs":{"type":"string","enum":["client","source"],"description":"Should always be `client` when using Maloja as a client","default":"client","examples":["client"]}},"required":["data","name"],"title":"MalojaClientConfig"},"MalojaClientData":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"url":{"type":"string","description":"URL for maloja server","examples":["http://localhost:42010"]},"apiKey":{"type":"string","description":"API Key for Maloja server","examples":["myApiKey"]}},"required":["apiKey","url"],"title":"MalojaClientData"},"CommonClientOptions":{"type":"object","properties":{"refreshEnabled":{"type":"boolean","description":"Try to get fresh scrobble history from client when tracks to be scrobbled are newer than the last scrobble found in client history","default":true,"examples":[true]},"refreshStaleAfter":{"type":"number","description":"Refresh scrobbled plays from upstream service if last refresh was at least X seconds ago\n\n**In most case this setting does NOT need to be changed.** The default value is sufficient for the majority of use-cases. Increasing this setting may increase upstream service load and slow down scrobbles.\n\nThis setting should only be changed in specific scenarios where MS is handling multiple \"relaying\" client-services (IE lfm -> lz -> lfm) and there is the potential for a client to be out of sync after more than a few seconds.","examples":[60],"default":60},"refreshMinInterval":{"type":"number","description":"Minimum time (milliseconds) required to pass before upstream scrobbles can be refreshed.\n\n**In most case this setting does NOT need to be changed.** This will always be equal to or smaller than `refreshStaleAfter`.","default":5000,"examples":[5000]},"refreshInitialCount":{"type":"number","description":"The number of tracks to retrieve on initial refresh (related to scrobbleBacklogCount). If not specified this is the maximum supported by the client in 1 API call."},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"checkExistingScrobbles":{"type":"boolean","description":"Check client for an existing scrobble at the same recorded time as the \"new\" track to be scrobbled. If an existing scrobble is found this track is not track scrobbled.","default":true,"examples":[true]},"verbose":{"type":"object","properties":{"match":{"$ref":"#/definitions/MatchLoggingOptions"}},"description":"Options used for increasing verbosity of logging in MS (used for debugging)"},"deadLetterRetries":{"type":"number","description":"Number of times MS should automatically retry scrobbles in dead letter queue","default":1,"examples":[1]},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"CommonClientOptions"},"MatchLoggingOptions":{"type":"object","properties":{"onNoMatch":{"type":"boolean","description":"Log to DEBUG when a new track does NOT match an existing scrobble","default":false,"examples":[false]},"onMatch":{"type":"boolean","description":"Log to DEBUG when a new track DOES match an existing scrobble","default":false,"examples":[false]},"confidenceBreakdown":{"type":"boolean","description":"Include confidence breakdowns in track match logging, if applicable","default":false,"examples":[false]}},"description":"Scrobble matching (between new source track and existing client scrobbles) logging options. Used for debugging.","title":"MatchLoggingOptions"},"PlayTransformOptions":{"type":"object","properties":{"log":{"anyOf":[{"type":"boolean"},{"type":"string","enum":["all"]}]},"preCompare":{"$ref":"#/definitions/PlayTransformPartsConfig%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%3E"},"compare":{"type":"object","properties":{"candidate":{"$ref":"#/definitions/PlayTransformPartsConfig%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%3E"},"existing":{"$ref":"#/definitions/PlayTransformPartsConfig%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%3E"}}},"postCompare":{"$ref":"#/definitions/PlayTransformPartsConfig%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%3E"}},"title":"PlayTransformOptions"},"PlayTransformPartsConfig<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm)>":{"anyOf":[{"$ref":"#/definitions/PlayTransformPartsArray%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%2CMaybeStageTyped%3E"},{"$ref":"#/definitions/PlayTransformParts%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%2CMaybeStageTyped%3E"}],"description":"Represents the weakly-defined user config. May be an array of parts or one parts object","title":"PlayTransformPartsConfig<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm)>"},"PlayTransformPartsArray<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm),MaybeStageTyped>":{"type":"array","items":{"$ref":"#/definitions/PlayTransformParts%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%2CMaybeStageTyped%3E"},"title":"PlayTransformPartsArray<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm),MaybeStageTyped>"},"PlayTransformParts<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm),MaybeStageTyped>":{"anyOf":[{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"title":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"artists":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"albumArtists":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"album":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"duration":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"meta":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"onSuccess":{"$ref":"#/definitions/FlowControlTerm"},"onFailure":{"$ref":"#/definitions/FlowControlTerm"},"onSkip":{"$ref":"#/definitions/FlowControlTerm"},"failureReturnPartial":{"type":"boolean"},"type":{"$ref":"#/definitions/StageTypeMetadata"},"name":{"type":"string"},"stageHash":{"type":"string"},"score":{"type":"number"}},"required":["type"]},{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"title":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"artists":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"albumArtists":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"album":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"duration":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"meta":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"onSuccess":{"$ref":"#/definitions/FlowControlTerm"},"onFailure":{"$ref":"#/definitions/FlowControlTerm"},"onSkip":{"$ref":"#/definitions/FlowControlTerm"},"failureReturnPartial":{"type":"boolean"},"type":{"$ref":"#/definitions/StageTypeUser"},"name":{"type":"string"},"stageHash":{"type":"string"}},"required":["type"]},{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"title":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"artists":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"albumArtists":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"album":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"duration":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"meta":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"onSuccess":{"$ref":"#/definitions/FlowControlTerm"},"onFailure":{"$ref":"#/definitions/FlowControlTerm"},"onSkip":{"$ref":"#/definitions/FlowControlTerm"},"failureReturnPartial":{"type":"boolean"},"type":{"type":"string","enum":["native"]},"name":{"type":"string"},"stageHash":{"type":"string"}},"required":["type"]},{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"title":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"artists":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"albumArtists":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"album":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"duration":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"meta":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"onSuccess":{"$ref":"#/definitions/FlowControlTerm"},"onFailure":{"$ref":"#/definitions/FlowControlTerm"},"onSkip":{"$ref":"#/definitions/FlowControlTerm"},"failureReturnPartial":{"type":"boolean"},"name":{"type":"string"}}},{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"title":{},"artists":{},"albumArtists":{},"album":{},"duration":{},"meta":{},"onSuccess":{"$ref":"#/definitions/FlowControlTerm"},"onFailure":{"$ref":"#/definitions/FlowControlTerm"},"onSkip":{"$ref":"#/definitions/FlowControlTerm"},"failureReturnPartial":{"type":"boolean"},"type":{"type":"string"},"name":{"type":"string"},"stageHash":{"type":"string"}},"required":["type"]}],"title":"PlayTransformParts<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm),MaybeStageTyped>"},"WhenConditionsConfig":{"$ref":"#/definitions/WhenConditions%3Cstring%3E","title":"WhenConditionsConfig"},"WhenConditions":{"type":"array","items":{"$ref":"#/definitions/WhenParts%3Cstring%3E"},"title":"WhenConditions"},"WhenParts":{"$ref":"#/definitions/PlayTransformPartsAtomic%3Cstring%3E","title":"WhenParts"},"PlayTransformPartsAtomic":{"type":"object","properties":{"title":{"type":"string"},"artists":{"type":"string"},"albumArtists":{"type":"string"},"album":{"type":"string"},"duration":{"type":"string"},"meta":{"type":"string"}},"title":"PlayTransformPartsAtomic"},"Whennable":{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"}},"title":"Whennable"},"FlowControlTerm":{"type":"string","enum":["continue","stop"],"title":"FlowControlTerm"},"StageTypeMetadata":{"type":"string","enum":["spotify","musicbrainz","native"],"title":"StageTypeMetadata"},"SearchAndReplaceTerm":{"anyOf":[{"type":"string"},{"$ref":"#/definitions/ConditionalSearchAndReplaceTerm"}],"title":"SearchAndReplaceTerm"},"ConditionalSearchAndReplaceTerm":{"$ref":"#/definitions/ConditionalSearchAndReplaceRegExp","title":"ConditionalSearchAndReplaceTerm"},"ConditionalSearchAndReplaceRegExp":{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"search":{"anyOf":[{"type":"string"},{"type":"string","format":"regex"}],"description":"The search value to test for\n\nCan be a normal string (converted to a case-sensitive literal) or a valid regular expression as a string, or an actual RegExp object","examples":[["find this string","/some string*/ig"]]},"replace":{"type":"string","description":"The replacement string/value to use when search is found\n\nThis can be a literal string like `'replace with this`, an empty string to remove the search value (`''`), or a special regex value\n\nSee replacement here for more information: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace"},"test":{"$comment":"(obj: SearchAndReplaceRegExp) => boolean","type":"object","properties":{"namedArgs":{"type":"object","properties":{"obj":{"$ref":"#/definitions/SearchAndReplaceRegExp"}},"required":["obj"],"additionalProperties":false}},"description":"An optional function to execute before running this search-and-replace that decides if it should run at all"}},"required":["replace","search"],"title":"ConditionalSearchAndReplaceRegExp"},"SearchAndReplaceRegExp":{"type":"object","properties":{"search":{"anyOf":[{"type":"string"},{"type":"string","format":"regex"}],"description":"The search value to test for\n\nCan be a normal string (converted to a case-sensitive literal) or a valid regular expression as a string, or an actual RegExp object","examples":[["find this string","/some string*/ig"]]},"replace":{"type":"string","description":"The replacement string/value to use when search is found\n\nThis can be a literal string like `'replace with this`, an empty string to remove the search value (`''`), or a special regex value\n\nSee replacement here for more information: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace"},"test":{"$comment":"(obj: SearchAndReplaceRegExp) => boolean","type":"object","properties":{"namedArgs":{"type":"object","properties":{"obj":{"$ref":"#/definitions/SearchAndReplaceRegExp"}},"required":["obj"],"additionalProperties":false}},"description":"An optional function to execute before running this search-and-replace that decides if it should run at all"}},"required":["search","replace"],"title":"SearchAndReplaceRegExp"},"ExternalMetadataTerm":{"anyOf":[{"type":"boolean"},{"not":{}},{"$ref":"#/definitions/Whennable"}],"title":"ExternalMetadataTerm"},"StageTypeUser":{"type":"string","enum":["user"],"title":"StageTypeUser"},"LastfmClientConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this client. Used with sources to restrict where scrobbles are sent.","examples":["MyConfig"]},"data":{"$ref":"#/definitions/LastfmData","description":"Specific data required to configure this client"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"options":{"$ref":"#/definitions/LastfmClientOptions"},"configureAs":{"type":"string","enum":["client","source"],"description":"Should always be `client` when using LastFM as a client","default":"client","examples":["client"]}},"required":["data","name"],"title":"LastfmClientConfig"},"LastfmData":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"apiKey":{"type":"string","description":"API Key generated from Last.fm/Libre.fm account","examples":["787c921a2a2ab42320831aba0c8f2fc2"]},"secret":{"type":"string","description":"Secret generated from Last.fm/Libre.fm account","examples":["ec42e09d5ae0ee0f0816ca151008412a"]},"session":{"type":"string","description":"Optional session id returned from a completed auth flow"},"redirectUri":{"type":"string","description":"Optional URI to use for callback. Specify this if callback should be different than the default. MUST have \"lastfm/callback\" in the URL somewhere.","default":"http://localhost:9078/lastfm/callback","examples":["http://localhost:9078/lastfm/callback"]}},"required":["apiKey","secret"],"title":"LastfmData"},"LastfmClientOptions":{"type":"object","properties":{"nowPlaying":{"anyOf":[{"type":"boolean"},{"type":"array","items":{"type":"string"}}],"description":"Configure if this Client should report Now Playing from Sources that can scrobble to it\n\n* `true` (default) => Report Now Playing from any eligible Source. \n * If multiple Sources are Playing then reported Play is based on alphabetical order of Source names\n* `false` => Do not report Now Playing\n* `string` list => list of Source `names` that should be allowed to report Now Playing. Order of list determine priority of Play to Report.","default":true},"refreshEnabled":{"type":"boolean","description":"Try to get fresh scrobble history from client when tracks to be scrobbled are newer than the last scrobble found in client history","default":true,"examples":[true]},"refreshStaleAfter":{"type":"number","description":"Refresh scrobbled plays from upstream service if last refresh was at least X seconds ago\n\n**In most case this setting does NOT need to be changed.** The default value is sufficient for the majority of use-cases. Increasing this setting may increase upstream service load and slow down scrobbles.\n\nThis setting should only be changed in specific scenarios where MS is handling multiple \"relaying\" client-services (IE lfm -> lz -> lfm) and there is the potential for a client to be out of sync after more than a few seconds.","examples":[60],"default":60},"refreshMinInterval":{"type":"number","description":"Minimum time (milliseconds) required to pass before upstream scrobbles can be refreshed.\n\n**In most case this setting does NOT need to be changed.** This will always be equal to or smaller than `refreshStaleAfter`.","default":5000,"examples":[5000]},"refreshInitialCount":{"type":"number","description":"The number of tracks to retrieve on initial refresh (related to scrobbleBacklogCount). If not specified this is the maximum supported by the client in 1 API call."},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"checkExistingScrobbles":{"type":"boolean","description":"Check client for an existing scrobble at the same recorded time as the \"new\" track to be scrobbled. If an existing scrobble is found this track is not track scrobbled.","default":true,"examples":[true]},"verbose":{"type":"object","properties":{"match":{"$ref":"#/definitions/MatchLoggingOptions"}},"description":"Options used for increasing verbosity of logging in MS (used for debugging)"},"deadLetterRetries":{"type":"number","description":"Number of times MS should automatically retry scrobbles in dead letter queue","default":1,"examples":[1]},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"LastfmClientOptions"},"LibrefmClientConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this client. Used with sources to restrict where scrobbles are sent.","examples":["MyConfig"]},"data":{"$ref":"#/definitions/LibrefmData","description":"Specific data required to configure this client"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"options":{"$ref":"#/definitions/LibrefmClientOptions"},"configureAs":{"type":"string","enum":["client","source"],"description":"Should always be `client` when using Librefm as a client","default":"client","examples":["client"]}},"required":["data","name"],"title":"LibrefmClientConfig"},"LibrefmData":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"apiKey":{"type":"string","description":"Optional Secret for Libre.fm account\n\nThis can be anything, or it will be generated by multi-scrobbler","examples":["anyValue"]},"secret":{"type":"string","description":"Optional Secret for Libre.fm account\n\nThis can be anything, or it will be generated by multi-scrobbler","examples":["anyValue"]},"session":{"type":"string","description":"Optional session id returned from a completed auth flow"},"path":{"type":"string"},"urlBase":{"type":"string","description":"(Optional) The host and path prefix for your Libre.fm instance","default":"https://libre.fm/2.0/"},"redirectUri":{"type":"string","description":"Optional URI to use for callback. Specify this if callback should be different than the default. MUST have \"librefm/callback\" in the URL somewhere.","default":"http://localhost:9078/librefm/callback","examples":["http://localhost:9078/librefm/callback"]}},"title":"LibrefmData"},"LibrefmClientOptions":{"type":"object","properties":{"nowPlaying":{"anyOf":[{"type":"boolean"},{"type":"array","items":{"type":"string"}}],"description":"Configure if this Client should report Now Playing from Sources that can scrobble to it\n\n* `true` (default) => Report Now Playing from any eligible Source. \n * If multiple Sources are Playing then reported Play is based on alphabetical order of Source names\n* `false` => Do not report Now Playing\n* `string` list => list of Source `names` that should be allowed to report Now Playing. Order of list determine priority of Play to Report.","default":true},"refreshEnabled":{"type":"boolean","description":"Try to get fresh scrobble history from client when tracks to be scrobbled are newer than the last scrobble found in client history","default":true,"examples":[true]},"refreshStaleAfter":{"type":"number","description":"Refresh scrobbled plays from upstream service if last refresh was at least X seconds ago\n\n**In most case this setting does NOT need to be changed.** The default value is sufficient for the majority of use-cases. Increasing this setting may increase upstream service load and slow down scrobbles.\n\nThis setting should only be changed in specific scenarios where MS is handling multiple \"relaying\" client-services (IE lfm -> lz -> lfm) and there is the potential for a client to be out of sync after more than a few seconds.","examples":[60],"default":60},"refreshMinInterval":{"type":"number","description":"Minimum time (milliseconds) required to pass before upstream scrobbles can be refreshed.\n\n**In most case this setting does NOT need to be changed.** This will always be equal to or smaller than `refreshStaleAfter`.","default":5000,"examples":[5000]},"refreshInitialCount":{"type":"number","description":"The number of tracks to retrieve on initial refresh (related to scrobbleBacklogCount). If not specified this is the maximum supported by the client in 1 API call."},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"checkExistingScrobbles":{"type":"boolean","description":"Check client for an existing scrobble at the same recorded time as the \"new\" track to be scrobbled. If an existing scrobble is found this track is not track scrobbled.","default":true,"examples":[true]},"verbose":{"type":"object","properties":{"match":{"$ref":"#/definitions/MatchLoggingOptions"}},"description":"Options used for increasing verbosity of logging in MS (used for debugging)"},"deadLetterRetries":{"type":"number","description":"Number of times MS should automatically retry scrobbles in dead letter queue","default":1,"examples":[1]},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"LibrefmClientOptions"},"ListenBrainzClientConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this client. Used with sources to restrict where scrobbles are sent.","examples":["MyConfig"]},"data":{"$ref":"#/definitions/ListenBrainzClientData","description":"Specific data required to configure this client"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"options":{"$ref":"#/definitions/CommonClientOptions"},"configureAs":{"type":"string","enum":["client","source"],"description":"Should always be `client` when using Listenbrainz as a client","default":"client","examples":["client"]}},"required":["data","name"],"title":"ListenBrainzClientConfig"},"ListenBrainzClientData":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"url":{"type":"string","description":"URL for the ListenBrainz server, if not using the default","examples":["https://api.listenbrainz.org/"],"default":"https://api.listenbrainz.org/"},"token":{"type":"string","description":"User token for the user to scrobble for","examples":["6794186bf-1157-4de6-80e5-uvb411f3ea2b"]},"username":{"type":"string","description":"Username of the user to scrobble for"}},"required":["token","username"],"title":"ListenBrainzClientData"},"KoitoClientConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this client. Used with sources to restrict where scrobbles are sent.","examples":["MyConfig"]},"data":{"$ref":"#/definitions/KoitoClientData","description":"Specific data required to configure this client"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"options":{"$ref":"#/definitions/CommonClientOptions"},"configureAs":{"type":"string","enum":["client","source"],"description":"Should always be `client` when using Koito as a client","default":"client","examples":["client"]}},"required":["data","name"],"title":"KoitoClientConfig"},"KoitoClientData":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"url":{"type":"string","description":"URL for the Koito server","examples":["http://192.168.0.100:4110"]},"token":{"type":"string","description":"User token for the user to scrobble for","examples":["pM195xPV98CDpk0QW47FIIOR8AKATAX5DblBF-Jq0t1MbbKL"]},"username":{"type":"string","description":"Username of the user to scrobble for"}},"required":["token","url","username"],"title":"KoitoClientData"},"TealClientConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this client. Used with sources to restrict where scrobbles are sent.","examples":["MyConfig"]},"data":{"$ref":"#/definitions/TealClientData","description":"Specific data required to configure this client"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"options":{"$ref":"#/definitions/TealClientOptions"},"configureAs":{"type":"string","enum":["client","source"],"description":"Should always be `client` when using Tealfm as a client","default":"client","examples":["client"]}},"required":["data","name"],"title":"TealClientConfig"},"TealClientData":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"baseUri":{"type":"string","description":"The base URI of the Multi-Scrobbler to use for ATProto OAuth\n\nOnly include this if you want to use OAuth. The URI must be a non-IP/non-local domain using https: protocol."},"identifier":{"type":"string","description":"Identify the account to login as\n\n* For **App Password** Auth - your email\n* For **Oauth** - your handle minus the @"},"appPassword":{"type":"string","description":"The [App Password](https://atproto.com/specs/xrpc#app-passwords) you created for your account\n\nThis is created under https://bsky.app/settings/app-passwords\n\n**Use this if you are self-hosting Multi-Scrobbler on localhost or accessed like http://IP:PORT**"}},"required":["identifier"],"title":"TealClientData"},"TealClientOptions":{"type":"object","properties":{"refreshEnabled":{"type":"boolean","description":"Try to get fresh scrobble history from client when tracks to be scrobbled are newer than the last scrobble found in client history","default":true,"examples":[true]},"refreshStaleAfter":{"type":"number","description":"Refresh scrobbled plays from upstream service if last refresh was at least X seconds ago\n\n**In most case this setting does NOT need to be changed.** The default value is sufficient for the majority of use-cases. Increasing this setting may increase upstream service load and slow down scrobbles.\n\nThis setting should only be changed in specific scenarios where MS is handling multiple \"relaying\" client-services (IE lfm -> lz -> lfm) and there is the potential for a client to be out of sync after more than a few seconds.","examples":[60],"default":60},"refreshMinInterval":{"type":"number","description":"Minimum time (milliseconds) required to pass before upstream scrobbles can be refreshed.\n\n**In most case this setting does NOT need to be changed.** This will always be equal to or smaller than `refreshStaleAfter`.","default":5000,"examples":[5000]},"refreshInitialCount":{"type":"number","description":"The number of tracks to retrieve on initial refresh (related to scrobbleBacklogCount). If not specified this is the maximum supported by the client in 1 API call."},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"checkExistingScrobbles":{"type":"boolean","description":"Check client for an existing scrobble at the same recorded time as the \"new\" track to be scrobbled. If an existing scrobble is found this track is not track scrobbled.","default":true,"examples":[true]},"verbose":{"type":"object","properties":{"match":{"$ref":"#/definitions/MatchLoggingOptions"}},"description":"Options used for increasing verbosity of logging in MS (used for debugging)"},"deadLetterRetries":{"type":"number","description":"Number of times MS should automatically retry scrobbles in dead letter queue","default":1,"examples":[1]},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"TealClientOptions"},"RockSkyClientConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this client. Used with sources to restrict where scrobbles are sent.","examples":["MyConfig"]},"data":{"$ref":"#/definitions/RockSkyClientData","description":"Specific data required to configure this client"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"options":{"$ref":"#/definitions/RockSkyClientOptions"},"configureAs":{"type":"string","enum":["client","source"],"description":"Should always be `client` when using RockSky as a client","default":"client","examples":["client"]}},"required":["data","name"],"title":"RockSkyClientConfig"},"RockSkyClientData":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"key":{"type":"string","description":"API Key generated from [API Applications](https://docs.rocksky.app/migrating-from-listenbrainz-to-rocksky-1040189m0) in Rocksky for your account","examples":["6794186bf-1157-4de6-80e5-uvb411f3ea2b"]},"handle":{"type":"string","description":"The **fully-qualified** handle for your ATPRoto/Bluesky account, like:\n\n* alice.bsky.social\n* foxxmd.com\n* mysuer.blacksky.app"}},"required":["handle","key"],"title":"RockSkyClientData"},"RockSkyClientOptions":{"type":"object","properties":{"nowPlaying":{"anyOf":[{"type":"boolean"},{"type":"array","items":{"type":"string"}}],"description":"Configure if this Client should report Now Playing from Sources that can scrobble to it\n\n* `true` (default) => Report Now Playing from any eligible Source. \n * If multiple Sources are Playing then reported Play is based on alphabetical order of Source names\n* `false` => Do not report Now Playing\n* `string` list => list of Source `names` that should be allowed to report Now Playing. Order of list determine priority of Play to Report.","default":true},"refreshEnabled":{"type":"boolean","description":"Try to get fresh scrobble history from client when tracks to be scrobbled are newer than the last scrobble found in client history","default":true,"examples":[true]},"refreshStaleAfter":{"type":"number","description":"Refresh scrobbled plays from upstream service if last refresh was at least X seconds ago\n\n**In most case this setting does NOT need to be changed.** The default value is sufficient for the majority of use-cases. Increasing this setting may increase upstream service load and slow down scrobbles.\n\nThis setting should only be changed in specific scenarios where MS is handling multiple \"relaying\" client-services (IE lfm -> lz -> lfm) and there is the potential for a client to be out of sync after more than a few seconds.","examples":[60],"default":60},"refreshMinInterval":{"type":"number","description":"Minimum time (milliseconds) required to pass before upstream scrobbles can be refreshed.\n\n**In most case this setting does NOT need to be changed.** This will always be equal to or smaller than `refreshStaleAfter`.","default":5000,"examples":[5000]},"refreshInitialCount":{"type":"number","description":"The number of tracks to retrieve on initial refresh (related to scrobbleBacklogCount). If not specified this is the maximum supported by the client in 1 API call."},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"checkExistingScrobbles":{"type":"boolean","description":"Check client for an existing scrobble at the same recorded time as the \"new\" track to be scrobbled. If an existing scrobble is found this track is not track scrobbled.","default":true,"examples":[true]},"verbose":{"type":"object","properties":{"match":{"$ref":"#/definitions/MatchLoggingOptions"}},"description":"Options used for increasing verbosity of logging in MS (used for debugging)"},"deadLetterRetries":{"type":"number","description":"Number of times MS should automatically retry scrobbles in dead letter queue","default":1,"examples":[1]},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"},"audioScrobblerUrl":{"type":"string","description":"URL for the Rocksky *Listenbrainz* endpoint, if not using the default","examples":["https://audioscrobbler.rocksky.app"],"default":"https://audioscrobbler.rocksky.app"},"apiUrl":{"type":"string","description":"URL for the Rocksky *API* endpoint, if not using the default","examples":["https://api.rocksky.app"],"default":"https://api.rocksky.app"}},"title":"RockSkyClientOptions"},"DiscordClientConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this client. Used with sources to restrict where scrobbles are sent.","examples":["MyConfig"]},"data":{"$ref":"#/definitions/DiscordClientData","description":"Specific data required to configure this client"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"options":{"$ref":"#/definitions/CommonClientOptions"},"configureAs":{"type":"string","enum":["client","source"],"description":"Should always be `client` when using Koito as a client","default":"client","examples":["client"]}},"required":["data","name"],"title":"DiscordClientConfig"},"DiscordClientData":{"type":"object","properties":{"token":{"type":"string"},"applicationId":{"type":"string"},"artwork":{"anyOf":[{"type":"boolean"},{"type":"string"},{"type":"array","items":{"type":"string"}}]},"artworkDefaultUrl":{"type":"string"},"statusOverrideAllow":{"anyOf":[{"type":"string"},{"type":"array","items":{"$ref":"#/definitions/StatusType"}}]},"listeningActivityAllow":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}]},"ipcLocations":{"anyOf":[{"type":"string"},{"type":"array","items":{"anyOf":[{"type":"string"},{"type":"array","minItems":2,"items":[{"type":"number"},{"type":"string"}],"maxItems":2}]}}]}},"title":"DiscordClientData"},"StatusType":{"type":"string","enum":["online","idle","dnd","invisible"],"title":"StatusType"}}} \ No newline at end of file diff --git a/docsite/static/schemas/PlexApiSourceConfig.json b/docsite/static/schemas/PlexApiSourceConfig.json new file mode 100644 index 00000000..93e1cf3c --- /dev/null +++ b/docsite/static/schemas/PlexApiSourceConfig.json @@ -0,0 +1 @@ +{"$schema":"http://json-schema.org/draft-07/schema#","type":"array","items":{"$ref":"#/definitions/PlexApiSourceConfig"},"definitions":{"PlexApiSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/PlexApiData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/PlexApiOptions"}},"required":["data"],"title":"PlexApiSourceConfig"},"PlexApiData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"token":{"type":"string"},"url":{"type":"string","description":"http(s)://HOST:PORT of the Plex server to connect to"},"usersAllow":{"anyOf":[{"type":"string"},{"type":"boolean","enum":[true]},{"type":"array","items":{"type":"string"}}],"description":"Only scrobble for specific users (case-insensitive)\n\nIf `true` MS will scrobble activity from all users"},"usersBlock":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Do not scrobble for these users (case-insensitive)"},"devicesAllow":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Only scrobble if device or application name contains strings from this list (case-insensitive)"},"devicesBlock":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Do not scrobble if device or application name contains strings from this list (case-insensitive)"},"librariesAllow":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Only scrobble if library name contains string from this list (case-insensitive)"},"librariesBlock":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Do not scrobble if library name contains strings from this list (case-insensitive)"}},"required":["url"],"title":"PlexApiData"},"PlexApiOptions":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"},"ignoreInvalidCert":{"type":"boolean","description":"Ignore invalid cert errors when connecting to Plex\n\nUseful for Plex servers using \"Required\" Secure Connections with self-signed certificates\n\nDo not enable unless you know you need this.","default":false}},"title":"PlexApiOptions"},"LogLevel":{"type":"string","enum":["silent","fatal","error","warn","info","log","verbose","debug","trace"],"description":"Names of log levels that can be invoked on the logger\n\nFrom lowest to highest:\n\n* `trace`\n* `debug`\n* `verbose`\n* `log`\n* `info`\n* `warn`\n* `error`\n* `fatal`\n* `silent` (will never output anything)\n\nWhen used in `LogOptions` specifies the **minimum** level the output should log at.","title":"LogLevel"},"FileLogOptions":{"type":"object","properties":{"timestamp":{"type":"string","enum":["unix","iso","auto"],"description":"For rolling log files\n\nWhen\n* value passed to rolling destination is a string (`path` from LogOptions is a string) and\n* `frequency` is defined\n\nThis determines the format of the datetime inserted into the log file name:\n\n* `unix` - unix epoch timestamp in milliseconds\n* `iso` - Full [ISO8601](https://en.wikipedia.org/wiki/ISO_8601) datetime IE '2024-03-07T20:11:34Z'\n* `auto`\n * When frequency is `daily` only inserts date IE YYYY-MM-DD\n * Otherwise inserts full ISO8601 datetime","default":"auto"},"size":{"type":["number","string"],"description":"The maximum size of a given rolling log file.\n\nCan be combined with frequency. Use k, m and g to express values in KB, MB or GB.\n\nNumerical values will be considered as MB.","default":"10MB"},"frequency":{"anyOf":[{"type":"string","enum":["daily"]},{"type":"string","enum":["hourly"]},{"type":"number"}],"description":"The amount of time a given rolling log file is used. Can be combined with size.\n\nUse `daily` or `hourly` to rotate file every day (or every hour). Existing file within the current day (or hour) will be re-used.\n\nNumerical values will be considered as a number of milliseconds. Using a numerical value will always create a new file upon startup.","default":"daily"},"path":{"anyOf":[{"type":"string"},{"$comment":"() => string"}],"description":"The path and filename to use for log files.\n\nIf using rolling files the filename will be appended with `.N` (a number) BEFORE the extension based on rolling status.\n\nMay also be specified using env LOG_PATH or a function that returns a string.\n\nIf path is relative the absolute path will be derived from `logBaseDir` (in `LoggerAppExtras`) which defaults to CWD","default":"./logs/app.log"},"level":{"anyOf":[{"$ref":"#/definitions/LogLevel"},{"type":"boolean","const":false}],"description":"Specify the minimum log level to output to rotating files. If `false` no log files will be created."}},"title":"FileLogOptions"},"ScrobbleThresholds":{"type":"object","properties":{"duration":{"type":["number","null"],"description":"The number of seconds a track has been listened to before it should be considered scrobbled.\n\nSet to null to disable.","default":240,"examples":[240]},"percent":{"type":["number","null"],"description":"The percentage (as an integer) of a track that should have been seen played before it should be scrobbled. Only used if the Source provides information about how long the track is.\n\nSet to null to disable.\n\nNOTE: This should be used with care when the Source is a \"polling\" type (has an 'interval' property). If the track is short and the interval is too high MS may ignore the track if percentage is high because it had not \"seen\" the track for long enough from first discovery, even if you have been playing the track for longer.","default":50,"examples":[50]}},"title":"ScrobbleThresholds"},"PlayTransformOptions":{"type":"object","properties":{"log":{"anyOf":[{"type":"boolean"},{"type":"string","enum":["all"]}]},"preCompare":{"$ref":"#/definitions/PlayTransformPartsConfig%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%3E"},"compare":{"type":"object","properties":{"candidate":{"$ref":"#/definitions/PlayTransformPartsConfig%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%3E"},"existing":{"$ref":"#/definitions/PlayTransformPartsConfig%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%3E"}}},"postCompare":{"$ref":"#/definitions/PlayTransformPartsConfig%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%3E"}},"title":"PlayTransformOptions"},"PlayTransformPartsConfig<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm)>":{"anyOf":[{"$ref":"#/definitions/PlayTransformPartsArray%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%2CMaybeStageTyped%3E"},{"$ref":"#/definitions/PlayTransformParts%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%2CMaybeStageTyped%3E"}],"description":"Represents the weakly-defined user config. May be an array of parts or one parts object","title":"PlayTransformPartsConfig<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm)>"},"PlayTransformPartsArray<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm),MaybeStageTyped>":{"type":"array","items":{"$ref":"#/definitions/PlayTransformParts%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%2CMaybeStageTyped%3E"},"title":"PlayTransformPartsArray<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm),MaybeStageTyped>"},"PlayTransformParts<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm),MaybeStageTyped>":{"anyOf":[{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"title":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"artists":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"albumArtists":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"album":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"duration":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"meta":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"onSuccess":{"$ref":"#/definitions/FlowControlTerm"},"onFailure":{"$ref":"#/definitions/FlowControlTerm"},"onSkip":{"$ref":"#/definitions/FlowControlTerm"},"failureReturnPartial":{"type":"boolean"},"type":{"$ref":"#/definitions/StageTypeMetadata"},"name":{"type":"string"},"stageHash":{"type":"string"},"score":{"type":"number"}},"required":["type"]},{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"title":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"artists":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"albumArtists":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"album":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"duration":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"meta":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"onSuccess":{"$ref":"#/definitions/FlowControlTerm"},"onFailure":{"$ref":"#/definitions/FlowControlTerm"},"onSkip":{"$ref":"#/definitions/FlowControlTerm"},"failureReturnPartial":{"type":"boolean"},"type":{"$ref":"#/definitions/StageTypeUser"},"name":{"type":"string"},"stageHash":{"type":"string"}},"required":["type"]},{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"title":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"artists":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"albumArtists":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"album":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"duration":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"meta":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"onSuccess":{"$ref":"#/definitions/FlowControlTerm"},"onFailure":{"$ref":"#/definitions/FlowControlTerm"},"onSkip":{"$ref":"#/definitions/FlowControlTerm"},"failureReturnPartial":{"type":"boolean"},"type":{"type":"string","enum":["native"]},"name":{"type":"string"},"stageHash":{"type":"string"}},"required":["type"]},{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"title":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"artists":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"albumArtists":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"album":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"duration":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"meta":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"onSuccess":{"$ref":"#/definitions/FlowControlTerm"},"onFailure":{"$ref":"#/definitions/FlowControlTerm"},"onSkip":{"$ref":"#/definitions/FlowControlTerm"},"failureReturnPartial":{"type":"boolean"},"name":{"type":"string"}}},{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"title":{},"artists":{},"albumArtists":{},"album":{},"duration":{},"meta":{},"onSuccess":{"$ref":"#/definitions/FlowControlTerm"},"onFailure":{"$ref":"#/definitions/FlowControlTerm"},"onSkip":{"$ref":"#/definitions/FlowControlTerm"},"failureReturnPartial":{"type":"boolean"},"type":{"type":"string"},"name":{"type":"string"},"stageHash":{"type":"string"}},"required":["type"]}],"title":"PlayTransformParts<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm),MaybeStageTyped>"},"WhenConditionsConfig":{"$ref":"#/definitions/WhenConditions%3Cstring%3E","title":"WhenConditionsConfig"},"WhenConditions":{"type":"array","items":{"$ref":"#/definitions/WhenParts%3Cstring%3E"},"title":"WhenConditions"},"WhenParts":{"$ref":"#/definitions/PlayTransformPartsAtomic%3Cstring%3E","title":"WhenParts"},"PlayTransformPartsAtomic":{"type":"object","properties":{"title":{"type":"string"},"artists":{"type":"string"},"albumArtists":{"type":"string"},"album":{"type":"string"},"duration":{"type":"string"},"meta":{"type":"string"}},"title":"PlayTransformPartsAtomic"},"Whennable":{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"}},"title":"Whennable"},"FlowControlTerm":{"type":"string","enum":["continue","stop"],"title":"FlowControlTerm"},"StageTypeMetadata":{"type":"string","enum":["spotify","musicbrainz","native"],"title":"StageTypeMetadata"},"SearchAndReplaceTerm":{"anyOf":[{"type":"string"},{"$ref":"#/definitions/ConditionalSearchAndReplaceTerm"}],"title":"SearchAndReplaceTerm"},"ConditionalSearchAndReplaceTerm":{"$ref":"#/definitions/ConditionalSearchAndReplaceRegExp","title":"ConditionalSearchAndReplaceTerm"},"ConditionalSearchAndReplaceRegExp":{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"search":{"anyOf":[{"type":"string"},{"type":"string","format":"regex"}],"description":"The search value to test for\n\nCan be a normal string (converted to a case-sensitive literal) or a valid regular expression as a string, or an actual RegExp object","examples":[["find this string","/some string*/ig"]]},"replace":{"type":"string","description":"The replacement string/value to use when search is found\n\nThis can be a literal string like `'replace with this`, an empty string to remove the search value (`''`), or a special regex value\n\nSee replacement here for more information: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace"},"test":{"$comment":"(obj: SearchAndReplaceRegExp) => boolean","type":"object","properties":{"namedArgs":{"type":"object","properties":{"obj":{"$ref":"#/definitions/SearchAndReplaceRegExp"}},"required":["obj"],"additionalProperties":false}},"description":"An optional function to execute before running this search-and-replace that decides if it should run at all"}},"required":["replace","search"],"title":"ConditionalSearchAndReplaceRegExp"},"SearchAndReplaceRegExp":{"type":"object","properties":{"search":{"anyOf":[{"type":"string"},{"type":"string","format":"regex"}],"description":"The search value to test for\n\nCan be a normal string (converted to a case-sensitive literal) or a valid regular expression as a string, or an actual RegExp object","examples":[["find this string","/some string*/ig"]]},"replace":{"type":"string","description":"The replacement string/value to use when search is found\n\nThis can be a literal string like `'replace with this`, an empty string to remove the search value (`''`), or a special regex value\n\nSee replacement here for more information: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace"},"test":{"$comment":"(obj: SearchAndReplaceRegExp) => boolean","type":"object","properties":{"namedArgs":{"type":"object","properties":{"obj":{"$ref":"#/definitions/SearchAndReplaceRegExp"}},"required":["obj"],"additionalProperties":false}},"description":"An optional function to execute before running this search-and-replace that decides if it should run at all"}},"required":["search","replace"],"title":"SearchAndReplaceRegExp"},"ExternalMetadataTerm":{"anyOf":[{"type":"boolean"},{"not":{}},{"$ref":"#/definitions/Whennable"}],"title":"ExternalMetadataTerm"},"StageTypeUser":{"type":"string","enum":["user"],"title":"StageTypeUser"}}} \ No newline at end of file diff --git a/docsite/static/source.json b/docsite/static/source.json index f30d854a..9da6e470 100644 --- a/docsite/static/source.json +++ b/docsite/static/source.json @@ -1 +1 @@ -{"$schema":"http://json-schema.org/draft-07/schema#","anyOf":[{"$ref":"#/definitions/SpotifySourceConfig"},{"$ref":"#/definitions/PlexApiSourceConfig"},{"$ref":"#/definitions/DeezerSourceConfig"},{"$ref":"#/definitions/DeezerInternalSourceConfig"},{"$ref":"#/definitions/ListenbrainzEndpointSourceConfig"},{"$ref":"#/definitions/LastFMEndpointSourceConfig"},{"$ref":"#/definitions/SubSonicSourceConfig"},{"$ref":"#/definitions/JellyApiSourceConfig"},{"$ref":"#/definitions/LastfmSourceConfig"},{"$ref":"#/definitions/LibrefmSourceConfig"},{"$ref":"#/definitions/YTMusicSourceConfig"},{"$ref":"#/definitions/MPRISSourceConfig"},{"$ref":"#/definitions/MopidySourceConfig"},{"$ref":"#/definitions/ListenBrainzSourceConfig"},{"$ref":"#/definitions/JRiverSourceConfig"},{"$ref":"#/definitions/KodiSourceConfig"},{"$ref":"#/definitions/WebScrobblerSourceConfig"},{"$ref":"#/definitions/ChromecastSourceConfig"},{"$ref":"#/definitions/MalojaSourceConfig"},{"$ref":"#/definitions/MusikcubeSourceConfig"},{"$ref":"#/definitions/MusicCastSourceConfig"},{"$ref":"#/definitions/MPDSourceConfig"},{"$ref":"#/definitions/VLCSourceConfig"},{"$ref":"#/definitions/IcecastSourceConfig"},{"$ref":"#/definitions/AzuracastSourceConfig"},{"$ref":"#/definitions/KoitoSourceConfig"},{"$ref":"#/definitions/TealSourceConfig"},{"$ref":"#/definitions/RockskySourceConfig"}],"definitions":{"SpotifySourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/SpotifySourceData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"}},"required":["data"],"title":"SpotifySourceConfig"},"SpotifySourceData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)\n\nIt is unlikely you should need to change this unless you scrobble many very short tracks often\n\nReading:\n* https://developer.spotify.com/documentation/web-api/guides/rate-limits/\n* https://medium.com/mendix/limiting-your-amount-of-calls-in-mendix-most-of-the-time-rest-835dde55b10e\n * Rate limit may ~180 req/min\n* https://community.spotify.com/t5/Spotify-for-Developers/Web-API-ratelimit/m-p/5503150/highlight/true#M7930\n * Informally indicated as 20 req/sec? Probably for burstiness","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"clientId":{"type":"string","description":"spotify client id","examples":["787c921a2a2ab42320831aba0c8f2fc2"]},"clientSecret":{"type":"string","description":"spotify client secret","examples":["ec42e09d5ae0ee0f0816ca151008412a"]},"redirectUri":{"type":"string","description":"spotify redirect URI -- required only if not the default shown here. URI must end in \"callback\"","default":"http://localhost:9078/callback","examples":["http://localhost:9078/callback"]}},"required":["clientId","clientSecret"],"title":"SpotifySourceData"},"CommonSourceOptions":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"CommonSourceOptions"},"LogLevel":{"type":"string","enum":["silent","fatal","error","warn","info","log","verbose","debug"],"description":"Names of log levels that can be invoked on the logger\n\nFrom lowest to highest:\n\n* `debug`\n* `verbose`\n* `log`\n* `info`\n* `warn`\n* `error`\n* `fatal`\n* `silent` (will never output anything)\n\nWhen used in `LogOptions` specifies the **minimum** level the output should log at.","title":"LogLevel"},"FileLogOptions":{"type":"object","properties":{"timestamp":{"type":"string","enum":["unix","iso","auto"],"description":"For rolling log files\n\nWhen\n* value passed to rolling destination is a string (`path` from LogOptions is a string) and\n* `frequency` is defined\n\nThis determines the format of the datetime inserted into the log file name:\n\n* `unix` - unix epoch timestamp in milliseconds\n* `iso` - Full [ISO8601](https://en.wikipedia.org/wiki/ISO_8601) datetime IE '2024-03-07T20:11:34Z'\n* `auto`\n * When frequency is `daily` only inserts date IE YYYY-MM-DD\n * Otherwise inserts full ISO8601 datetime","default":"auto"},"size":{"type":["number","string"],"description":"The maximum size of a given rolling log file.\n\nCan be combined with frequency. Use k, m and g to express values in KB, MB or GB.\n\nNumerical values will be considered as MB.","default":"10MB"},"frequency":{"anyOf":[{"type":"string","enum":["daily"]},{"type":"string","enum":["hourly"]},{"type":"number"}],"description":"The amount of time a given rolling log file is used. Can be combined with size.\n\nUse `daily` or `hourly` to rotate file every day (or every hour). Existing file within the current day (or hour) will be re-used.\n\nNumerical values will be considered as a number of milliseconds. Using a numerical value will always create a new file upon startup.","default":"daily"},"path":{"anyOf":[{"type":"string"},{"$comment":"() => string"}],"description":"The path and filename to use for log files.\n\nIf using rolling files the filename will be appended with `.N` (a number) BEFORE the extension based on rolling status.\n\nMay also be specified using env LOG_PATH or a function that returns a string.\n\nIf path is relative the absolute path will be derived from `logBaseDir` (in `LoggerAppExtras`) which defaults to CWD","default":"./logs/app.log"},"level":{"anyOf":[{"$ref":"#/definitions/LogLevel"},{"type":"boolean","const":false}],"description":"Specify the minimum log level to output to rotating files. If `false` no log files will be created."}},"title":"FileLogOptions"},"ScrobbleThresholds":{"type":"object","properties":{"duration":{"type":["number","null"],"description":"The number of seconds a track has been listened to before it should be considered scrobbled.\n\nSet to null to disable.","default":240,"examples":[240]},"percent":{"type":["number","null"],"description":"The percentage (as an integer) of a track that should have been seen played before it should be scrobbled. Only used if the Source provides information about how long the track is.\n\nSet to null to disable.\n\nNOTE: This should be used with care when the Source is a \"polling\" type (has an 'interval' property). If the track is short and the interval is too high MS may ignore the track if percentage is high because it had not \"seen\" the track for long enough from first discovery, even if you have been playing the track for longer.","default":50,"examples":[50]}},"title":"ScrobbleThresholds"},"PlayTransformOptions":{"type":"object","properties":{"log":{"anyOf":[{"type":"boolean"},{"type":"string","enum":["all"]}]},"preCompare":{"$ref":"#/definitions/PlayTransformPartsConfig%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%3E"},"compare":{"type":"object","properties":{"candidate":{"$ref":"#/definitions/PlayTransformPartsConfig%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%3E"},"existing":{"$ref":"#/definitions/PlayTransformPartsConfig%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%3E"}}},"postCompare":{"$ref":"#/definitions/PlayTransformPartsConfig%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%3E"}},"title":"PlayTransformOptions"},"PlayTransformPartsConfig<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm)>":{"anyOf":[{"$ref":"#/definitions/PlayTransformPartsArray%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%2CMaybeStageTyped%3E"},{"$ref":"#/definitions/PlayTransformParts%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%2CMaybeStageTyped%3E"}],"description":"Represents the weakly-defined user config. May be an array of parts or one parts object","title":"PlayTransformPartsConfig<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm)>"},"PlayTransformPartsArray<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm),MaybeStageTyped>":{"type":"array","items":{"$ref":"#/definitions/PlayTransformParts%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%2CMaybeStageTyped%3E"},"title":"PlayTransformPartsArray<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm),MaybeStageTyped>"},"PlayTransformParts<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm),MaybeStageTyped>":{"anyOf":[{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"title":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"artists":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"albumArtists":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"album":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"duration":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"meta":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"onSuccess":{"$ref":"#/definitions/FlowControlTerm"},"onFailure":{"$ref":"#/definitions/FlowControlTerm"},"onSkip":{"$ref":"#/definitions/FlowControlTerm"},"failureReturnPartial":{"type":"boolean"},"type":{"$ref":"#/definitions/StageTypeMetadata"},"name":{"type":"string"},"stageHash":{"type":"string"},"score":{"type":"number"}},"required":["type"]},{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"title":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"artists":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"albumArtists":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"album":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"duration":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"meta":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"onSuccess":{"$ref":"#/definitions/FlowControlTerm"},"onFailure":{"$ref":"#/definitions/FlowControlTerm"},"onSkip":{"$ref":"#/definitions/FlowControlTerm"},"failureReturnPartial":{"type":"boolean"},"type":{"$ref":"#/definitions/StageTypeUser"},"name":{"type":"string"},"stageHash":{"type":"string"}},"required":["type"]},{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"title":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"artists":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"albumArtists":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"album":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"duration":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"meta":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"onSuccess":{"$ref":"#/definitions/FlowControlTerm"},"onFailure":{"$ref":"#/definitions/FlowControlTerm"},"onSkip":{"$ref":"#/definitions/FlowControlTerm"},"failureReturnPartial":{"type":"boolean"},"type":{"type":"string","enum":["native"]},"name":{"type":"string"},"stageHash":{"type":"string"}},"required":["type"]},{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"title":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"artists":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"albumArtists":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"album":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"duration":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"meta":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"onSuccess":{"$ref":"#/definitions/FlowControlTerm"},"onFailure":{"$ref":"#/definitions/FlowControlTerm"},"onSkip":{"$ref":"#/definitions/FlowControlTerm"},"failureReturnPartial":{"type":"boolean"},"name":{"type":"string"}}},{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"title":{},"artists":{},"albumArtists":{},"album":{},"duration":{},"meta":{},"onSuccess":{"$ref":"#/definitions/FlowControlTerm"},"onFailure":{"$ref":"#/definitions/FlowControlTerm"},"onSkip":{"$ref":"#/definitions/FlowControlTerm"},"failureReturnPartial":{"type":"boolean"},"type":{"type":"string"},"name":{"type":"string"},"stageHash":{"type":"string"}},"required":["type"]}],"title":"PlayTransformParts<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm),MaybeStageTyped>"},"WhenConditionsConfig":{"$ref":"#/definitions/WhenConditions%3Cstring%3E","title":"WhenConditionsConfig"},"WhenConditions":{"type":"array","items":{"$ref":"#/definitions/WhenParts%3Cstring%3E"},"title":"WhenConditions"},"WhenParts":{"$ref":"#/definitions/PlayTransformPartsAtomic%3Cstring%3E","title":"WhenParts"},"PlayTransformPartsAtomic":{"type":"object","properties":{"title":{"type":"string"},"artists":{"type":"string"},"albumArtists":{"type":"string"},"album":{"type":"string"},"duration":{"type":"string"},"meta":{"type":"string"}},"title":"PlayTransformPartsAtomic"},"Whennable":{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"}},"title":"Whennable"},"FlowControlTerm":{"type":"string","enum":["continue","stop"],"title":"FlowControlTerm"},"StageTypeMetadata":{"type":"string","enum":["spotify","musicbrainz","native"],"title":"StageTypeMetadata"},"SearchAndReplaceTerm":{"anyOf":[{"type":"string"},{"$ref":"#/definitions/ConditionalSearchAndReplaceTerm"}],"title":"SearchAndReplaceTerm"},"ConditionalSearchAndReplaceTerm":{"$ref":"#/definitions/ConditionalSearchAndReplaceRegExp","title":"ConditionalSearchAndReplaceTerm"},"ConditionalSearchAndReplaceRegExp":{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"search":{"anyOf":[{"type":"string"},{"type":"string","format":"regex"}],"description":"The search value to test for\n\nCan be a normal string (converted to a case-sensitive literal) or a valid regular expression as a string, or an actual RegExp object","examples":[["find this string","/some string*/ig"]]},"replace":{"type":"string","description":"The replacement string/value to use when search is found\n\nThis can be a literal string like `'replace with this`, an empty string to remove the search value (`''`), or a special regex value\n\nSee replacement here for more information: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace"},"test":{"$comment":"(obj: SearchAndReplaceRegExp) => boolean","type":"object","properties":{"namedArgs":{"type":"object","properties":{"obj":{"$ref":"#/definitions/SearchAndReplaceRegExp"}},"required":["obj"],"additionalProperties":false}},"description":"An optional function to execute before running this search-and-replace that decides if it should run at all"}},"required":["replace","search"],"title":"ConditionalSearchAndReplaceRegExp"},"SearchAndReplaceRegExp":{"type":"object","properties":{"search":{"anyOf":[{"type":"string"},{"type":"string","format":"regex"}],"description":"The search value to test for\n\nCan be a normal string (converted to a case-sensitive literal) or a valid regular expression as a string, or an actual RegExp object","examples":[["find this string","/some string*/ig"]]},"replace":{"type":"string","description":"The replacement string/value to use when search is found\n\nThis can be a literal string like `'replace with this`, an empty string to remove the search value (`''`), or a special regex value\n\nSee replacement here for more information: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace"},"test":{"$comment":"(obj: SearchAndReplaceRegExp) => boolean","type":"object","properties":{"namedArgs":{"type":"object","properties":{"obj":{"$ref":"#/definitions/SearchAndReplaceRegExp"}},"required":["obj"],"additionalProperties":false}},"description":"An optional function to execute before running this search-and-replace that decides if it should run at all"}},"required":["search","replace"],"title":"SearchAndReplaceRegExp"},"ExternalMetadataTerm":{"anyOf":[{"type":"boolean"},{"not":{}},{"$ref":"#/definitions/Whennable"}],"title":"ExternalMetadataTerm"},"StageTypeUser":{"type":"string","enum":["user"],"title":"StageTypeUser"},"PlexApiSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/PlexApiData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/PlexApiOptions"}},"required":["data"],"title":"PlexApiSourceConfig"},"PlexApiData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"token":{"type":"string"},"url":{"type":"string","description":"http(s)://HOST:PORT of the Plex server to connect to"},"usersAllow":{"anyOf":[{"type":"string"},{"type":"boolean","enum":[true]},{"type":"array","items":{"type":"string"}}],"description":"Only scrobble for specific users (case-insensitive)\n\nIf `true` MS will scrobble activity from all users"},"usersBlock":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Do not scrobble for these users (case-insensitive)"},"devicesAllow":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Only scrobble if device or application name contains strings from this list (case-insensitive)"},"devicesBlock":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Do not scrobble if device or application name contains strings from this list (case-insensitive)"},"librariesAllow":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Only scrobble if library name contains string from this list (case-insensitive)"},"librariesBlock":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Do not scrobble if library name contains strings from this list (case-insensitive)"}},"required":["url"],"title":"PlexApiData"},"PlexApiOptions":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"},"ignoreInvalidCert":{"type":"boolean","description":"Ignore invalid cert errors when connecting to Plex\n\nUseful for Plex servers using \"Required\" Secure Connections with self-signed certificates\n\nDo not enable unless you know you need this.","default":false}},"title":"PlexApiOptions"},"DeezerSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/DeezerData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"}},"required":["data"],"title":"DeezerSourceConfig"},"DeezerData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"clientId":{"type":"string","description":"deezer client id","examples":["a89cba1569901a0671d5a9875fed4be1"]},"clientSecret":{"type":"string","description":"deezer client secret","examples":["ec42e09d5ae0ee0f0816ca151008412a"]},"redirectUri":{"type":"string","description":"deezer redirect URI -- required only if not the default shown here. URI must end in \"callback\"","default":"http://localhost:9078/deezer/callback","examples":["http://localhost:9078/deezer/callback"]}},"required":["clientId","clientSecret"],"title":"DeezerData"},"DeezerInternalSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/DeezerInternalData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/DeezerInternalSourceOptions"}},"required":["data"],"title":"DeezerInternalSourceConfig"},"DeezerInternalData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"arl":{"type":"string","description":"ARL retrieved from Deezer response header"},"userAgent":{"type":"string","description":"User agent","default":"Mozilla/5.0 (X11; Linux i686; rv:135.0) Gecko/20100101 Firefox/135.0"}},"required":["arl"],"title":"DeezerInternalData"},"DeezerInternalSourceOptions":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"},"fuzzyDiscoveryIgnore":{"anyOf":[{"type":"boolean"},{"type":"string","enum":["aggressive"]}]}},"title":"DeezerInternalSourceOptions"},"ListenbrainzEndpointSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/ListenbrainzEndpointData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"}},"title":"ListenbrainzEndpointSourceConfig"},"ListenbrainzEndpointData":{"type":"object","properties":{"slug":{"type":["string","null"],"description":"The URL ending that should be used to identify scrobbles for this source\n\nIf you are using multiple Listenbrainz endpoint sources (scrobbles for many users) you can use a slug to match Sources with individual users/origins\n\nExample:\n\n* slug: 'usera' => API URL: http://localhost:9078/api/listenbrainz/usera\n* slug: 'originb' => API URL: http://localhost:9078/api/listenbrainz/originb\n\nIf no slug is found from an extension's incoming webhook event the first Listenbrainz source without a slug will be used"},"token":{"type":["string","null"],"description":"If an LZ submission request contains this token in the Authorization Header it will be used to match the submission with this Source\n\nSee: https://listenbrainz.readthedocs.io/en/latest/users/api/index.html#add-the-user-token-to-your-requests"}},"title":"ListenbrainzEndpointData"},"LastFMEndpointSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/LastFMEndpointData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"}},"title":"LastFMEndpointSourceConfig"},"LastFMEndpointData":{"type":"object","properties":{"slug":{"type":["string","null"],"description":"The URL ending that should be used to identify scrobbles for this source\n\nIf you are using multiple Last.fm endpoint sources (scrobbles for many users) you can use a slug to match Sources with individual users/origins\n\nExample:\n\n* slug: 'usera' => API URL: http://localhost:9078/api/lastfm/usera\n* slug: 'originb' => API URL: http://localhost:9078/api/lastfm/originb\n\nIf no slug is found from an extension's incoming webhook event the first Last.fm source without a slug will be used"}},"title":"LastFMEndpointData"},"SubSonicSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/SubsonicData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"}},"required":["data"],"title":"SubSonicSourceConfig"},"SubsonicData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"url":{"type":"string","description":"URL of the subsonic media server to query","examples":["http://airsonic.local"]},"user":{"type":"string","description":"Username to login to the server with","examples":[["MyUser"]]},"password":{"type":"string","description":"Password for the user to login to the server with","examples":["MyPassword"]},"ignoreTlsErrors":{"type":"boolean","description":"If your subsonic server is using self-signed certs you may need to disable TLS errors in order to get a connection\n\nWARNING: This should be used with caution as your traffic may not be encrypted.","default":false},"legacyAuthentication":{"type":"boolean","description":"Older Subsonic versions, and some badly implemented servers (Nextcloud), use legacy authentication which sends your password in CLEAR TEXT. This is less secure than the newer, recommended hashing authentication method but in some cases it is needed. See \"Authentication\" section here => https://www.subsonic.org/pages/api.jsp\n\nIf this option is not specified it will be turned on if the subsonic server responds with error code 41 \"Token authentication not supported for LDAP users.\" -- See Error Handling section => https://www.subsonic.org/pages/api.jsp","default":false},"usersAllow":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Only scrobble for specific users (case-insensitive)\n\nIf undefined or an empty string/list MS will scrobble activity from all users"}},"required":["url","user","password"],"title":"SubsonicData"},"JellyApiSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/JellyApiData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/JellyApiOptions"}},"required":["data","options"],"title":"JellyApiSourceConfig"},"JellyApiData":{"type":"object","properties":{"url":{"type":"string","description":"HOST:PORT of the Jellyfin server to connect to"},"user":{"type":"string","description":"The username of the user to authenticate for or track scrobbles for"},"password":{"type":"string","description":"Password of the username to authenticate for\n\nRequired if `apiKey` is not provided."},"apiKey":{"type":"string","description":"API Key to authenticate with.\n\nRequired if `password` is not provided."},"usersAllow":{"anyOf":[{"type":"string"},{"type":"boolean","enum":[true]},{"type":"array","items":{"type":"string"}}],"description":"Only scrobble for specific users (case-insensitive)\n\nIf `true` MS will scrobble activity from all users"},"usersBlock":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Do not scrobble for these users (case-insensitive)"},"devicesAllow":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Only scrobble if device or application name contains strings from this list (case-insensitive)"},"devicesBlock":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Do not scrobble if device or application name contains strings from this list (case-insensitive)"},"librariesAllow":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Only scrobble if library name contains string from this list (case-insensitive)"},"librariesBlock":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Do not scrobble if library name contains strings from this list (case-insensitive)"},"additionalAllowedLibraryTypes":{"type":"array","items":{},"description":"Allow MS to scrobble audio media in libraries classified other than 'music'\n\n`librariesAllow` will achieve the same result as this but this is more convenient if you do not want to explicitly list every library name or are only using `librariesBlock`"},"allowUnknown":{"type":"boolean","description":"Force media with a type of \"Unknown\" to be counted as Audio","default":false},"frontendUrlOverride":{"type":"string","description":"HOST:PORT of the Jellyfin server that your browser will be able to access from the frontend (and thus load images and links from)\nIf unspecified it will use the normal server HOST and PORT from the `url`\nNecessary if you are using a reverse proxy or other network configuration that prevents the frontend from accessing the server directly\n\nENV: JELLYFIN_FRONTEND_URL_OVERRIDE"}},"required":["url","user"],"title":"JellyApiData"},"JellyApiOptions":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"JellyApiOptions"},"LastfmSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/LastFmSourceData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"configureAs":{"type":"string","enum":["source"],"description":"When used in `lastfm.config` this tells multi-scrobbler whether to use this data to configure a source or client.","default":"source","examples":["source"]}},"required":["data"],"title":"LastfmSourceConfig"},"LastFmSourceData":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"apiKey":{"type":"string","description":"API Key generated from Last.fm/Libre.fm account","examples":["787c921a2a2ab42320831aba0c8f2fc2"]},"secret":{"type":"string","description":"Secret generated from Last.fm/Libre.fm account","examples":["ec42e09d5ae0ee0f0816ca151008412a"]},"session":{"type":"string","description":"Optional session id returned from a completed auth flow"},"redirectUri":{"type":"string","description":"Optional URI to use for callback. Specify this if callback should be different than the default. MUST have \"lastfm/callback\" in the URL somewhere.","default":"http://localhost:9078/lastfm/callback","examples":["http://localhost:9078/lastfm/callback"]},"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"}},"required":["apiKey","secret"],"title":"LastFmSourceData"},"LibrefmSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/LibrefmData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"configureAs":{"type":"string","enum":["source"],"description":"When used in `librefm.config` this tells multi-scrobbler whether to use this data to configure a source or client.","default":"source","examples":["source"]}},"required":["data"],"title":"LibrefmSourceConfig"},"LibrefmData":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"apiKey":{"type":"string","description":"Optional Secret for Libre.fm account\n\nThis can be anything, or it will be generated by multi-scrobbler","examples":["anyValue"]},"secret":{"type":"string","description":"Optional Secret for Libre.fm account\n\nThis can be anything, or it will be generated by multi-scrobbler","examples":["anyValue"]},"session":{"type":"string","description":"Optional session id returned from a completed auth flow"},"path":{"type":"string"},"urlBase":{"type":"string","description":"(Optional) The host and path prefix for your Libre.fm instance","default":"https://libre.fm/2.0/"},"redirectUri":{"type":"string","description":"Optional URI to use for callback. Specify this if callback should be different than the default. MUST have \"librefm/callback\" in the URL somewhere.","default":"http://localhost:9078/librefm/callback","examples":["http://localhost:9078/librefm/callback"]}},"title":"LibrefmData"},"YTMusicSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/YTMusicData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"type":"object","properties":{"logAuth":{"type":"boolean","description":"When true MS will log to DEBUG all of the credentials data it receives from YTM"},"logDiff":{"type":"boolean","description":"Always log history diff\n\nBy default MS will log to `WARN` if history diff is inconsistent but does not log if diff is expected (on new tracks found)\nSet this to `true` to ALWAYS log diff on new tracks. Expected diffs will log to `DEBUG` and inconsistent diffs will continue to log to `WARN`","default":false},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}}}},"title":"YTMusicSourceConfig"},"YTMusicData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"cookie":{"type":"string","description":"The cookie retrieved from the Request Headers of music.youtube.com after logging in.\n\nSee https://ytmusicapi.readthedocs.io/en/stable/setup/browser.html#copy-authentication-headers for how to retrieve this value.","examples":["VISITOR_INFO1_LIVE=jMp2xA1Xz2_PbVc; __Secure-3PAPISID=3AxsXpy0M/AkISpjek; ..."]},"clientId":{"type":"string","description":"Google Cloud Console project OAuth Client ID\n\nGenerated from a custom OAuth Client, see docs"},"clientSecret":{"type":"string","description":"Google Cloud Console project OAuth Client Secret\n\nGenerated from a custom OAuth Client, see docs"},"redirectUri":{"type":"string","description":"Google Cloud Console project OAuth Client Authorized redirect URI\n\nGenerated from a custom OAuth Client, see docs. multi-scrobbler will generate a default based on BASE_URL.\nOnly specify this if the default does not work for you."},"innertubeOptions":{"$ref":"#/definitions/InnertubeOptions","description":"Additional options for authorization and tailoring YTM client"}},"title":"YTMusicData"},"InnertubeOptions":{"type":"object","properties":{"po_token":{"type":"string","description":"Proof of Origin token\n\nMay be required if YTM starts returning 403"},"visitor_data":{"type":"string","description":"Visitor ID value found in VISITOR_INFO1_LIVE or visitorData cookie\n\nMay be required if YTM starts returning 403"},"account_index":{"type":"number","description":"If account login results in being able to choose multiple account, use a zero-based index to choose which one to monitor","examples":[0,1]},"location":{"type":"string"},"lang":{"type":"string"},"generate_session_locally":{"type":"boolean"},"device_category":{"type":"string"},"client_type":{"type":"string"},"timezone":{"type":"string"}},"title":"InnertubeOptions"},"MPRISSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/MPRISData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"}},"required":["data"],"title":"MPRISSourceConfig"},"MPRISData":{"type":"object","properties":{"blacklist":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"DO NOT scrobble from any players that START WITH these values, case-insensitive","examples":[["spotify","vlc"]]},"whitelist":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"ONLY from any players that START WITH these values, case-insensitive\n\nIf whitelist is present then blacklist is ignored","examples":[["spotify","vlc"]]}},"title":"MPRISData"},"MopidySourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/MopidyData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"}},"required":["data"],"title":"MopidySourceConfig"},"MopidyData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"url":{"type":"string","description":"URL of the Mopidy HTTP server to connect to\n\nYou MUST have Mopidy-HTTP extension enabled: https://mopidy.com/ext/http\n\nmulti-scrobbler connects to the WebSocket endpoint that ultimately looks like this => `ws://localhost:6680/mopidy/ws/`\n\nThe URL you provide here will have all parts not explicitly defined filled in for you so if these are not the default you must define them.\n\nParts => [default value]\n\n* Protocol => `ws://`\n* Hostname => `localhost`\n* Port => `6680`\n* Path => `/mopidy/ws/`","examples":["ws://localhost:6680/mopidy/ws/"],"default":"ws://localhost:6680/mopidy/ws/"},"uriBlacklist":{"type":"array","items":{"type":"string"},"description":"Do not scrobble tracks whose URI STARTS WITH any of these strings, case-insensitive\n\nEX: Don't scrobble tracks from soundcloud by adding 'soundcloud' to this list.\n\nList is ignored if uriWhitelist is used."},"uriWhitelist":{"type":"array","items":{"type":"string"},"description":"Only scrobble tracks whose URI STARTS WITH any of these strings, case-insensitive\n\nEX: Only scrobble tracks from soundcloud by adding 'soundcloud' to this list."},"albumBlacklist":{"type":"array","items":{"type":"string"},"description":"Remove album data that matches any case-insensitive string from this list when scrobbling,\n\nFor certain sources (Soundcloud) Mopidy does not have all track info (Album) and will instead use \"Soundcloud\" as the Album name. You can prevent multi-scrobbler from using this bad Album data by adding the fake name to this list. Multi-scrobbler will still scrobble the track, just without the bad data.","examples":[["Soundcloud","Mixcloud"]],"default":["Soundcloud"]}},"title":"MopidyData"},"ListenBrainzSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/ListenBrainzSourceData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"configureAs":{"type":"string","enum":["source"],"description":"When used in `listenbrainz.config` this tells multi-scrobbler whether to use this data to configure a source or client.","default":"source","examples":["source"]}},"required":["data"],"title":"ListenBrainzSourceConfig"},"ListenBrainzSourceData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"url":{"type":"string","description":"URL for the ListenBrainz server, if not using the default","examples":["https://api.listenbrainz.org/"],"default":"https://api.listenbrainz.org/"},"token":{"type":"string","description":"User token for the user to scrobble for","examples":["6794186bf-1157-4de6-80e5-uvb411f3ea2b"]},"username":{"type":"string","description":"Username of the user to scrobble for"}},"required":["token","username"],"title":"ListenBrainzSourceData"},"JRiverSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/JRiverData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"}},"required":["data"],"title":"JRiverSourceConfig"},"JRiverData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"url":{"type":"string","description":"URL of the JRiver HTTP server to connect to\n\nmulti-scrobbler connects to the Web Service Interface endpoint that ultimately looks like this => `http://yourDomain:52199/MCWS/v1/`\n\nThe URL you provide here will have all parts not explicitly defined filled in for you so if these are not the default you must define them.\n\nParts => [default value]\n\n* Protocol => `http://`\n* Hostname => `localhost`\n* Port => `52199`\n* Path => `/MCWS/v1/`","examples":["http://localhost:52199/MCWS/v1/"],"default":"http://localhost:52199/MCWS/v1/"},"username":{"type":"string","description":"If you have enabled authentication, the username you set"},"password":{"type":"string","description":"If you have enabled authentication, the password you set"}},"required":["url"],"title":"JRiverData"},"KodiSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/KodiData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"}},"required":["data"],"title":"KodiSourceConfig"},"KodiData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"url":{"type":"string","description":"URL of the Kodi HTTP server to connect to\n\nmulti-scrobbler connects to the Web Service Interface endpoint that ultimately looks like this => `http://yourDomain:8080/jsonrpc`\n\nThe URL you provide here will have all parts not explicitly defined filled in for you so if these are not the default you must define them.\n\nParts => [default value]\n\n* Protocol => `http://`\n* Hostname => `localhost`\n* Port => `8080`\n* Path => `/jsonrpc`","examples":["http://localhost:8080/jsonrpc"],"default":"http://localhost:8080/jsonrpc"},"username":{"type":"string","description":"The username set for Remote Control via Web Sever"},"password":{"type":"string","description":"The password set for Remote Control via Web Sever"}},"required":["url","username","password"],"title":"KodiData"},"WebScrobblerSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/WebScrobblerData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"}},"title":"WebScrobblerSourceConfig"},"WebScrobblerData":{"type":"object","properties":{"slug":{"type":["string","null"],"description":"The URL ending that should be used to identify scrobbles for this source\n\nIn WebScrobbler's Webhook you must set an 'API URL'. All MS WebScrobbler sources must start like:\n\nhttp://localhost:9078/api/webscrobbler\n\nIf you are using multiple WebScrobbler sources (scrobbles for many users) you must use a slug to match Sources with each users extension.\n\nExample:\n\n* slug: 'usera' => API URL: http://localhost:9078/api/webscrobbler/usera\n* slug: 'userb' => API URL: http://localhost:9078/api/webscrobbler/userb\n\nIf no slug is found from an extension's incoming webhook event the first WebScrobbler source without a slug will be used"},"blacklist":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Block scrobbling from specific WebScrobbler Connectors","examples":[["youtube"]]},"whitelist":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Only allow scrobbling from specific WebScrobbler Connectors","examples":[["mixcloud","soundcloud","bandcamp"]]}},"title":"WebScrobblerData"},"ChromecastSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/ChromecastData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"}},"required":["data"],"title":"ChromecastSourceConfig"},"ChromecastData":{"type":"object","properties":{"blacklistDevices":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"DO NOT scrobble from any cast devices that START WITH these values, case-insensitive\n\nUseful when used with auto discovery","examples":[["home-mini","family-tv"]]},"whitelistDevices":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"ONLY scrobble from any cast device that START WITH these values, case-insensitive\n\nIf whitelist is present then blacklist is ignored\n\nUseful when used with auto discovery","examples":[["home-mini","family-tv"]]},"blacklistApps":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"DO NOT scrobble from any application that START WITH these values, case-insensitive","examples":[["spotify","pandora"]]},"whitelistApps":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"ONLY scrobble from any application that START WITH these values, case-insensitive\n\nIf whitelist is present then blacklist is ignored","examples":[["spotify","pandora"]]},"useAvahi":{"type":"boolean","description":"Try to use Avahi and avahi-browse to resolve mDNS devices instead of native mDNS querying\n\nUseful for docker (alpine) container where mDNS resolution is not yet supported. Avahi socket must be exposed to the container and avahi-tools must be installed.","default":false},"useAutoDiscovery":{"type":"boolean","description":"Use mDNS to discovery Google Cast devices on your next automatically?\n\nIf not explicitly set then it is TRUE if `devices` is not set"},"devices":{"type":"array","items":{"$ref":"#/definitions/ChromecastDeviceInfo"},"description":"A list of Google Cast devices to monitor\n\nIf this is used then `useAutoDiscovery` is set to FALSE, if not explicitly set"},"allowUnknownMedia":{"anyOf":[{"type":"boolean"},{"type":"array","items":{"type":"string"}}],"description":"Chromecast Apps report a \"media type\" in the status info returned for whatever is currently playing\n\n* If set to TRUE then Music AND Generic/Unknown media will be tracked for ALL APPS\n* If set to FALSE then only media explicitly typed as Music will be tracked for ALL APPS\n* If set to a list then only Apps whose name contain one of these values, case-insensitive, will have Music AND Generic/Unknown tracked\n\nSee https://developers.google.com/cast/docs/media/messages#MediaInformation \"metadata\" property","default":false},"forceMediaRecognitionOn":{"type":"array","items":{"type":"string"},"description":"Media provided by any App whose name is listed here will ALWAYS be tracked, regardless of the \"media type\" reported\n\nApps will be recognized if they CONTAIN any of these values, case-insensitive"}},"title":"ChromecastData"},"ChromecastDeviceInfo":{"type":"object","properties":{"name":{"type":"string","description":"A friendly name to identify this device","examples":["MySmartTV"]},"address":{"type":"string","description":"The IP address of the device","examples":["192.168.0.115"]}},"required":["name","address"],"title":"ChromecastDeviceInfo"},"MalojaSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/MalojaSourceData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"configureAs":{"type":"string","enum":["source"],"description":"When used in `maloja.config` this tells multi-scrobbler whether to use this data to configure a source or client.","default":"source","examples":["source"]}},"required":["data"],"title":"MalojaSourceConfig"},"MalojaSourceData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"url":{"type":"string","description":"URL for maloja server","examples":["http://localhost:42010"]},"apiKey":{"type":"string","description":"API Key for Maloja server","examples":["myApiKey"]}},"required":["apiKey","url"],"title":"MalojaSourceData"},"MusikcubeSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/MusikcubeData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"}},"required":["data"],"title":"MusikcubeSourceConfig"},"MusikcubeData":{"type":"object","properties":{"url":{"type":"string","description":"URL of the Musikcube Websocket (Metadata) server to connect to\n\nYou MUST have enabled 'metadata' server and set a password: https://github.com/clangen/musikcube/wiki/remote-api-documentation\n * musikcube -> settings -> server setup\n\nThe URL you provide here will have all parts not explicitly defined filled in for you so if these are not the default you must define them.\n\nParts => [default value]\n\n* Protocol => `ws://`\n* Hostname => `localhost`\n* Port => `7905`","examples":["ws://localhost:7905"],"default":"ws://localhost:7905"},"password":{"type":"string","description":"Password set in Musikcube https://github.com/clangen/musikcube/wiki/remote-api-documentation\n\n* musikcube -> settings -> server setup -> password"},"device_id":{"type":"string"}},"required":["password"],"title":"MusikcubeData"},"MusicCastSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/MusicCastData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"}},"required":["data"],"title":"MusicCastSourceConfig"},"MusicCastData":{"type":"object","properties":{"url":{"type":"string","description":"The host or URL of the YamahaExtendedControl endpoint to use","examples":[["192.168.0.101","http://192.168.0.101/YamahaExtendedControl"]]}},"required":["url"],"title":"MusicCastData"},"MPDSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/MPDData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/MPDSourceOptions"}},"required":["data","options"],"title":"MPDSourceConfig"},"MPDData":{"type":"object","properties":{"url":{"type":"string","description":"URL:PORT of the MPD server to connect to\n\nTo use this you must have TCP connections enabled for your MPD server https://mpd.readthedocs.io/en/stable/user.html#client-connections","examples":["localhost:6600"],"default":"localhost:6600"},"path":{"type":"string","description":"If using socket specify the path instead of url.\n\ntrailing `~` is replaced by your home directory"},"password":{"type":"string","description":"Password for the server, if set https://mpd.readthedocs.io/en/stable/user.html#permissions-and-passwords"}},"title":"MPDData"},"MPDSourceOptions":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"MPDSourceOptions"},"VLCSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/VLCData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/VLCSourceOptions"}},"required":["data"],"title":"VLCSourceConfig"},"VLCData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"url":{"type":"string","description":"URL:PORT of the VLC server to connect to\n\nTo use this you must have the Web (http) interface module enabled and a password set https://foxxmd.github.io/multi-scrobbler/docs/configuration#vlc","examples":["localhost:8080"],"default":"localhost:8080"},"password":{"type":"string","description":"Password for the server"}},"required":["password"],"title":"VLCData"},"VLCSourceOptions":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"},"filenamePatterns":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"A list of regular expressions to use to extract metadata (title, album, artist) from a filename\n\nUsed when VLC reports only the filename for the current audio track"},"logFilenamePatterns":{"type":"boolean","description":"Log to DEBUG when a filename-only track is matched or not matched by filenamePatterns","default":false},"dumpVlcMetadata":{"type":"boolean","description":"Dump all the metadata VLC reports for an audio track to DEBUG.\n\nUse this if reporting an issue with VLC not correctly capturing metadata for a track.","default":false}},"title":"VLCSourceOptions"},"IcecastSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/IcecastData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/IcecastSourceOptions"}},"required":["data"],"title":"IcecastSourceConfig"},"IcecastData":{"type":"object","properties":{"sources":{"type":"array","items":{"$ref":"#/definitions/IcecastSource"}},"icestatsEndpoint":{"type":"string"},"statsEndpoint":{"type":"string"},"nextsongsEndpoint":{"type":"string"},"sevenhtmlEndpoint":{"type":"string"},"icyMetaInt":{"type":"number"},"url":{"type":"string","description":"The Icecast stream URL"}},"required":["url"],"title":"IcecastData"},"IcecastSource":{"type":"string","enum":["icy","ogg","icestats","stats","sevenhtml","nextsongs"],"title":"IcecastSource"},"IcecastSourceOptions":{"type":"object","properties":{"systemScrobble":{"type":"boolean","description":"For Sources that support manual listening, should MS default to scrobbling when no user interaction has occurred?\n\nIf not specified MS will use a Source's specific behavior, see Source's documentation."},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"IcecastSourceOptions"},"AzuracastSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/AzuracastData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"}},"required":["data"],"title":"AzuracastSourceConfig"},"AzuracastData":{"type":"object","properties":{"url":{"type":"string","description":"Base URL of the Azuracast instance\n\nThis does NOT include the station. If a station is included it will be ignored. Use `station` field to specify station, if necessary","examples":["https://radio.mydomain.tld","http://localhost:80"]},"station":{"type":"string","description":"The specific station to monitor\n\nScrobbling will only occur if any of the monitor conditions are met AND the station is ONLINE.\n\nTo monitor multiple stations create a Source for each station.","examples":["my-station-1"]},"monitorWhenListeners":{"type":["boolean","number"],"description":"Only activate scrobble monitoring if station\n\n* `true` => has any current listeners\n* `number` => has EQUAL TO or MORE THAN X number of listeners"},"monitorWhenLive":{"type":"boolean","description":"Only activate scrobble monitoring if station has a live DJ/Streamer","default":true},"apiKey":{"type":"string","description":"API Key used to access data about private streams\n\nhttps://www.azuracast.com/docs/developers/apis/#api-authentication"}},"required":["url","station"],"title":"AzuracastData"},"KoitoSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/KoitoSourceData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"configureAs":{"type":"string","enum":["source"],"description":"When used in `koito.config` this tells multi-scrobbler whether to use this data to configure a source or client.","default":"source","examples":["source"]}},"required":["data"],"title":"KoitoSourceConfig"},"KoitoSourceData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"url":{"type":"string","description":"URL for the Koito server","examples":["http://192.168.0.100:4110"]},"token":{"type":"string","description":"User token for the user to scrobble for","examples":["pM195xPV98CDpk0QW47FIIOR8AKATAX5DblBF-Jq0t1MbbKL"]},"username":{"type":"string","description":"Username of the user to scrobble for"}},"required":["token","url","username"],"title":"KoitoSourceData"},"TealSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/TealSourceData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/TealSourceOptions"},"configureAs":{"type":"string","enum":["source"],"description":"Should always be `souce` when using Tealfm as a Source","default":"source","examples":["source"]}},"required":["data"],"title":"TealSourceConfig"},"TealSourceData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"baseUri":{"type":"string","description":"The base URI of the Multi-Scrobbler to use for ATProto OAuth\n\nOnly include this if you want to use OAuth. The URI must be a non-IP/non-local domain using https: protocol."},"identifier":{"type":"string","description":"Identify the account to login as\n\n* For **App Password** Auth - your email\n* For **Oauth** - your handle minus the @"},"appPassword":{"type":"string","description":"The [App Password](https://atproto.com/specs/xrpc#app-passwords) you created for your account\n\nThis is created under https://bsky.app/settings/app-passwords\n\n**Use this if you are self-hosting Multi-Scrobbler on localhost or accessed like http://IP:PORT**"},"serviceAllow":{"type":"array","items":{"type":"string"}},"serviceDeny":{"type":"array","items":{"type":"string"}}},"required":["identifier"],"title":"TealSourceData"},"TealSourceOptions":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"TealSourceOptions"},"RockskySourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/RockskySourceData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/RockskySourceOptions"},"configureAs":{"type":"string","enum":["source"],"description":"When used in `rocksky.config` this tells multi-scrobbler whether to use this data to configure a source or client.","default":"source","examples":["source"]}},"required":["data"],"title":"RockskySourceConfig"},"RockskySourceData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"key":{"type":"string","description":"API Key generated from [API Applications](https://docs.rocksky.app/migrating-from-listenbrainz-to-rocksky-1040189m0) in Rocksky for your account","examples":["6794186bf-1157-4de6-80e5-uvb411f3ea2b"]},"handle":{"type":"string","description":"The **fully-qualified** handle for your ATPRoto/Bluesky account, like:\n\n* alice.bsky.social\n* foxxmd.com\n* mysuer.blacksky.app"}},"required":["handle","key"],"title":"RockskySourceData"},"RockskySourceOptions":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"},"audioScrobblerUrl":{"type":"string","description":"URL for the Rocksky *Listenbrainz* endpoint, if not using the default","examples":["https://audioscrobbler.rocksky.app"],"default":"https://audioscrobbler.rocksky.app"},"apiUrl":{"type":"string","description":"URL for the Rocksky *API* endpoint, if not using the default","examples":["https://api.rocksky.app"],"default":"https://api.rocksky.app"}},"title":"RockskySourceOptions"}}} \ No newline at end of file +{"$schema":"http://json-schema.org/draft-07/schema#","anyOf":[{"$ref":"#/definitions/SpotifySourceConfig"},{"$ref":"#/definitions/PlexApiSourceConfig"},{"$ref":"#/definitions/DeezerSourceConfig"},{"$ref":"#/definitions/DeezerInternalSourceConfig"},{"$ref":"#/definitions/ListenbrainzEndpointSourceConfig"},{"$ref":"#/definitions/LastFMEndpointSourceConfig"},{"$ref":"#/definitions/SubSonicSourceConfig"},{"$ref":"#/definitions/JellyApiSourceConfig"},{"$ref":"#/definitions/LastfmSourceConfig"},{"$ref":"#/definitions/LibrefmSourceConfig"},{"$ref":"#/definitions/YTMusicSourceConfig"},{"$ref":"#/definitions/MPRISSourceConfig"},{"$ref":"#/definitions/MopidySourceConfig"},{"$ref":"#/definitions/ListenBrainzSourceConfig"},{"$ref":"#/definitions/JRiverSourceConfig"},{"$ref":"#/definitions/KodiSourceConfig"},{"$ref":"#/definitions/WebScrobblerSourceConfig"},{"$ref":"#/definitions/ChromecastSourceConfig"},{"$ref":"#/definitions/MalojaSourceConfig"},{"$ref":"#/definitions/MusikcubeSourceConfig"},{"$ref":"#/definitions/MusicCastSourceConfig"},{"$ref":"#/definitions/MPDSourceConfig"},{"$ref":"#/definitions/VLCSourceConfig"},{"$ref":"#/definitions/IcecastSourceConfig"},{"$ref":"#/definitions/AzuracastSourceConfig"},{"$ref":"#/definitions/KoitoSourceConfig"},{"$ref":"#/definitions/TealSourceConfig"},{"$ref":"#/definitions/RockskySourceConfig"},{"$ref":"#/definitions/SonosSourceConfig"}],"definitions":{"SpotifySourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/SpotifySourceData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"}},"required":["data"],"title":"SpotifySourceConfig"},"SpotifySourceData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)\n\nIt is unlikely you should need to change this unless you scrobble many very short tracks often\n\nReading:\n* https://developer.spotify.com/documentation/web-api/guides/rate-limits/\n* https://medium.com/mendix/limiting-your-amount-of-calls-in-mendix-most-of-the-time-rest-835dde55b10e\n * Rate limit may ~180 req/min\n* https://community.spotify.com/t5/Spotify-for-Developers/Web-API-ratelimit/m-p/5503150/highlight/true#M7930\n * Informally indicated as 20 req/sec? Probably for burstiness","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"clientId":{"type":"string","description":"spotify client id","examples":["787c921a2a2ab42320831aba0c8f2fc2"]},"clientSecret":{"type":"string","description":"spotify client secret","examples":["ec42e09d5ae0ee0f0816ca151008412a"]},"redirectUri":{"type":"string","description":"spotify redirect URI -- required only if not the default shown here. URI must end in \"callback\"","default":"http://localhost:9078/callback","examples":["http://localhost:9078/callback"]}},"required":["clientId","clientSecret"],"title":"SpotifySourceData"},"CommonSourceOptions":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"CommonSourceOptions"},"LogLevel":{"type":"string","enum":["silent","fatal","error","warn","info","log","verbose","debug","trace"],"description":"Names of log levels that can be invoked on the logger\n\nFrom lowest to highest:\n\n* `trace`\n* `debug`\n* `verbose`\n* `log`\n* `info`\n* `warn`\n* `error`\n* `fatal`\n* `silent` (will never output anything)\n\nWhen used in `LogOptions` specifies the **minimum** level the output should log at.","title":"LogLevel"},"FileLogOptions":{"type":"object","properties":{"timestamp":{"type":"string","enum":["unix","iso","auto"],"description":"For rolling log files\n\nWhen\n* value passed to rolling destination is a string (`path` from LogOptions is a string) and\n* `frequency` is defined\n\nThis determines the format of the datetime inserted into the log file name:\n\n* `unix` - unix epoch timestamp in milliseconds\n* `iso` - Full [ISO8601](https://en.wikipedia.org/wiki/ISO_8601) datetime IE '2024-03-07T20:11:34Z'\n* `auto`\n * When frequency is `daily` only inserts date IE YYYY-MM-DD\n * Otherwise inserts full ISO8601 datetime","default":"auto"},"size":{"type":["number","string"],"description":"The maximum size of a given rolling log file.\n\nCan be combined with frequency. Use k, m and g to express values in KB, MB or GB.\n\nNumerical values will be considered as MB.","default":"10MB"},"frequency":{"anyOf":[{"type":"string","enum":["daily"]},{"type":"string","enum":["hourly"]},{"type":"number"}],"description":"The amount of time a given rolling log file is used. Can be combined with size.\n\nUse `daily` or `hourly` to rotate file every day (or every hour). Existing file within the current day (or hour) will be re-used.\n\nNumerical values will be considered as a number of milliseconds. Using a numerical value will always create a new file upon startup.","default":"daily"},"path":{"anyOf":[{"type":"string"},{"$comment":"() => string"}],"description":"The path and filename to use for log files.\n\nIf using rolling files the filename will be appended with `.N` (a number) BEFORE the extension based on rolling status.\n\nMay also be specified using env LOG_PATH or a function that returns a string.\n\nIf path is relative the absolute path will be derived from `logBaseDir` (in `LoggerAppExtras`) which defaults to CWD","default":"./logs/app.log"},"level":{"anyOf":[{"$ref":"#/definitions/LogLevel"},{"type":"boolean","const":false}],"description":"Specify the minimum log level to output to rotating files. If `false` no log files will be created."}},"title":"FileLogOptions"},"ScrobbleThresholds":{"type":"object","properties":{"duration":{"type":["number","null"],"description":"The number of seconds a track has been listened to before it should be considered scrobbled.\n\nSet to null to disable.","default":240,"examples":[240]},"percent":{"type":["number","null"],"description":"The percentage (as an integer) of a track that should have been seen played before it should be scrobbled. Only used if the Source provides information about how long the track is.\n\nSet to null to disable.\n\nNOTE: This should be used with care when the Source is a \"polling\" type (has an 'interval' property). If the track is short and the interval is too high MS may ignore the track if percentage is high because it had not \"seen\" the track for long enough from first discovery, even if you have been playing the track for longer.","default":50,"examples":[50]}},"title":"ScrobbleThresholds"},"PlayTransformOptions":{"type":"object","properties":{"log":{"anyOf":[{"type":"boolean"},{"type":"string","enum":["all"]}]},"preCompare":{"$ref":"#/definitions/PlayTransformPartsConfig%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%3E"},"compare":{"type":"object","properties":{"candidate":{"$ref":"#/definitions/PlayTransformPartsConfig%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%3E"},"existing":{"$ref":"#/definitions/PlayTransformPartsConfig%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%3E"}}},"postCompare":{"$ref":"#/definitions/PlayTransformPartsConfig%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%3E"}},"title":"PlayTransformOptions"},"PlayTransformPartsConfig<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm)>":{"anyOf":[{"$ref":"#/definitions/PlayTransformPartsArray%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%2CMaybeStageTyped%3E"},{"$ref":"#/definitions/PlayTransformParts%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%2CMaybeStageTyped%3E"}],"description":"Represents the weakly-defined user config. May be an array of parts or one parts object","title":"PlayTransformPartsConfig<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm)>"},"PlayTransformPartsArray<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm),MaybeStageTyped>":{"type":"array","items":{"$ref":"#/definitions/PlayTransformParts%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%2CMaybeStageTyped%3E"},"title":"PlayTransformPartsArray<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm),MaybeStageTyped>"},"PlayTransformParts<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm),MaybeStageTyped>":{"anyOf":[{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"title":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"artists":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"albumArtists":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"album":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"duration":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"meta":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"onSuccess":{"$ref":"#/definitions/FlowControlTerm"},"onFailure":{"$ref":"#/definitions/FlowControlTerm"},"onSkip":{"$ref":"#/definitions/FlowControlTerm"},"failureReturnPartial":{"type":"boolean"},"type":{"$ref":"#/definitions/StageTypeMetadata"},"name":{"type":"string"},"stageHash":{"type":"string"},"score":{"type":"number"}},"required":["type"]},{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"title":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"artists":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"albumArtists":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"album":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"duration":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"meta":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"onSuccess":{"$ref":"#/definitions/FlowControlTerm"},"onFailure":{"$ref":"#/definitions/FlowControlTerm"},"onSkip":{"$ref":"#/definitions/FlowControlTerm"},"failureReturnPartial":{"type":"boolean"},"type":{"$ref":"#/definitions/StageTypeUser"},"name":{"type":"string"},"stageHash":{"type":"string"}},"required":["type"]},{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"title":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"artists":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"albumArtists":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"album":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"duration":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"meta":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"onSuccess":{"$ref":"#/definitions/FlowControlTerm"},"onFailure":{"$ref":"#/definitions/FlowControlTerm"},"onSkip":{"$ref":"#/definitions/FlowControlTerm"},"failureReturnPartial":{"type":"boolean"},"type":{"type":"string","enum":["native"]},"name":{"type":"string"},"stageHash":{"type":"string"}},"required":["type"]},{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"title":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"artists":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"albumArtists":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"album":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"duration":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"meta":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"onSuccess":{"$ref":"#/definitions/FlowControlTerm"},"onFailure":{"$ref":"#/definitions/FlowControlTerm"},"onSkip":{"$ref":"#/definitions/FlowControlTerm"},"failureReturnPartial":{"type":"boolean"},"name":{"type":"string"}}},{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"title":{},"artists":{},"albumArtists":{},"album":{},"duration":{},"meta":{},"onSuccess":{"$ref":"#/definitions/FlowControlTerm"},"onFailure":{"$ref":"#/definitions/FlowControlTerm"},"onSkip":{"$ref":"#/definitions/FlowControlTerm"},"failureReturnPartial":{"type":"boolean"},"type":{"type":"string"},"name":{"type":"string"},"stageHash":{"type":"string"}},"required":["type"]}],"title":"PlayTransformParts<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm),MaybeStageTyped>"},"WhenConditionsConfig":{"$ref":"#/definitions/WhenConditions%3Cstring%3E","title":"WhenConditionsConfig"},"WhenConditions":{"type":"array","items":{"$ref":"#/definitions/WhenParts%3Cstring%3E"},"title":"WhenConditions"},"WhenParts":{"$ref":"#/definitions/PlayTransformPartsAtomic%3Cstring%3E","title":"WhenParts"},"PlayTransformPartsAtomic":{"type":"object","properties":{"title":{"type":"string"},"artists":{"type":"string"},"albumArtists":{"type":"string"},"album":{"type":"string"},"duration":{"type":"string"},"meta":{"type":"string"}},"title":"PlayTransformPartsAtomic"},"Whennable":{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"}},"title":"Whennable"},"FlowControlTerm":{"type":"string","enum":["continue","stop"],"title":"FlowControlTerm"},"StageTypeMetadata":{"type":"string","enum":["spotify","musicbrainz","native"],"title":"StageTypeMetadata"},"SearchAndReplaceTerm":{"anyOf":[{"type":"string"},{"$ref":"#/definitions/ConditionalSearchAndReplaceTerm"}],"title":"SearchAndReplaceTerm"},"ConditionalSearchAndReplaceTerm":{"$ref":"#/definitions/ConditionalSearchAndReplaceRegExp","title":"ConditionalSearchAndReplaceTerm"},"ConditionalSearchAndReplaceRegExp":{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"search":{"anyOf":[{"type":"string"},{"type":"string","format":"regex"}],"description":"The search value to test for\n\nCan be a normal string (converted to a case-sensitive literal) or a valid regular expression as a string, or an actual RegExp object","examples":[["find this string","/some string*/ig"]]},"replace":{"type":"string","description":"The replacement string/value to use when search is found\n\nThis can be a literal string like `'replace with this`, an empty string to remove the search value (`''`), or a special regex value\n\nSee replacement here for more information: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace"},"test":{"$comment":"(obj: SearchAndReplaceRegExp) => boolean","type":"object","properties":{"namedArgs":{"type":"object","properties":{"obj":{"$ref":"#/definitions/SearchAndReplaceRegExp"}},"required":["obj"],"additionalProperties":false}},"description":"An optional function to execute before running this search-and-replace that decides if it should run at all"}},"required":["replace","search"],"title":"ConditionalSearchAndReplaceRegExp"},"SearchAndReplaceRegExp":{"type":"object","properties":{"search":{"anyOf":[{"type":"string"},{"type":"string","format":"regex"}],"description":"The search value to test for\n\nCan be a normal string (converted to a case-sensitive literal) or a valid regular expression as a string, or an actual RegExp object","examples":[["find this string","/some string*/ig"]]},"replace":{"type":"string","description":"The replacement string/value to use when search is found\n\nThis can be a literal string like `'replace with this`, an empty string to remove the search value (`''`), or a special regex value\n\nSee replacement here for more information: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace"},"test":{"$comment":"(obj: SearchAndReplaceRegExp) => boolean","type":"object","properties":{"namedArgs":{"type":"object","properties":{"obj":{"$ref":"#/definitions/SearchAndReplaceRegExp"}},"required":["obj"],"additionalProperties":false}},"description":"An optional function to execute before running this search-and-replace that decides if it should run at all"}},"required":["search","replace"],"title":"SearchAndReplaceRegExp"},"ExternalMetadataTerm":{"anyOf":[{"type":"boolean"},{"not":{}},{"$ref":"#/definitions/Whennable"}],"title":"ExternalMetadataTerm"},"StageTypeUser":{"type":"string","enum":["user"],"title":"StageTypeUser"},"PlexApiSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/PlexApiData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/PlexApiOptions"}},"required":["data"],"title":"PlexApiSourceConfig"},"PlexApiData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"token":{"type":"string"},"url":{"type":"string","description":"http(s)://HOST:PORT of the Plex server to connect to"},"usersAllow":{"anyOf":[{"type":"string"},{"type":"boolean","enum":[true]},{"type":"array","items":{"type":"string"}}],"description":"Only scrobble for specific users (case-insensitive)\n\nIf `true` MS will scrobble activity from all users"},"usersBlock":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Do not scrobble for these users (case-insensitive)"},"devicesAllow":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Only scrobble if device or application name contains strings from this list (case-insensitive)"},"devicesBlock":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Do not scrobble if device or application name contains strings from this list (case-insensitive)"},"librariesAllow":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Only scrobble if library name contains string from this list (case-insensitive)"},"librariesBlock":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Do not scrobble if library name contains strings from this list (case-insensitive)"}},"required":["url"],"title":"PlexApiData"},"PlexApiOptions":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"},"ignoreInvalidCert":{"type":"boolean","description":"Ignore invalid cert errors when connecting to Plex\n\nUseful for Plex servers using \"Required\" Secure Connections with self-signed certificates\n\nDo not enable unless you know you need this.","default":false}},"title":"PlexApiOptions"},"DeezerSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/DeezerData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"}},"required":["data"],"title":"DeezerSourceConfig"},"DeezerData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"clientId":{"type":"string","description":"deezer client id","examples":["a89cba1569901a0671d5a9875fed4be1"]},"clientSecret":{"type":"string","description":"deezer client secret","examples":["ec42e09d5ae0ee0f0816ca151008412a"]},"redirectUri":{"type":"string","description":"deezer redirect URI -- required only if not the default shown here. URI must end in \"callback\"","default":"http://localhost:9078/deezer/callback","examples":["http://localhost:9078/deezer/callback"]}},"required":["clientId","clientSecret"],"title":"DeezerData"},"DeezerInternalSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/DeezerInternalData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/DeezerInternalSourceOptions"}},"required":["data"],"title":"DeezerInternalSourceConfig"},"DeezerInternalData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"arl":{"type":"string","description":"ARL retrieved from Deezer response header"},"userAgent":{"type":"string","description":"User agent","default":"Mozilla/5.0 (X11; Linux i686; rv:135.0) Gecko/20100101 Firefox/135.0"},"accountId":{"type":"string","description":"The ID (USER_ID) of the linked account to monitor. If not set, monitors the main ARL account"}},"required":["arl"],"title":"DeezerInternalData"},"DeezerInternalSourceOptions":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"},"fuzzyDiscoveryIgnore":{"anyOf":[{"type":"boolean"},{"type":"string","enum":["aggressive"]}]}},"title":"DeezerInternalSourceOptions"},"ListenbrainzEndpointSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/ListenbrainzEndpointData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"}},"title":"ListenbrainzEndpointSourceConfig"},"ListenbrainzEndpointData":{"type":"object","properties":{"slug":{"type":["string","null"],"description":"The URL ending that should be used to identify scrobbles for this source\n\nIf you are using multiple Listenbrainz endpoint sources (scrobbles for many users) you can use a slug to match Sources with individual users/origins\n\nExample:\n\n* slug: 'usera' => API URL: http://localhost:9078/api/listenbrainz/usera\n* slug: 'originb' => API URL: http://localhost:9078/api/listenbrainz/originb\n\nIf no slug is found from an extension's incoming webhook event the first Listenbrainz source without a slug will be used"},"token":{"type":["string","null"],"description":"If an LZ submission request contains this token in the Authorization Header it will be used to match the submission with this Source\n\nSee: https://listenbrainz.readthedocs.io/en/latest/users/api/index.html#add-the-user-token-to-your-requests"}},"title":"ListenbrainzEndpointData"},"LastFMEndpointSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/LastFMEndpointData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"}},"title":"LastFMEndpointSourceConfig"},"LastFMEndpointData":{"type":"object","properties":{"slug":{"type":["string","null"],"description":"The URL ending that should be used to identify scrobbles for this source\n\nIf you are using multiple Last.fm endpoint sources (scrobbles for many users) you can use a slug to match Sources with individual users/origins\n\nExample:\n\n* slug: 'usera' => API URL: http://localhost:9078/api/lastfm/usera\n* slug: 'originb' => API URL: http://localhost:9078/api/lastfm/originb\n\nIf no slug is found from an extension's incoming webhook event the first Last.fm source without a slug will be used"}},"title":"LastFMEndpointData"},"SubSonicSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/SubsonicData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"}},"required":["data"],"title":"SubSonicSourceConfig"},"SubsonicData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"url":{"type":"string","description":"URL of the subsonic media server to query","examples":["http://airsonic.local"]},"user":{"type":"string","description":"Username to login to the server with","examples":[["MyUser"]]},"password":{"type":"string","description":"Password for the user to login to the server with","examples":["MyPassword"]},"ignoreTlsErrors":{"type":"boolean","description":"If your subsonic server is using self-signed certs you may need to disable TLS errors in order to get a connection\n\nWARNING: This should be used with caution as your traffic may not be encrypted.","default":false},"legacyAuthentication":{"type":"boolean","description":"Older Subsonic versions, and some badly implemented servers (Nextcloud), use legacy authentication which sends your password in CLEAR TEXT. This is less secure than the newer, recommended hashing authentication method but in some cases it is needed. See \"Authentication\" section here => https://www.subsonic.org/pages/api.jsp\n\nIf this option is not specified it will be turned on if the subsonic server responds with error code 41 \"Token authentication not supported for LDAP users.\" -- See Error Handling section => https://www.subsonic.org/pages/api.jsp","default":false},"usersAllow":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Only scrobble for specific users (case-insensitive)\n\nIf undefined or an empty string/list MS will scrobble activity from all users"}},"required":["url","user","password"],"title":"SubsonicData"},"JellyApiSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/JellyApiData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/JellyApiOptions"}},"required":["data"],"title":"JellyApiSourceConfig"},"JellyApiData":{"type":"object","properties":{"url":{"type":"string","description":"HOST:PORT of the Jellyfin server to connect to"},"user":{"type":"string","description":"The username of the user to authenticate for or track scrobbles for"},"password":{"type":"string","description":"Password of the username to authenticate for\n\nRequired if `apiKey` is not provided."},"apiKey":{"type":"string","description":"API Key to authenticate with.\n\nRequired if `password` is not provided."},"usersAllow":{"anyOf":[{"type":"string"},{"type":"boolean","enum":[true]},{"type":"array","items":{"type":"string"}}],"description":"Only scrobble for specific users (case-insensitive)\n\nIf `true` MS will scrobble activity from all users"},"usersBlock":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Do not scrobble for these users (case-insensitive)"},"devicesAllow":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Only scrobble if device or application name contains strings from this list (case-insensitive)"},"devicesBlock":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Do not scrobble if device or application name contains strings from this list (case-insensitive)"},"librariesAllow":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Only scrobble if library name contains string from this list (case-insensitive)"},"librariesBlock":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Do not scrobble if library name contains strings from this list (case-insensitive)"},"additionalAllowedLibraryTypes":{"type":"array","items":{},"description":"Allow MS to scrobble audio media in libraries classified other than 'music'\n\n`librariesAllow` will achieve the same result as this but this is more convenient if you do not want to explicitly list every library name or are only using `librariesBlock`"},"allowUnknown":{"type":"boolean","description":"Force media with a type of \"Unknown\" to be counted as Audio","default":false,"deprecated":"use allowMediaTypes instead"},"allowMediaTypes":{"anyOf":[{"type":"array","items":{}},{"type":"string"}],"description":"Allow these media types to be scrobbled.\n\nIf not defined or empty, uses 'Audio' as default. If non-empty then *only* uses these types (make sure you include Audio!)\n\nValues are case-insensitive.\n\nSee https://github.com/jellyfin/jellyfin-sdk-typescript/blob/master/src/generated-client/models/media-type.ts#L22 for possible types"},"frontendUrlOverride":{"type":"string","description":"HOST:PORT of the Jellyfin server that your browser will be able to access from the frontend (and thus load images and links from)\nIf unspecified it will use the normal server HOST and PORT from the `url`\nNecessary if you are using a reverse proxy or other network configuration that prevents the frontend from accessing the server directly\n\nENV: JELLYFIN_FRONTEND_URL_OVERRIDE"}},"required":["url","user"],"title":"JellyApiData"},"JellyApiOptions":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"JellyApiOptions"},"LastfmSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/LastFmSourceData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"configureAs":{"type":"string","enum":["source"],"description":"When used in `lastfm.config` this tells multi-scrobbler whether to use this data to configure a source or client.","default":"source","examples":["source"]}},"required":["data"],"title":"LastfmSourceConfig"},"LastFmSourceData":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"apiKey":{"type":"string","description":"API Key generated from Last.fm/Libre.fm account","examples":["787c921a2a2ab42320831aba0c8f2fc2"]},"secret":{"type":"string","description":"Secret generated from Last.fm/Libre.fm account","examples":["ec42e09d5ae0ee0f0816ca151008412a"]},"session":{"type":"string","description":"Optional session id returned from a completed auth flow"},"redirectUri":{"type":"string","description":"Optional URI to use for callback. Specify this if callback should be different than the default. MUST have \"lastfm/callback\" in the URL somewhere.","default":"http://localhost:9078/lastfm/callback","examples":["http://localhost:9078/lastfm/callback"]},"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"}},"required":["apiKey","secret"],"title":"LastFmSourceData"},"LibrefmSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/LibrefmData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"configureAs":{"type":"string","enum":["source"],"description":"When used in `librefm.config` this tells multi-scrobbler whether to use this data to configure a source or client.","default":"source","examples":["source"]}},"required":["data"],"title":"LibrefmSourceConfig"},"LibrefmData":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"apiKey":{"type":"string","description":"Optional Secret for Libre.fm account\n\nThis can be anything, or it will be generated by multi-scrobbler","examples":["anyValue"]},"secret":{"type":"string","description":"Optional Secret for Libre.fm account\n\nThis can be anything, or it will be generated by multi-scrobbler","examples":["anyValue"]},"session":{"type":"string","description":"Optional session id returned from a completed auth flow"},"path":{"type":"string"},"urlBase":{"type":"string","description":"(Optional) The host and path prefix for your Libre.fm instance","default":"https://libre.fm/2.0/"},"redirectUri":{"type":"string","description":"Optional URI to use for callback. Specify this if callback should be different than the default. MUST have \"librefm/callback\" in the URL somewhere.","default":"http://localhost:9078/librefm/callback","examples":["http://localhost:9078/librefm/callback"]}},"title":"LibrefmData"},"YTMusicSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/YTMusicData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"type":"object","properties":{"logAuth":{"type":"boolean","description":"When true MS will log to DEBUG all of the credentials data it receives from YTM"},"logDiff":{"type":"boolean","description":"Always log history diff\n\nBy default MS will log to `WARN` if history diff is inconsistent but does not log if diff is expected (on new tracks found)\nSet this to `true` to ALWAYS log diff on new tracks. Expected diffs will log to `DEBUG` and inconsistent diffs will continue to log to `WARN`","default":false},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}}}},"title":"YTMusicSourceConfig"},"YTMusicData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"cookie":{"type":"string","description":"The cookie retrieved from the Request Headers of music.youtube.com after logging in.\n\nSee https://ytmusicapi.readthedocs.io/en/stable/setup/browser.html#copy-authentication-headers for how to retrieve this value.","examples":["VISITOR_INFO1_LIVE=jMp2xA1Xz2_PbVc; __Secure-3PAPISID=3AxsXpy0M/AkISpjek; ..."]},"clientId":{"type":"string","description":"Google Cloud Console project OAuth Client ID\n\nGenerated from a custom OAuth Client, see docs"},"clientSecret":{"type":"string","description":"Google Cloud Console project OAuth Client Secret\n\nGenerated from a custom OAuth Client, see docs"},"redirectUri":{"type":"string","description":"Google Cloud Console project OAuth Client Authorized redirect URI\n\nGenerated from a custom OAuth Client, see docs. multi-scrobbler will generate a default based on BASE_URL.\nOnly specify this if the default does not work for you."},"innertubeOptions":{"$ref":"#/definitions/InnertubeOptions","description":"Additional options for authorization and tailoring YTM client"}},"title":"YTMusicData"},"InnertubeOptions":{"type":"object","properties":{"po_token":{"type":"string","description":"Proof of Origin token\n\nMay be required if YTM starts returning 403"},"visitor_data":{"type":"string","description":"Visitor ID value found in VISITOR_INFO1_LIVE or visitorData cookie\n\nMay be required if YTM starts returning 403"},"account_index":{"type":"number","description":"If account login results in being able to choose multiple account, use a zero-based index to choose which one to monitor","examples":[0,1]},"location":{"type":"string"},"lang":{"type":"string"},"generate_session_locally":{"type":"boolean"},"device_category":{"type":"string"},"client_type":{"type":"string"},"timezone":{"type":"string"}},"title":"InnertubeOptions"},"MPRISSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/MPRISData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"}},"required":["data"],"title":"MPRISSourceConfig"},"MPRISData":{"type":"object","properties":{"blacklist":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"DO NOT scrobble from any players that START WITH these values, case-insensitive","examples":[["spotify","vlc"]]},"whitelist":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"ONLY from any players that START WITH these values, case-insensitive\n\nIf whitelist is present then blacklist is ignored","examples":[["spotify","vlc"]]}},"title":"MPRISData"},"MopidySourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/MopidyData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"}},"required":["data"],"title":"MopidySourceConfig"},"MopidyData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"url":{"type":"string","description":"URL of the Mopidy HTTP server to connect to\n\nYou MUST have Mopidy-HTTP extension enabled: https://mopidy.com/ext/http\n\nmulti-scrobbler connects to the WebSocket endpoint that ultimately looks like this => `ws://localhost:6680/mopidy/ws/`\n\nThe URL you provide here will have all parts not explicitly defined filled in for you so if these are not the default you must define them.\n\nParts => [default value]\n\n* Protocol => `ws://`\n* Hostname => `localhost`\n* Port => `6680`\n* Path => `/mopidy/ws/`","examples":["ws://localhost:6680/mopidy/ws/"],"default":"ws://localhost:6680/mopidy/ws/"},"uriBlacklist":{"type":"array","items":{"type":"string"},"description":"Do not scrobble tracks whose URI STARTS WITH any of these strings, case-insensitive\n\nEX: Don't scrobble tracks from soundcloud by adding 'soundcloud' to this list.\n\nList is ignored if uriWhitelist is used."},"uriWhitelist":{"type":"array","items":{"type":"string"},"description":"Only scrobble tracks whose URI STARTS WITH any of these strings, case-insensitive\n\nEX: Only scrobble tracks from soundcloud by adding 'soundcloud' to this list."},"albumBlacklist":{"type":"array","items":{"type":"string"},"description":"Remove album data that matches any case-insensitive string from this list when scrobbling,\n\nFor certain sources (Soundcloud) Mopidy does not have all track info (Album) and will instead use \"Soundcloud\" as the Album name. You can prevent multi-scrobbler from using this bad Album data by adding the fake name to this list. Multi-scrobbler will still scrobble the track, just without the bad data.","examples":[["Soundcloud","Mixcloud"]],"default":["Soundcloud"]}},"title":"MopidyData"},"ListenBrainzSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/ListenBrainzSourceData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"configureAs":{"type":"string","enum":["source"],"description":"When used in `listenbrainz.config` this tells multi-scrobbler whether to use this data to configure a source or client.","default":"source","examples":["source"]}},"required":["data"],"title":"ListenBrainzSourceConfig"},"ListenBrainzSourceData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"url":{"type":"string","description":"URL for the ListenBrainz server, if not using the default","examples":["https://api.listenbrainz.org/"],"default":"https://api.listenbrainz.org/"},"token":{"type":"string","description":"User token for the user to scrobble for","examples":["6794186bf-1157-4de6-80e5-uvb411f3ea2b"]},"username":{"type":"string","description":"Username of the user to scrobble for"}},"required":["token","username"],"title":"ListenBrainzSourceData"},"JRiverSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/JRiverData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"}},"required":["data"],"title":"JRiverSourceConfig"},"JRiverData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"url":{"type":"string","description":"URL of the JRiver HTTP server to connect to\n\nmulti-scrobbler connects to the Web Service Interface endpoint that ultimately looks like this => `http://yourDomain:52199/MCWS/v1/`\n\nThe URL you provide here will have all parts not explicitly defined filled in for you so if these are not the default you must define them.\n\nParts => [default value]\n\n* Protocol => `http://`\n* Hostname => `localhost`\n* Port => `52199`\n* Path => `/MCWS/v1/`","examples":["http://localhost:52199/MCWS/v1/"],"default":"http://localhost:52199/MCWS/v1/"},"username":{"type":"string","description":"If you have enabled authentication, the username you set"},"password":{"type":"string","description":"If you have enabled authentication, the password you set"}},"required":["url"],"title":"JRiverData"},"KodiSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/KodiData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"}},"required":["data"],"title":"KodiSourceConfig"},"KodiData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"url":{"type":"string","description":"URL of the Kodi HTTP server to connect to\n\nmulti-scrobbler connects to the Web Service Interface endpoint that ultimately looks like this => `http://yourDomain:8080/jsonrpc`\n\nThe URL you provide here will have all parts not explicitly defined filled in for you so if these are not the default you must define them.\n\nParts => [default value]\n\n* Protocol => `http://`\n* Hostname => `localhost`\n* Port => `8080`\n* Path => `/jsonrpc`","examples":["http://localhost:8080/jsonrpc"],"default":"http://localhost:8080/jsonrpc"},"username":{"type":"string","description":"The username set for Remote Control via Web Sever"},"password":{"type":"string","description":"The password set for Remote Control via Web Sever"}},"required":["url","username","password"],"title":"KodiData"},"WebScrobblerSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/WebScrobblerData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"}},"title":"WebScrobblerSourceConfig"},"WebScrobblerData":{"type":"object","properties":{"slug":{"type":["string","null"],"description":"The URL ending that should be used to identify scrobbles for this source\n\nIn WebScrobbler's Webhook you must set an 'API URL'. All MS WebScrobbler sources must start like:\n\nhttp://localhost:9078/api/webscrobbler\n\nIf you are using multiple WebScrobbler sources (scrobbles for many users) you must use a slug to match Sources with each users extension.\n\nExample:\n\n* slug: 'usera' => API URL: http://localhost:9078/api/webscrobbler/usera\n* slug: 'userb' => API URL: http://localhost:9078/api/webscrobbler/userb\n\nIf no slug is found from an extension's incoming webhook event the first WebScrobbler source without a slug will be used"},"blacklist":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Block scrobbling from specific WebScrobbler Connectors","examples":[["youtube"]]},"whitelist":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Only allow scrobbling from specific WebScrobbler Connectors","examples":[["mixcloud","soundcloud","bandcamp"]]}},"title":"WebScrobblerData"},"ChromecastSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/ChromecastData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"}},"required":["data"],"title":"ChromecastSourceConfig"},"ChromecastData":{"type":"object","properties":{"blacklistDevices":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"DO NOT scrobble from any cast devices that START WITH these values, case-insensitive\n\nUseful when used with auto discovery","examples":[["home-mini","family-tv"]]},"whitelistDevices":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"ONLY scrobble from any cast device that START WITH these values, case-insensitive\n\nIf whitelist is present then blacklist is ignored\n\nUseful when used with auto discovery","examples":[["home-mini","family-tv"]]},"blacklistApps":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"DO NOT scrobble from any application that START WITH these values, case-insensitive","examples":[["spotify","pandora"]]},"whitelistApps":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"ONLY scrobble from any application that START WITH these values, case-insensitive\n\nIf whitelist is present then blacklist is ignored","examples":[["spotify","pandora"]]},"useAvahi":{"type":"boolean","description":"Try to use Avahi and avahi-browse to resolve mDNS devices instead of native mDNS querying\n\nUseful for docker (alpine) container where mDNS resolution is not yet supported. Avahi socket must be exposed to the container and avahi-tools must be installed.","default":false},"useAutoDiscovery":{"type":"boolean","description":"Use mDNS to discovery Google Cast devices on your next automatically?\n\nIf not explicitly set then it is TRUE if `devices` is not set"},"devices":{"type":"array","items":{"$ref":"#/definitions/ChromecastDeviceInfo"},"description":"A list of Google Cast devices to monitor\n\nIf this is used then `useAutoDiscovery` is set to FALSE, if not explicitly set"},"allowUnknownMedia":{"anyOf":[{"type":"boolean"},{"type":"array","items":{"type":"string"}}],"description":"Chromecast Apps report a \"media type\" in the status info returned for whatever is currently playing\n\n* If set to TRUE then Music AND Generic/Unknown media will be tracked for ALL APPS\n* If set to FALSE then only media explicitly typed as Music will be tracked for ALL APPS\n* If set to a list then only Apps whose name contain one of these values, case-insensitive, will have Music AND Generic/Unknown tracked\n\nSee https://developers.google.com/cast/docs/media/messages#MediaInformation \"metadata\" property","default":false},"forceMediaRecognitionOn":{"type":"array","items":{"type":"string"},"description":"Media provided by any App whose name is listed here will ALWAYS be tracked, regardless of the \"media type\" reported\n\nApps will be recognized if they CONTAIN any of these values, case-insensitive"}},"title":"ChromecastData"},"ChromecastDeviceInfo":{"type":"object","properties":{"name":{"type":"string","description":"A friendly name to identify this device","examples":["MySmartTV"]},"address":{"type":"string","description":"The IP address of the device","examples":["192.168.0.115"]}},"required":["name","address"],"title":"ChromecastDeviceInfo"},"MalojaSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/MalojaSourceData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"configureAs":{"type":"string","enum":["source"],"description":"When used in `maloja.config` this tells multi-scrobbler whether to use this data to configure a source or client.","default":"source","examples":["source"]}},"required":["data"],"title":"MalojaSourceConfig"},"MalojaSourceData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"url":{"type":"string","description":"URL for maloja server","examples":["http://localhost:42010"]},"apiKey":{"type":"string","description":"API Key for Maloja server","examples":["myApiKey"]}},"required":["apiKey","url"],"title":"MalojaSourceData"},"MusikcubeSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/MusikcubeData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"}},"required":["data"],"title":"MusikcubeSourceConfig"},"MusikcubeData":{"type":"object","properties":{"url":{"type":"string","description":"URL of the Musikcube Websocket (Metadata) server to connect to\n\nYou MUST have enabled 'metadata' server and set a password: https://github.com/clangen/musikcube/wiki/remote-api-documentation\n * musikcube -> settings -> server setup\n\nThe URL you provide here will have all parts not explicitly defined filled in for you so if these are not the default you must define them.\n\nParts => [default value]\n\n* Protocol => `ws://`\n* Hostname => `localhost`\n* Port => `7905`","examples":["ws://localhost:7905"],"default":"ws://localhost:7905"},"password":{"type":"string","description":"Password set in Musikcube https://github.com/clangen/musikcube/wiki/remote-api-documentation\n\n* musikcube -> settings -> server setup -> password"},"device_id":{"type":"string"}},"required":["password"],"title":"MusikcubeData"},"MusicCastSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/MusicCastData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"}},"required":["data"],"title":"MusicCastSourceConfig"},"MusicCastData":{"type":"object","properties":{"url":{"type":"string","description":"The host or URL of the YamahaExtendedControl endpoint to use","examples":[["192.168.0.101","http://192.168.0.101/YamahaExtendedControl"]]}},"required":["url"],"title":"MusicCastData"},"MPDSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/MPDData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/MPDSourceOptions"}},"required":["data","options"],"title":"MPDSourceConfig"},"MPDData":{"type":"object","properties":{"url":{"type":"string","description":"URL:PORT of the MPD server to connect to\n\nTo use this you must have TCP connections enabled for your MPD server https://mpd.readthedocs.io/en/stable/user.html#client-connections","examples":["localhost:6600"],"default":"localhost:6600"},"path":{"type":"string","description":"If using socket specify the path instead of url.\n\ntrailing `~` is replaced by your home directory"},"password":{"type":"string","description":"Password for the server, if set https://mpd.readthedocs.io/en/stable/user.html#permissions-and-passwords"}},"title":"MPDData"},"MPDSourceOptions":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"MPDSourceOptions"},"VLCSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/VLCData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/VLCSourceOptions"}},"required":["data"],"title":"VLCSourceConfig"},"VLCData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"url":{"type":"string","description":"URL:PORT of the VLC server to connect to\n\nTo use this you must have the Web (http) interface module enabled and a password set https://foxxmd.github.io/multi-scrobbler/docs/configuration#vlc","examples":["localhost:8080"],"default":"localhost:8080"},"password":{"type":"string","description":"Password for the server"}},"required":["password"],"title":"VLCData"},"VLCSourceOptions":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"},"filenamePatterns":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"A list of regular expressions to use to extract metadata (title, album, artist) from a filename\n\nUsed when VLC reports only the filename for the current audio track"},"logFilenamePatterns":{"type":"boolean","description":"Log to DEBUG when a filename-only track is matched or not matched by filenamePatterns","default":false},"dumpVlcMetadata":{"type":"boolean","description":"Dump all the metadata VLC reports for an audio track to DEBUG.\n\nUse this if reporting an issue with VLC not correctly capturing metadata for a track.","default":false}},"title":"VLCSourceOptions"},"IcecastSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/IcecastData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/IcecastSourceOptions"}},"required":["data"],"title":"IcecastSourceConfig"},"IcecastData":{"type":"object","properties":{"sources":{"type":"array","items":{"$ref":"#/definitions/IcecastSource"}},"icestatsEndpoint":{"type":"string"},"statsEndpoint":{"type":"string"},"nextsongsEndpoint":{"type":"string"},"sevenhtmlEndpoint":{"type":"string"},"icyMetaInt":{"type":"number"},"url":{"type":"string","description":"The Icecast stream URL"}},"required":["url"],"title":"IcecastData"},"IcecastSource":{"type":"string","enum":["icy","ogg","icestats","stats","sevenhtml","nextsongs"],"title":"IcecastSource"},"IcecastSourceOptions":{"type":"object","properties":{"systemScrobble":{"type":"boolean","description":"For Sources that support manual listening, should MS default to scrobbling when no user interaction has occurred?\n\nIf not specified MS will use a Source's specific behavior, see Source's documentation."},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"IcecastSourceOptions"},"AzuracastSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/AzuracastData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"}},"required":["data"],"title":"AzuracastSourceConfig"},"AzuracastData":{"type":"object","properties":{"url":{"type":"string","description":"Base URL of the Azuracast instance\n\nThis does NOT include the station. If a station is included it will be ignored. Use `station` field to specify station, if necessary","examples":["https://radio.mydomain.tld","http://localhost:80"]},"station":{"type":"string","description":"The specific station to monitor\n\nScrobbling will only occur if any of the monitor conditions are met AND the station is ONLINE.\n\nTo monitor multiple stations create a Source for each station.","examples":["my-station-1"]},"monitorWhenListeners":{"type":["boolean","number"],"description":"Only activate scrobble monitoring if station\n\n* `true` => has any current listeners\n* `number` => has EQUAL TO or MORE THAN X number of listeners"},"monitorWhenLive":{"type":"boolean","description":"Only activate scrobble monitoring if station has a live DJ/Streamer","default":true},"apiKey":{"type":"string","description":"API Key used to access data about private streams\n\nhttps://www.azuracast.com/docs/developers/apis/#api-authentication"}},"required":["url","station"],"title":"AzuracastData"},"KoitoSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/KoitoSourceData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"configureAs":{"type":"string","enum":["source"],"description":"When used in `koito.config` this tells multi-scrobbler whether to use this data to configure a source or client.","default":"source","examples":["source"]}},"required":["data"],"title":"KoitoSourceConfig"},"KoitoSourceData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"url":{"type":"string","description":"URL for the Koito server","examples":["http://192.168.0.100:4110"]},"token":{"type":"string","description":"User token for the user to scrobble for","examples":["pM195xPV98CDpk0QW47FIIOR8AKATAX5DblBF-Jq0t1MbbKL"]},"username":{"type":"string","description":"Username of the user to scrobble for"}},"required":["token","url","username"],"title":"KoitoSourceData"},"TealSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/TealSourceData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/TealSourceOptions"},"configureAs":{"type":"string","enum":["source"],"description":"Should always be `souce` when using Tealfm as a Source","default":"source","examples":["source"]}},"required":["data"],"title":"TealSourceConfig"},"TealSourceData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"baseUri":{"type":"string","description":"The base URI of the Multi-Scrobbler to use for ATProto OAuth\n\nOnly include this if you want to use OAuth. The URI must be a non-IP/non-local domain using https: protocol."},"identifier":{"type":"string","description":"Identify the account to login as\n\n* For **App Password** Auth - your email\n* For **Oauth** - your handle minus the @"},"appPassword":{"type":"string","description":"The [App Password](https://atproto.com/specs/xrpc#app-passwords) you created for your account\n\nThis is created under https://bsky.app/settings/app-passwords\n\n**Use this if you are self-hosting Multi-Scrobbler on localhost or accessed like http://IP:PORT**"},"serviceAllow":{"type":"array","items":{"type":"string"}},"serviceDeny":{"type":"array","items":{"type":"string"}}},"required":["identifier"],"title":"TealSourceData"},"TealSourceOptions":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"TealSourceOptions"},"RockskySourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/RockskySourceData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/RockskySourceOptions"},"configureAs":{"type":"string","enum":["source"],"description":"When used in `rocksky.config` this tells multi-scrobbler whether to use this data to configure a source or client.","default":"source","examples":["source"]}},"required":["data"],"title":"RockskySourceConfig"},"RockskySourceData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"key":{"type":"string","description":"API Key generated from [API Applications](https://docs.rocksky.app/migrating-from-listenbrainz-to-rocksky-1040189m0) in Rocksky for your account","examples":["6794186bf-1157-4de6-80e5-uvb411f3ea2b"]},"handle":{"type":"string","description":"The **fully-qualified** handle for your ATPRoto/Bluesky account, like:\n\n* alice.bsky.social\n* foxxmd.com\n* mysuer.blacksky.app"}},"required":["handle","key"],"title":"RockskySourceData"},"RockskySourceOptions":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"},"audioScrobblerUrl":{"type":"string","description":"URL for the Rocksky *Listenbrainz* endpoint, if not using the default","examples":["https://audioscrobbler.rocksky.app"],"default":"https://audioscrobbler.rocksky.app"},"apiUrl":{"type":"string","description":"URL for the Rocksky *API* endpoint, if not using the default","examples":["https://api.rocksky.app"],"default":"https://api.rocksky.app"}},"title":"RockskySourceOptions"},"SonosSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/SonosData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/SonosSourceOptions"}},"required":["data"],"title":"SonosSourceConfig"},"SonosData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"host":{"type":"string","description":"IP address of any connected Sonos speaker or device","examples":["192.168.0.170"]},"devicesAllow":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Only scrobble if device name contains strings from this list (case-insensitive)"},"devicesBlock":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Do not scrobble if device name contains strings from this list (case-insensitive)"},"groupsAllow":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Only scrobble if the name of a group the playing device belongs to contains strings from this list (case-insensitive)"},"groupsBlock":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Do not scrobble if the name of a group the playing device belongs to contains strings from this list (case-insensitive)"}},"required":["host"],"title":"SonosData"},"SonosSourceOptions":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"},"logEmptyPlayer":{"type":"boolean"}},"title":"SonosSourceOptions"}}} \ No newline at end of file diff --git a/docsite/tsconfig.json b/docsite/tsconfig.json index bed109a1..77ff3473 100644 --- a/docsite/tsconfig.json +++ b/docsite/tsconfig.json @@ -5,6 +5,6 @@ "baseUrl": ".", "resolveJsonModule": true, // Extending "@tsconfig/docusaurus/tsconfig.json".types with "docusaurus-json-schema-plugin" - "types": ["node", "@docusaurus/module-type-aliases", "@docusaurus/theme-classic", "docusaurus-json-schema-plugin"] + "types": ["node", "@docusaurus/module-type-aliases", "@docusaurus/theme-classic", "docusaurus-json-schema-plugin","docusaurus-plugin-sass"] } } diff --git a/src/backend/common/infrastructure/config/source/plex.ts b/src/backend/common/infrastructure/config/source/plex.ts index 57b91106..4c3e64c6 100644 --- a/src/backend/common/infrastructure/config/source/plex.ts +++ b/src/backend/common/infrastructure/config/source/plex.ts @@ -56,6 +56,8 @@ export interface PlexApiSourceConfig extends CommonSourceConfig { options?: PlexApiOptions } +export type PlexApiSourceConfigs = PlexApiSourceConfig[]; + export interface PlexApiSourceAIOConfig extends PlexApiSourceConfig { type: 'plex' } diff --git a/src/backend/common/schema/aio-client.json b/src/backend/common/schema/aio-client.json index 0d4a97c6..e8778b87 100644 --- a/src/backend/common/schema/aio-client.json +++ b/src/backend/common/schema/aio-client.json @@ -1 +1 @@ -{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"clientDefaults":{"$ref":"#/definitions/RequestRetryOptions"},"clients":{"type":"array","items":{"$ref":"#/definitions/ClientAIOConfig"}}},"definitions":{"RequestRetryOptions":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]}},"title":"RequestRetryOptions"},"ClientAIOConfig":{"anyOf":[{"$ref":"#/definitions/MalojaClientAIOConfig"},{"$ref":"#/definitions/LastfmClientAIOConfig"},{"$ref":"#/definitions/LibrefmClientAIOConfig"},{"$ref":"#/definitions/ListenBrainzClientAIOConfig"},{"$ref":"#/definitions/KoitoClientAIOConfig"},{"$ref":"#/definitions/TealClientAIOConfig"},{"$ref":"#/definitions/RockSkyClientAIOConfig"}],"title":"ClientAIOConfig"},"MalojaClientAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this client. Used with sources to restrict where scrobbles are sent.","examples":["MyConfig"]},"data":{"$ref":"#/definitions/MalojaClientData","description":"Specific data required to configure this client"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"options":{"$ref":"#/definitions/CommonClientOptions"},"configureAs":{"type":"string","enum":["client","source"],"description":"Should always be `client` when using Maloja as a client","default":"client","examples":["client"]},"type":{"type":"string","enum":["maloja"]}},"required":["data","name","type"],"title":"MalojaClientAIOConfig"},"MalojaClientData":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"url":{"type":"string","description":"URL for maloja server","examples":["http://localhost:42010"]},"apiKey":{"type":"string","description":"API Key for Maloja server","examples":["myApiKey"]}},"required":["apiKey","url"],"title":"MalojaClientData"},"CommonClientOptions":{"type":"object","properties":{"refreshEnabled":{"type":"boolean","description":"Try to get fresh scrobble history from client when tracks to be scrobbled are newer than the last scrobble found in client history","default":true,"examples":[true]},"refreshStaleAfter":{"type":"number","description":"Refresh scrobbled plays from upstream service if last refresh was at least X seconds ago\n\n**In most case this setting does NOT need to be changed.** The default value is sufficient for the majority of use-cases. Increasing this setting may increase upstream service load and slow down scrobbles.\n\nThis setting should only be changed in specific scenarios where MS is handling multiple \"relaying\" client-services (IE lfm -> lz -> lfm) and there is the potential for a client to be out of sync after more than a few seconds.","examples":[60],"default":60},"refreshMinInterval":{"type":"number","description":"Minimum time (milliseconds) required to pass before upstream scrobbles can be refreshed.\n\n**In most case this setting does NOT need to be changed.** This will always be equal to or smaller than `refreshStaleAfter`.","default":5000,"examples":[5000]},"refreshInitialCount":{"type":"number","description":"The number of tracks to retrieve on initial refresh (related to scrobbleBacklogCount). If not specified this is the maximum supported by the client in 1 API call."},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"checkExistingScrobbles":{"type":"boolean","description":"Check client for an existing scrobble at the same recorded time as the \"new\" track to be scrobbled. If an existing scrobble is found this track is not track scrobbled.","default":true,"examples":[true]},"verbose":{"type":"object","properties":{"match":{"$ref":"#/definitions/MatchLoggingOptions"}},"description":"Options used for increasing verbosity of logging in MS (used for debugging)"},"deadLetterRetries":{"type":"number","description":"Number of times MS should automatically retry scrobbles in dead letter queue","default":1,"examples":[1]},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"CommonClientOptions"},"MatchLoggingOptions":{"type":"object","properties":{"onNoMatch":{"type":"boolean","description":"Log to DEBUG when a new track does NOT match an existing scrobble","default":false,"examples":[false]},"onMatch":{"type":"boolean","description":"Log to DEBUG when a new track DOES match an existing scrobble","default":false,"examples":[false]},"confidenceBreakdown":{"type":"boolean","description":"Include confidence breakdowns in track match logging, if applicable","default":false,"examples":[false]}},"description":"Scrobble matching (between new source track and existing client scrobbles) logging options. Used for debugging.","title":"MatchLoggingOptions"},"PlayTransformOptions":{"type":"object","properties":{"log":{"anyOf":[{"type":"boolean"},{"type":"string","enum":["all"]}]},"preCompare":{"$ref":"#/definitions/PlayTransformPartsConfig%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%3E"},"compare":{"type":"object","properties":{"candidate":{"$ref":"#/definitions/PlayTransformPartsConfig%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%3E"},"existing":{"$ref":"#/definitions/PlayTransformPartsConfig%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%3E"}}},"postCompare":{"$ref":"#/definitions/PlayTransformPartsConfig%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%3E"}},"title":"PlayTransformOptions"},"PlayTransformPartsConfig<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm)>":{"anyOf":[{"$ref":"#/definitions/PlayTransformPartsArray%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%2CMaybeStageTyped%3E"},{"$ref":"#/definitions/PlayTransformParts%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%2CMaybeStageTyped%3E"}],"description":"Represents the weakly-defined user config. May be an array of parts or one parts object","title":"PlayTransformPartsConfig<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm)>"},"PlayTransformPartsArray<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm),MaybeStageTyped>":{"type":"array","items":{"$ref":"#/definitions/PlayTransformParts%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%2CMaybeStageTyped%3E"},"title":"PlayTransformPartsArray<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm),MaybeStageTyped>"},"PlayTransformParts<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm),MaybeStageTyped>":{"anyOf":[{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"title":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"artists":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"albumArtists":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"album":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"duration":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"meta":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"onSuccess":{"$ref":"#/definitions/FlowControlTerm"},"onFailure":{"$ref":"#/definitions/FlowControlTerm"},"onSkip":{"$ref":"#/definitions/FlowControlTerm"},"failureReturnPartial":{"type":"boolean"},"type":{"$ref":"#/definitions/StageTypeMetadata"},"name":{"type":"string"},"stageHash":{"type":"string"},"score":{"type":"number"}},"required":["type"]},{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"title":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"artists":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"albumArtists":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"album":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"duration":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"meta":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"onSuccess":{"$ref":"#/definitions/FlowControlTerm"},"onFailure":{"$ref":"#/definitions/FlowControlTerm"},"onSkip":{"$ref":"#/definitions/FlowControlTerm"},"failureReturnPartial":{"type":"boolean"},"type":{"$ref":"#/definitions/StageTypeUser"},"name":{"type":"string"},"stageHash":{"type":"string"}},"required":["type"]},{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"title":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"artists":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"albumArtists":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"album":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"duration":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"meta":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"onSuccess":{"$ref":"#/definitions/FlowControlTerm"},"onFailure":{"$ref":"#/definitions/FlowControlTerm"},"onSkip":{"$ref":"#/definitions/FlowControlTerm"},"failureReturnPartial":{"type":"boolean"},"type":{"type":"string","enum":["native"]},"name":{"type":"string"},"stageHash":{"type":"string"}},"required":["type"]},{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"title":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"artists":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"albumArtists":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"album":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"duration":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"meta":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"onSuccess":{"$ref":"#/definitions/FlowControlTerm"},"onFailure":{"$ref":"#/definitions/FlowControlTerm"},"onSkip":{"$ref":"#/definitions/FlowControlTerm"},"failureReturnPartial":{"type":"boolean"},"name":{"type":"string"}}},{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"title":{},"artists":{},"albumArtists":{},"album":{},"duration":{},"meta":{},"onSuccess":{"$ref":"#/definitions/FlowControlTerm"},"onFailure":{"$ref":"#/definitions/FlowControlTerm"},"onSkip":{"$ref":"#/definitions/FlowControlTerm"},"failureReturnPartial":{"type":"boolean"},"type":{"type":"string"},"name":{"type":"string"},"stageHash":{"type":"string"}},"required":["type"]}],"title":"PlayTransformParts<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm),MaybeStageTyped>"},"WhenConditionsConfig":{"$ref":"#/definitions/WhenConditions%3Cstring%3E","title":"WhenConditionsConfig"},"WhenConditions":{"type":"array","items":{"$ref":"#/definitions/WhenParts%3Cstring%3E"},"title":"WhenConditions"},"WhenParts":{"$ref":"#/definitions/PlayTransformPartsAtomic%3Cstring%3E","title":"WhenParts"},"PlayTransformPartsAtomic":{"type":"object","properties":{"title":{"type":"string"},"artists":{"type":"string"},"albumArtists":{"type":"string"},"album":{"type":"string"},"duration":{"type":"string"},"meta":{"type":"string"}},"title":"PlayTransformPartsAtomic"},"Whennable":{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"}},"title":"Whennable"},"FlowControlTerm":{"type":"string","enum":["continue","stop"],"title":"FlowControlTerm"},"StageTypeMetadata":{"type":"string","enum":["spotify","musicbrainz","native"],"title":"StageTypeMetadata"},"SearchAndReplaceTerm":{"anyOf":[{"type":"string"},{"$ref":"#/definitions/ConditionalSearchAndReplaceTerm"}],"title":"SearchAndReplaceTerm"},"ConditionalSearchAndReplaceTerm":{"$ref":"#/definitions/ConditionalSearchAndReplaceRegExp","title":"ConditionalSearchAndReplaceTerm"},"ConditionalSearchAndReplaceRegExp":{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"search":{"anyOf":[{"type":"string"},{"type":"string","format":"regex"}],"description":"The search value to test for\n\nCan be a normal string (converted to a case-sensitive literal) or a valid regular expression as a string, or an actual RegExp object","examples":[["find this string","/some string*/ig"]]},"replace":{"type":"string","description":"The replacement string/value to use when search is found\n\nThis can be a literal string like `'replace with this`, an empty string to remove the search value (`''`), or a special regex value\n\nSee replacement here for more information: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace"},"test":{"$comment":"(obj: SearchAndReplaceRegExp) => boolean","type":"object","properties":{"namedArgs":{"type":"object","properties":{"obj":{"$ref":"#/definitions/SearchAndReplaceRegExp"}},"required":["obj"],"additionalProperties":false}},"description":"An optional function to execute before running this search-and-replace that decides if it should run at all"}},"required":["replace","search"],"title":"ConditionalSearchAndReplaceRegExp"},"SearchAndReplaceRegExp":{"type":"object","properties":{"search":{"anyOf":[{"type":"string"},{"type":"string","format":"regex"}],"description":"The search value to test for\n\nCan be a normal string (converted to a case-sensitive literal) or a valid regular expression as a string, or an actual RegExp object","examples":[["find this string","/some string*/ig"]]},"replace":{"type":"string","description":"The replacement string/value to use when search is found\n\nThis can be a literal string like `'replace with this`, an empty string to remove the search value (`''`), or a special regex value\n\nSee replacement here for more information: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace"},"test":{"$comment":"(obj: SearchAndReplaceRegExp) => boolean","type":"object","properties":{"namedArgs":{"type":"object","properties":{"obj":{"$ref":"#/definitions/SearchAndReplaceRegExp"}},"required":["obj"],"additionalProperties":false}},"description":"An optional function to execute before running this search-and-replace that decides if it should run at all"}},"required":["search","replace"],"title":"SearchAndReplaceRegExp"},"ExternalMetadataTerm":{"anyOf":[{"type":"boolean"},{"not":{}},{"$ref":"#/definitions/Whennable"}],"title":"ExternalMetadataTerm"},"StageTypeUser":{"type":"string","enum":["user"],"title":"StageTypeUser"},"LastfmClientAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this client. Used with sources to restrict where scrobbles are sent.","examples":["MyConfig"]},"data":{"$ref":"#/definitions/LastfmData","description":"Specific data required to configure this client"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"options":{"$ref":"#/definitions/LastfmClientOptions"},"configureAs":{"type":"string","enum":["client","source"],"description":"Should always be `client` when using LastFM as a client","default":"client","examples":["client"]},"type":{"type":"string","enum":["lastfm"]}},"required":["data","name","type"],"title":"LastfmClientAIOConfig"},"LastfmData":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"apiKey":{"type":"string","description":"API Key generated from Last.fm/Libre.fm account","examples":["787c921a2a2ab42320831aba0c8f2fc2"]},"secret":{"type":"string","description":"Secret generated from Last.fm/Libre.fm account","examples":["ec42e09d5ae0ee0f0816ca151008412a"]},"session":{"type":"string","description":"Optional session id returned from a completed auth flow"},"redirectUri":{"type":"string","description":"Optional URI to use for callback. Specify this if callback should be different than the default. MUST have \"lastfm/callback\" in the URL somewhere.","default":"http://localhost:9078/lastfm/callback","examples":["http://localhost:9078/lastfm/callback"]}},"required":["apiKey","secret"],"title":"LastfmData"},"LastfmClientOptions":{"type":"object","properties":{"nowPlaying":{"anyOf":[{"type":"boolean"},{"type":"array","items":{"type":"string"}}],"description":"Configure if this Client should report Now Playing from Sources that can scrobble to it\n\n* `true` (default) => Report Now Playing from any eligible Source. \n * If multiple Sources are Playing then reported Play is based on alphabetical order of Source names\n* `false` => Do not report Now Playing\n* `string` list => list of Source `names` that should be allowed to report Now Playing. Order of list determine priority of Play to Report.","default":true},"refreshEnabled":{"type":"boolean","description":"Try to get fresh scrobble history from client when tracks to be scrobbled are newer than the last scrobble found in client history","default":true,"examples":[true]},"refreshStaleAfter":{"type":"number","description":"Refresh scrobbled plays from upstream service if last refresh was at least X seconds ago\n\n**In most case this setting does NOT need to be changed.** The default value is sufficient for the majority of use-cases. Increasing this setting may increase upstream service load and slow down scrobbles.\n\nThis setting should only be changed in specific scenarios where MS is handling multiple \"relaying\" client-services (IE lfm -> lz -> lfm) and there is the potential for a client to be out of sync after more than a few seconds.","examples":[60],"default":60},"refreshMinInterval":{"type":"number","description":"Minimum time (milliseconds) required to pass before upstream scrobbles can be refreshed.\n\n**In most case this setting does NOT need to be changed.** This will always be equal to or smaller than `refreshStaleAfter`.","default":5000,"examples":[5000]},"refreshInitialCount":{"type":"number","description":"The number of tracks to retrieve on initial refresh (related to scrobbleBacklogCount). If not specified this is the maximum supported by the client in 1 API call."},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"checkExistingScrobbles":{"type":"boolean","description":"Check client for an existing scrobble at the same recorded time as the \"new\" track to be scrobbled. If an existing scrobble is found this track is not track scrobbled.","default":true,"examples":[true]},"verbose":{"type":"object","properties":{"match":{"$ref":"#/definitions/MatchLoggingOptions"}},"description":"Options used for increasing verbosity of logging in MS (used for debugging)"},"deadLetterRetries":{"type":"number","description":"Number of times MS should automatically retry scrobbles in dead letter queue","default":1,"examples":[1]},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"LastfmClientOptions"},"LibrefmClientAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this client. Used with sources to restrict where scrobbles are sent.","examples":["MyConfig"]},"data":{"$ref":"#/definitions/LibrefmData","description":"Specific data required to configure this client"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"options":{"$ref":"#/definitions/LibrefmClientOptions"},"configureAs":{"type":"string","enum":["client","source"],"description":"Should always be `client` when using Librefm as a client","default":"client","examples":["client"]},"type":{"type":"string","enum":["librefm"]}},"required":["data","name","type"],"title":"LibrefmClientAIOConfig"},"LibrefmData":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"apiKey":{"type":"string","description":"Optional Secret for Libre.fm account\n\nThis can be anything, or it will be generated by multi-scrobbler","examples":["anyValue"]},"secret":{"type":"string","description":"Optional Secret for Libre.fm account\n\nThis can be anything, or it will be generated by multi-scrobbler","examples":["anyValue"]},"session":{"type":"string","description":"Optional session id returned from a completed auth flow"},"path":{"type":"string"},"urlBase":{"type":"string","description":"(Optional) The host and path prefix for your Libre.fm instance","default":"https://libre.fm/2.0/"},"redirectUri":{"type":"string","description":"Optional URI to use for callback. Specify this if callback should be different than the default. MUST have \"librefm/callback\" in the URL somewhere.","default":"http://localhost:9078/librefm/callback","examples":["http://localhost:9078/librefm/callback"]}},"title":"LibrefmData"},"LibrefmClientOptions":{"type":"object","properties":{"nowPlaying":{"anyOf":[{"type":"boolean"},{"type":"array","items":{"type":"string"}}],"description":"Configure if this Client should report Now Playing from Sources that can scrobble to it\n\n* `true` (default) => Report Now Playing from any eligible Source. \n * If multiple Sources are Playing then reported Play is based on alphabetical order of Source names\n* `false` => Do not report Now Playing\n* `string` list => list of Source `names` that should be allowed to report Now Playing. Order of list determine priority of Play to Report.","default":true},"refreshEnabled":{"type":"boolean","description":"Try to get fresh scrobble history from client when tracks to be scrobbled are newer than the last scrobble found in client history","default":true,"examples":[true]},"refreshStaleAfter":{"type":"number","description":"Refresh scrobbled plays from upstream service if last refresh was at least X seconds ago\n\n**In most case this setting does NOT need to be changed.** The default value is sufficient for the majority of use-cases. Increasing this setting may increase upstream service load and slow down scrobbles.\n\nThis setting should only be changed in specific scenarios where MS is handling multiple \"relaying\" client-services (IE lfm -> lz -> lfm) and there is the potential for a client to be out of sync after more than a few seconds.","examples":[60],"default":60},"refreshMinInterval":{"type":"number","description":"Minimum time (milliseconds) required to pass before upstream scrobbles can be refreshed.\n\n**In most case this setting does NOT need to be changed.** This will always be equal to or smaller than `refreshStaleAfter`.","default":5000,"examples":[5000]},"refreshInitialCount":{"type":"number","description":"The number of tracks to retrieve on initial refresh (related to scrobbleBacklogCount). If not specified this is the maximum supported by the client in 1 API call."},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"checkExistingScrobbles":{"type":"boolean","description":"Check client for an existing scrobble at the same recorded time as the \"new\" track to be scrobbled. If an existing scrobble is found this track is not track scrobbled.","default":true,"examples":[true]},"verbose":{"type":"object","properties":{"match":{"$ref":"#/definitions/MatchLoggingOptions"}},"description":"Options used for increasing verbosity of logging in MS (used for debugging)"},"deadLetterRetries":{"type":"number","description":"Number of times MS should automatically retry scrobbles in dead letter queue","default":1,"examples":[1]},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"LibrefmClientOptions"},"ListenBrainzClientAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this client. Used with sources to restrict where scrobbles are sent.","examples":["MyConfig"]},"data":{"$ref":"#/definitions/ListenBrainzClientData","description":"Specific data required to configure this client"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"options":{"$ref":"#/definitions/CommonClientOptions"},"configureAs":{"type":"string","enum":["client","source"],"description":"Should always be `client` when using Listenbrainz as a client","default":"client","examples":["client"]},"type":{"type":"string","enum":["listenbrainz"]}},"required":["data","name","type"],"title":"ListenBrainzClientAIOConfig"},"ListenBrainzClientData":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"url":{"type":"string","description":"URL for the ListenBrainz server, if not using the default","examples":["https://api.listenbrainz.org/"],"default":"https://api.listenbrainz.org/"},"token":{"type":"string","description":"User token for the user to scrobble for","examples":["6794186bf-1157-4de6-80e5-uvb411f3ea2b"]},"username":{"type":"string","description":"Username of the user to scrobble for"}},"required":["token","username"],"title":"ListenBrainzClientData"},"KoitoClientAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this client. Used with sources to restrict where scrobbles are sent.","examples":["MyConfig"]},"data":{"$ref":"#/definitions/KoitoClientData","description":"Specific data required to configure this client"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"options":{"$ref":"#/definitions/CommonClientOptions"},"configureAs":{"type":"string","enum":["client","source"],"description":"Should always be `client` when using Koito as a client","default":"client","examples":["client"]},"type":{"type":"string","enum":["koito"]}},"required":["data","name","type"],"title":"KoitoClientAIOConfig"},"KoitoClientData":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"url":{"type":"string","description":"URL for the Koito server","examples":["http://192.168.0.100:4110"]},"token":{"type":"string","description":"User token for the user to scrobble for","examples":["pM195xPV98CDpk0QW47FIIOR8AKATAX5DblBF-Jq0t1MbbKL"]},"username":{"type":"string","description":"Username of the user to scrobble for"}},"required":["token","url","username"],"title":"KoitoClientData"},"TealClientAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this client. Used with sources to restrict where scrobbles are sent.","examples":["MyConfig"]},"data":{"$ref":"#/definitions/TealClientData","description":"Specific data required to configure this client"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"options":{"$ref":"#/definitions/TealClientOptions"},"configureAs":{"type":"string","enum":["client","source"],"description":"Should always be `client` when using Tealfm as a client","default":"client","examples":["client"]},"type":{"type":"string","enum":["tealfm"]}},"required":["data","name","type"],"title":"TealClientAIOConfig"},"TealClientData":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"baseUri":{"type":"string","description":"The base URI of the Multi-Scrobbler to use for ATProto OAuth\n\nOnly include this if you want to use OAuth. The URI must be a non-IP/non-local domain using https: protocol."},"identifier":{"type":"string","description":"Identify the account to login as\n\n* For **App Password** Auth - your email\n* For **Oauth** - your handle minus the @"},"appPassword":{"type":"string","description":"The [App Password](https://atproto.com/specs/xrpc#app-passwords) you created for your account\n\nThis is created under https://bsky.app/settings/app-passwords\n\n**Use this if you are self-hosting Multi-Scrobbler on localhost or accessed like http://IP:PORT**"}},"required":["identifier"],"title":"TealClientData"},"TealClientOptions":{"type":"object","properties":{"refreshEnabled":{"type":"boolean","description":"Try to get fresh scrobble history from client when tracks to be scrobbled are newer than the last scrobble found in client history","default":true,"examples":[true]},"refreshStaleAfter":{"type":"number","description":"Refresh scrobbled plays from upstream service if last refresh was at least X seconds ago\n\n**In most case this setting does NOT need to be changed.** The default value is sufficient for the majority of use-cases. Increasing this setting may increase upstream service load and slow down scrobbles.\n\nThis setting should only be changed in specific scenarios where MS is handling multiple \"relaying\" client-services (IE lfm -> lz -> lfm) and there is the potential for a client to be out of sync after more than a few seconds.","examples":[60],"default":60},"refreshMinInterval":{"type":"number","description":"Minimum time (milliseconds) required to pass before upstream scrobbles can be refreshed.\n\n**In most case this setting does NOT need to be changed.** This will always be equal to or smaller than `refreshStaleAfter`.","default":5000,"examples":[5000]},"refreshInitialCount":{"type":"number","description":"The number of tracks to retrieve on initial refresh (related to scrobbleBacklogCount). If not specified this is the maximum supported by the client in 1 API call."},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"checkExistingScrobbles":{"type":"boolean","description":"Check client for an existing scrobble at the same recorded time as the \"new\" track to be scrobbled. If an existing scrobble is found this track is not track scrobbled.","default":true,"examples":[true]},"verbose":{"type":"object","properties":{"match":{"$ref":"#/definitions/MatchLoggingOptions"}},"description":"Options used for increasing verbosity of logging in MS (used for debugging)"},"deadLetterRetries":{"type":"number","description":"Number of times MS should automatically retry scrobbles in dead letter queue","default":1,"examples":[1]},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"TealClientOptions"},"RockSkyClientAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this client. Used with sources to restrict where scrobbles are sent.","examples":["MyConfig"]},"data":{"$ref":"#/definitions/RockSkyClientData","description":"Specific data required to configure this client"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"options":{"$ref":"#/definitions/RockSkyClientOptions"},"configureAs":{"type":"string","enum":["client","source"],"description":"Should always be `client` when using RockSky as a client","default":"client","examples":["client"]},"type":{"type":"string","enum":["rocksky"]}},"required":["data","name","type"],"title":"RockSkyClientAIOConfig"},"RockSkyClientData":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"key":{"type":"string","description":"API Key generated from [API Applications](https://docs.rocksky.app/migrating-from-listenbrainz-to-rocksky-1040189m0) in Rocksky for your account","examples":["6794186bf-1157-4de6-80e5-uvb411f3ea2b"]},"handle":{"type":"string","description":"The **fully-qualified** handle for your ATPRoto/Bluesky account, like:\n\n* alice.bsky.social\n* foxxmd.com\n* mysuer.blacksky.app"}},"required":["handle","key"],"title":"RockSkyClientData"},"RockSkyClientOptions":{"type":"object","properties":{"nowPlaying":{"anyOf":[{"type":"boolean"},{"type":"array","items":{"type":"string"}}],"description":"Configure if this Client should report Now Playing from Sources that can scrobble to it\n\n* `true` (default) => Report Now Playing from any eligible Source. \n * If multiple Sources are Playing then reported Play is based on alphabetical order of Source names\n* `false` => Do not report Now Playing\n* `string` list => list of Source `names` that should be allowed to report Now Playing. Order of list determine priority of Play to Report.","default":true},"refreshEnabled":{"type":"boolean","description":"Try to get fresh scrobble history from client when tracks to be scrobbled are newer than the last scrobble found in client history","default":true,"examples":[true]},"refreshStaleAfter":{"type":"number","description":"Refresh scrobbled plays from upstream service if last refresh was at least X seconds ago\n\n**In most case this setting does NOT need to be changed.** The default value is sufficient for the majority of use-cases. Increasing this setting may increase upstream service load and slow down scrobbles.\n\nThis setting should only be changed in specific scenarios where MS is handling multiple \"relaying\" client-services (IE lfm -> lz -> lfm) and there is the potential for a client to be out of sync after more than a few seconds.","examples":[60],"default":60},"refreshMinInterval":{"type":"number","description":"Minimum time (milliseconds) required to pass before upstream scrobbles can be refreshed.\n\n**In most case this setting does NOT need to be changed.** This will always be equal to or smaller than `refreshStaleAfter`.","default":5000,"examples":[5000]},"refreshInitialCount":{"type":"number","description":"The number of tracks to retrieve on initial refresh (related to scrobbleBacklogCount). If not specified this is the maximum supported by the client in 1 API call."},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"checkExistingScrobbles":{"type":"boolean","description":"Check client for an existing scrobble at the same recorded time as the \"new\" track to be scrobbled. If an existing scrobble is found this track is not track scrobbled.","default":true,"examples":[true]},"verbose":{"type":"object","properties":{"match":{"$ref":"#/definitions/MatchLoggingOptions"}},"description":"Options used for increasing verbosity of logging in MS (used for debugging)"},"deadLetterRetries":{"type":"number","description":"Number of times MS should automatically retry scrobbles in dead letter queue","default":1,"examples":[1]},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"},"audioScrobblerUrl":{"type":"string","description":"URL for the Rocksky *Listenbrainz* endpoint, if not using the default","examples":["https://audioscrobbler.rocksky.app"],"default":"https://audioscrobbler.rocksky.app"},"apiUrl":{"type":"string","description":"URL for the Rocksky *API* endpoint, if not using the default","examples":["https://api.rocksky.app"],"default":"https://api.rocksky.app"}},"title":"RockSkyClientOptions"}}} \ No newline at end of file +{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"clientDefaults":{"$ref":"#/definitions/RequestRetryOptions"},"clients":{"type":"array","items":{"$ref":"#/definitions/ClientAIOConfig"}}},"definitions":{"RequestRetryOptions":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]}},"title":"RequestRetryOptions"},"ClientAIOConfig":{"anyOf":[{"$ref":"#/definitions/MalojaClientAIOConfig"},{"$ref":"#/definitions/LastfmClientAIOConfig"},{"$ref":"#/definitions/LibrefmClientAIOConfig"},{"$ref":"#/definitions/ListenBrainzClientAIOConfig"},{"$ref":"#/definitions/KoitoClientAIOConfig"},{"$ref":"#/definitions/TealClientAIOConfig"},{"$ref":"#/definitions/RockSkyClientAIOConfig"},{"$ref":"#/definitions/DiscordClientAIOConfig"}],"title":"ClientAIOConfig"},"MalojaClientAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this client. Used with sources to restrict where scrobbles are sent.","examples":["MyConfig"]},"data":{"$ref":"#/definitions/MalojaClientData","description":"Specific data required to configure this client"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"options":{"$ref":"#/definitions/CommonClientOptions"},"configureAs":{"type":"string","enum":["client","source"],"description":"Should always be `client` when using Maloja as a client","default":"client","examples":["client"]},"type":{"type":"string","enum":["maloja"]}},"required":["data","name","type"],"title":"MalojaClientAIOConfig"},"MalojaClientData":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"url":{"type":"string","description":"URL for maloja server","examples":["http://localhost:42010"]},"apiKey":{"type":"string","description":"API Key for Maloja server","examples":["myApiKey"]}},"required":["apiKey","url"],"title":"MalojaClientData"},"CommonClientOptions":{"type":"object","properties":{"refreshEnabled":{"type":"boolean","description":"Try to get fresh scrobble history from client when tracks to be scrobbled are newer than the last scrobble found in client history","default":true,"examples":[true]},"refreshStaleAfter":{"type":"number","description":"Refresh scrobbled plays from upstream service if last refresh was at least X seconds ago\n\n**In most case this setting does NOT need to be changed.** The default value is sufficient for the majority of use-cases. Increasing this setting may increase upstream service load and slow down scrobbles.\n\nThis setting should only be changed in specific scenarios where MS is handling multiple \"relaying\" client-services (IE lfm -> lz -> lfm) and there is the potential for a client to be out of sync after more than a few seconds.","examples":[60],"default":60},"refreshMinInterval":{"type":"number","description":"Minimum time (milliseconds) required to pass before upstream scrobbles can be refreshed.\n\n**In most case this setting does NOT need to be changed.** This will always be equal to or smaller than `refreshStaleAfter`.","default":5000,"examples":[5000]},"refreshInitialCount":{"type":"number","description":"The number of tracks to retrieve on initial refresh (related to scrobbleBacklogCount). If not specified this is the maximum supported by the client in 1 API call."},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"checkExistingScrobbles":{"type":"boolean","description":"Check client for an existing scrobble at the same recorded time as the \"new\" track to be scrobbled. If an existing scrobble is found this track is not track scrobbled.","default":true,"examples":[true]},"verbose":{"type":"object","properties":{"match":{"$ref":"#/definitions/MatchLoggingOptions"}},"description":"Options used for increasing verbosity of logging in MS (used for debugging)"},"deadLetterRetries":{"type":"number","description":"Number of times MS should automatically retry scrobbles in dead letter queue","default":1,"examples":[1]},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"CommonClientOptions"},"MatchLoggingOptions":{"type":"object","properties":{"onNoMatch":{"type":"boolean","description":"Log to DEBUG when a new track does NOT match an existing scrobble","default":false,"examples":[false]},"onMatch":{"type":"boolean","description":"Log to DEBUG when a new track DOES match an existing scrobble","default":false,"examples":[false]},"confidenceBreakdown":{"type":"boolean","description":"Include confidence breakdowns in track match logging, if applicable","default":false,"examples":[false]}},"description":"Scrobble matching (between new source track and existing client scrobbles) logging options. Used for debugging.","title":"MatchLoggingOptions"},"PlayTransformOptions":{"type":"object","properties":{"log":{"anyOf":[{"type":"boolean"},{"type":"string","enum":["all"]}]},"preCompare":{"$ref":"#/definitions/PlayTransformPartsConfig%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%3E"},"compare":{"type":"object","properties":{"candidate":{"$ref":"#/definitions/PlayTransformPartsConfig%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%3E"},"existing":{"$ref":"#/definitions/PlayTransformPartsConfig%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%3E"}}},"postCompare":{"$ref":"#/definitions/PlayTransformPartsConfig%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%3E"}},"title":"PlayTransformOptions"},"PlayTransformPartsConfig<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm)>":{"anyOf":[{"$ref":"#/definitions/PlayTransformPartsArray%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%2CMaybeStageTyped%3E"},{"$ref":"#/definitions/PlayTransformParts%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%2CMaybeStageTyped%3E"}],"description":"Represents the weakly-defined user config. May be an array of parts or one parts object","title":"PlayTransformPartsConfig<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm)>"},"PlayTransformPartsArray<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm),MaybeStageTyped>":{"type":"array","items":{"$ref":"#/definitions/PlayTransformParts%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%2CMaybeStageTyped%3E"},"title":"PlayTransformPartsArray<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm),MaybeStageTyped>"},"PlayTransformParts<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm),MaybeStageTyped>":{"anyOf":[{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"title":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"artists":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"albumArtists":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"album":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"duration":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"meta":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"onSuccess":{"$ref":"#/definitions/FlowControlTerm"},"onFailure":{"$ref":"#/definitions/FlowControlTerm"},"onSkip":{"$ref":"#/definitions/FlowControlTerm"},"failureReturnPartial":{"type":"boolean"},"type":{"$ref":"#/definitions/StageTypeMetadata"},"name":{"type":"string"},"stageHash":{"type":"string"},"score":{"type":"number"}},"required":["type"]},{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"title":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"artists":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"albumArtists":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"album":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"duration":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"meta":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"onSuccess":{"$ref":"#/definitions/FlowControlTerm"},"onFailure":{"$ref":"#/definitions/FlowControlTerm"},"onSkip":{"$ref":"#/definitions/FlowControlTerm"},"failureReturnPartial":{"type":"boolean"},"type":{"$ref":"#/definitions/StageTypeUser"},"name":{"type":"string"},"stageHash":{"type":"string"}},"required":["type"]},{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"title":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"artists":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"albumArtists":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"album":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"duration":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"meta":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"onSuccess":{"$ref":"#/definitions/FlowControlTerm"},"onFailure":{"$ref":"#/definitions/FlowControlTerm"},"onSkip":{"$ref":"#/definitions/FlowControlTerm"},"failureReturnPartial":{"type":"boolean"},"type":{"type":"string","enum":["native"]},"name":{"type":"string"},"stageHash":{"type":"string"}},"required":["type"]},{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"title":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"artists":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"albumArtists":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"album":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"duration":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"meta":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"onSuccess":{"$ref":"#/definitions/FlowControlTerm"},"onFailure":{"$ref":"#/definitions/FlowControlTerm"},"onSkip":{"$ref":"#/definitions/FlowControlTerm"},"failureReturnPartial":{"type":"boolean"},"name":{"type":"string"}}},{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"title":{},"artists":{},"albumArtists":{},"album":{},"duration":{},"meta":{},"onSuccess":{"$ref":"#/definitions/FlowControlTerm"},"onFailure":{"$ref":"#/definitions/FlowControlTerm"},"onSkip":{"$ref":"#/definitions/FlowControlTerm"},"failureReturnPartial":{"type":"boolean"},"type":{"type":"string"},"name":{"type":"string"},"stageHash":{"type":"string"}},"required":["type"]}],"title":"PlayTransformParts<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm),MaybeStageTyped>"},"WhenConditionsConfig":{"$ref":"#/definitions/WhenConditions%3Cstring%3E","title":"WhenConditionsConfig"},"WhenConditions":{"type":"array","items":{"$ref":"#/definitions/WhenParts%3Cstring%3E"},"title":"WhenConditions"},"WhenParts":{"$ref":"#/definitions/PlayTransformPartsAtomic%3Cstring%3E","title":"WhenParts"},"PlayTransformPartsAtomic":{"type":"object","properties":{"title":{"type":"string"},"artists":{"type":"string"},"albumArtists":{"type":"string"},"album":{"type":"string"},"duration":{"type":"string"},"meta":{"type":"string"}},"title":"PlayTransformPartsAtomic"},"Whennable":{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"}},"title":"Whennable"},"FlowControlTerm":{"type":"string","enum":["continue","stop"],"title":"FlowControlTerm"},"StageTypeMetadata":{"type":"string","enum":["spotify","musicbrainz","native"],"title":"StageTypeMetadata"},"SearchAndReplaceTerm":{"anyOf":[{"type":"string"},{"$ref":"#/definitions/ConditionalSearchAndReplaceTerm"}],"title":"SearchAndReplaceTerm"},"ConditionalSearchAndReplaceTerm":{"$ref":"#/definitions/ConditionalSearchAndReplaceRegExp","title":"ConditionalSearchAndReplaceTerm"},"ConditionalSearchAndReplaceRegExp":{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"search":{"anyOf":[{"type":"string"},{"type":"string","format":"regex"}],"description":"The search value to test for\n\nCan be a normal string (converted to a case-sensitive literal) or a valid regular expression as a string, or an actual RegExp object","examples":[["find this string","/some string*/ig"]]},"replace":{"type":"string","description":"The replacement string/value to use when search is found\n\nThis can be a literal string like `'replace with this`, an empty string to remove the search value (`''`), or a special regex value\n\nSee replacement here for more information: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace"},"test":{"$comment":"(obj: SearchAndReplaceRegExp) => boolean","type":"object","properties":{"namedArgs":{"type":"object","properties":{"obj":{"$ref":"#/definitions/SearchAndReplaceRegExp"}},"required":["obj"],"additionalProperties":false}},"description":"An optional function to execute before running this search-and-replace that decides if it should run at all"}},"required":["replace","search"],"title":"ConditionalSearchAndReplaceRegExp"},"SearchAndReplaceRegExp":{"type":"object","properties":{"search":{"anyOf":[{"type":"string"},{"type":"string","format":"regex"}],"description":"The search value to test for\n\nCan be a normal string (converted to a case-sensitive literal) or a valid regular expression as a string, or an actual RegExp object","examples":[["find this string","/some string*/ig"]]},"replace":{"type":"string","description":"The replacement string/value to use when search is found\n\nThis can be a literal string like `'replace with this`, an empty string to remove the search value (`''`), or a special regex value\n\nSee replacement here for more information: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace"},"test":{"$comment":"(obj: SearchAndReplaceRegExp) => boolean","type":"object","properties":{"namedArgs":{"type":"object","properties":{"obj":{"$ref":"#/definitions/SearchAndReplaceRegExp"}},"required":["obj"],"additionalProperties":false}},"description":"An optional function to execute before running this search-and-replace that decides if it should run at all"}},"required":["search","replace"],"title":"SearchAndReplaceRegExp"},"ExternalMetadataTerm":{"anyOf":[{"type":"boolean"},{"not":{}},{"$ref":"#/definitions/Whennable"}],"title":"ExternalMetadataTerm"},"StageTypeUser":{"type":"string","enum":["user"],"title":"StageTypeUser"},"LastfmClientAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this client. Used with sources to restrict where scrobbles are sent.","examples":["MyConfig"]},"data":{"$ref":"#/definitions/LastfmData","description":"Specific data required to configure this client"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"options":{"$ref":"#/definitions/LastfmClientOptions"},"configureAs":{"type":"string","enum":["client","source"],"description":"Should always be `client` when using LastFM as a client","default":"client","examples":["client"]},"type":{"type":"string","enum":["lastfm"]}},"required":["data","name","type"],"title":"LastfmClientAIOConfig"},"LastfmData":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"apiKey":{"type":"string","description":"API Key generated from Last.fm/Libre.fm account","examples":["787c921a2a2ab42320831aba0c8f2fc2"]},"secret":{"type":"string","description":"Secret generated from Last.fm/Libre.fm account","examples":["ec42e09d5ae0ee0f0816ca151008412a"]},"session":{"type":"string","description":"Optional session id returned from a completed auth flow"},"redirectUri":{"type":"string","description":"Optional URI to use for callback. Specify this if callback should be different than the default. MUST have \"lastfm/callback\" in the URL somewhere.","default":"http://localhost:9078/lastfm/callback","examples":["http://localhost:9078/lastfm/callback"]}},"required":["apiKey","secret"],"title":"LastfmData"},"LastfmClientOptions":{"type":"object","properties":{"nowPlaying":{"anyOf":[{"type":"boolean"},{"type":"array","items":{"type":"string"}}],"description":"Configure if this Client should report Now Playing from Sources that can scrobble to it\n\n* `true` (default) => Report Now Playing from any eligible Source. \n * If multiple Sources are Playing then reported Play is based on alphabetical order of Source names\n* `false` => Do not report Now Playing\n* `string` list => list of Source `names` that should be allowed to report Now Playing. Order of list determine priority of Play to Report.","default":true},"refreshEnabled":{"type":"boolean","description":"Try to get fresh scrobble history from client when tracks to be scrobbled are newer than the last scrobble found in client history","default":true,"examples":[true]},"refreshStaleAfter":{"type":"number","description":"Refresh scrobbled plays from upstream service if last refresh was at least X seconds ago\n\n**In most case this setting does NOT need to be changed.** The default value is sufficient for the majority of use-cases. Increasing this setting may increase upstream service load and slow down scrobbles.\n\nThis setting should only be changed in specific scenarios where MS is handling multiple \"relaying\" client-services (IE lfm -> lz -> lfm) and there is the potential for a client to be out of sync after more than a few seconds.","examples":[60],"default":60},"refreshMinInterval":{"type":"number","description":"Minimum time (milliseconds) required to pass before upstream scrobbles can be refreshed.\n\n**In most case this setting does NOT need to be changed.** This will always be equal to or smaller than `refreshStaleAfter`.","default":5000,"examples":[5000]},"refreshInitialCount":{"type":"number","description":"The number of tracks to retrieve on initial refresh (related to scrobbleBacklogCount). If not specified this is the maximum supported by the client in 1 API call."},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"checkExistingScrobbles":{"type":"boolean","description":"Check client for an existing scrobble at the same recorded time as the \"new\" track to be scrobbled. If an existing scrobble is found this track is not track scrobbled.","default":true,"examples":[true]},"verbose":{"type":"object","properties":{"match":{"$ref":"#/definitions/MatchLoggingOptions"}},"description":"Options used for increasing verbosity of logging in MS (used for debugging)"},"deadLetterRetries":{"type":"number","description":"Number of times MS should automatically retry scrobbles in dead letter queue","default":1,"examples":[1]},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"LastfmClientOptions"},"LibrefmClientAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this client. Used with sources to restrict where scrobbles are sent.","examples":["MyConfig"]},"data":{"$ref":"#/definitions/LibrefmData","description":"Specific data required to configure this client"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"options":{"$ref":"#/definitions/LibrefmClientOptions"},"configureAs":{"type":"string","enum":["client","source"],"description":"Should always be `client` when using Librefm as a client","default":"client","examples":["client"]},"type":{"type":"string","enum":["librefm"]}},"required":["data","name","type"],"title":"LibrefmClientAIOConfig"},"LibrefmData":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"apiKey":{"type":"string","description":"Optional Secret for Libre.fm account\n\nThis can be anything, or it will be generated by multi-scrobbler","examples":["anyValue"]},"secret":{"type":"string","description":"Optional Secret for Libre.fm account\n\nThis can be anything, or it will be generated by multi-scrobbler","examples":["anyValue"]},"session":{"type":"string","description":"Optional session id returned from a completed auth flow"},"path":{"type":"string"},"urlBase":{"type":"string","description":"(Optional) The host and path prefix for your Libre.fm instance","default":"https://libre.fm/2.0/"},"redirectUri":{"type":"string","description":"Optional URI to use for callback. Specify this if callback should be different than the default. MUST have \"librefm/callback\" in the URL somewhere.","default":"http://localhost:9078/librefm/callback","examples":["http://localhost:9078/librefm/callback"]}},"title":"LibrefmData"},"LibrefmClientOptions":{"type":"object","properties":{"nowPlaying":{"anyOf":[{"type":"boolean"},{"type":"array","items":{"type":"string"}}],"description":"Configure if this Client should report Now Playing from Sources that can scrobble to it\n\n* `true` (default) => Report Now Playing from any eligible Source. \n * If multiple Sources are Playing then reported Play is based on alphabetical order of Source names\n* `false` => Do not report Now Playing\n* `string` list => list of Source `names` that should be allowed to report Now Playing. Order of list determine priority of Play to Report.","default":true},"refreshEnabled":{"type":"boolean","description":"Try to get fresh scrobble history from client when tracks to be scrobbled are newer than the last scrobble found in client history","default":true,"examples":[true]},"refreshStaleAfter":{"type":"number","description":"Refresh scrobbled plays from upstream service if last refresh was at least X seconds ago\n\n**In most case this setting does NOT need to be changed.** The default value is sufficient for the majority of use-cases. Increasing this setting may increase upstream service load and slow down scrobbles.\n\nThis setting should only be changed in specific scenarios where MS is handling multiple \"relaying\" client-services (IE lfm -> lz -> lfm) and there is the potential for a client to be out of sync after more than a few seconds.","examples":[60],"default":60},"refreshMinInterval":{"type":"number","description":"Minimum time (milliseconds) required to pass before upstream scrobbles can be refreshed.\n\n**In most case this setting does NOT need to be changed.** This will always be equal to or smaller than `refreshStaleAfter`.","default":5000,"examples":[5000]},"refreshInitialCount":{"type":"number","description":"The number of tracks to retrieve on initial refresh (related to scrobbleBacklogCount). If not specified this is the maximum supported by the client in 1 API call."},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"checkExistingScrobbles":{"type":"boolean","description":"Check client for an existing scrobble at the same recorded time as the \"new\" track to be scrobbled. If an existing scrobble is found this track is not track scrobbled.","default":true,"examples":[true]},"verbose":{"type":"object","properties":{"match":{"$ref":"#/definitions/MatchLoggingOptions"}},"description":"Options used for increasing verbosity of logging in MS (used for debugging)"},"deadLetterRetries":{"type":"number","description":"Number of times MS should automatically retry scrobbles in dead letter queue","default":1,"examples":[1]},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"LibrefmClientOptions"},"ListenBrainzClientAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this client. Used with sources to restrict where scrobbles are sent.","examples":["MyConfig"]},"data":{"$ref":"#/definitions/ListenBrainzClientData","description":"Specific data required to configure this client"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"options":{"$ref":"#/definitions/CommonClientOptions"},"configureAs":{"type":"string","enum":["client","source"],"description":"Should always be `client` when using Listenbrainz as a client","default":"client","examples":["client"]},"type":{"type":"string","enum":["listenbrainz"]}},"required":["data","name","type"],"title":"ListenBrainzClientAIOConfig"},"ListenBrainzClientData":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"url":{"type":"string","description":"URL for the ListenBrainz server, if not using the default","examples":["https://api.listenbrainz.org/"],"default":"https://api.listenbrainz.org/"},"token":{"type":"string","description":"User token for the user to scrobble for","examples":["6794186bf-1157-4de6-80e5-uvb411f3ea2b"]},"username":{"type":"string","description":"Username of the user to scrobble for"}},"required":["token","username"],"title":"ListenBrainzClientData"},"KoitoClientAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this client. Used with sources to restrict where scrobbles are sent.","examples":["MyConfig"]},"data":{"$ref":"#/definitions/KoitoClientData","description":"Specific data required to configure this client"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"options":{"$ref":"#/definitions/CommonClientOptions"},"configureAs":{"type":"string","enum":["client","source"],"description":"Should always be `client` when using Koito as a client","default":"client","examples":["client"]},"type":{"type":"string","enum":["koito"]}},"required":["data","name","type"],"title":"KoitoClientAIOConfig"},"KoitoClientData":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"url":{"type":"string","description":"URL for the Koito server","examples":["http://192.168.0.100:4110"]},"token":{"type":"string","description":"User token for the user to scrobble for","examples":["pM195xPV98CDpk0QW47FIIOR8AKATAX5DblBF-Jq0t1MbbKL"]},"username":{"type":"string","description":"Username of the user to scrobble for"}},"required":["token","url","username"],"title":"KoitoClientData"},"TealClientAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this client. Used with sources to restrict where scrobbles are sent.","examples":["MyConfig"]},"data":{"$ref":"#/definitions/TealClientData","description":"Specific data required to configure this client"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"options":{"$ref":"#/definitions/TealClientOptions"},"configureAs":{"type":"string","enum":["client","source"],"description":"Should always be `client` when using Tealfm as a client","default":"client","examples":["client"]},"type":{"type":"string","enum":["tealfm"]}},"required":["data","name","type"],"title":"TealClientAIOConfig"},"TealClientData":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"baseUri":{"type":"string","description":"The base URI of the Multi-Scrobbler to use for ATProto OAuth\n\nOnly include this if you want to use OAuth. The URI must be a non-IP/non-local domain using https: protocol."},"identifier":{"type":"string","description":"Identify the account to login as\n\n* For **App Password** Auth - your email\n* For **Oauth** - your handle minus the @"},"appPassword":{"type":"string","description":"The [App Password](https://atproto.com/specs/xrpc#app-passwords) you created for your account\n\nThis is created under https://bsky.app/settings/app-passwords\n\n**Use this if you are self-hosting Multi-Scrobbler on localhost or accessed like http://IP:PORT**"}},"required":["identifier"],"title":"TealClientData"},"TealClientOptions":{"type":"object","properties":{"refreshEnabled":{"type":"boolean","description":"Try to get fresh scrobble history from client when tracks to be scrobbled are newer than the last scrobble found in client history","default":true,"examples":[true]},"refreshStaleAfter":{"type":"number","description":"Refresh scrobbled plays from upstream service if last refresh was at least X seconds ago\n\n**In most case this setting does NOT need to be changed.** The default value is sufficient for the majority of use-cases. Increasing this setting may increase upstream service load and slow down scrobbles.\n\nThis setting should only be changed in specific scenarios where MS is handling multiple \"relaying\" client-services (IE lfm -> lz -> lfm) and there is the potential for a client to be out of sync after more than a few seconds.","examples":[60],"default":60},"refreshMinInterval":{"type":"number","description":"Minimum time (milliseconds) required to pass before upstream scrobbles can be refreshed.\n\n**In most case this setting does NOT need to be changed.** This will always be equal to or smaller than `refreshStaleAfter`.","default":5000,"examples":[5000]},"refreshInitialCount":{"type":"number","description":"The number of tracks to retrieve on initial refresh (related to scrobbleBacklogCount). If not specified this is the maximum supported by the client in 1 API call."},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"checkExistingScrobbles":{"type":"boolean","description":"Check client for an existing scrobble at the same recorded time as the \"new\" track to be scrobbled. If an existing scrobble is found this track is not track scrobbled.","default":true,"examples":[true]},"verbose":{"type":"object","properties":{"match":{"$ref":"#/definitions/MatchLoggingOptions"}},"description":"Options used for increasing verbosity of logging in MS (used for debugging)"},"deadLetterRetries":{"type":"number","description":"Number of times MS should automatically retry scrobbles in dead letter queue","default":1,"examples":[1]},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"TealClientOptions"},"RockSkyClientAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this client. Used with sources to restrict where scrobbles are sent.","examples":["MyConfig"]},"data":{"$ref":"#/definitions/RockSkyClientData","description":"Specific data required to configure this client"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"options":{"$ref":"#/definitions/RockSkyClientOptions"},"configureAs":{"type":"string","enum":["client","source"],"description":"Should always be `client` when using RockSky as a client","default":"client","examples":["client"]},"type":{"type":"string","enum":["rocksky"]}},"required":["data","name","type"],"title":"RockSkyClientAIOConfig"},"RockSkyClientData":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"key":{"type":"string","description":"API Key generated from [API Applications](https://docs.rocksky.app/migrating-from-listenbrainz-to-rocksky-1040189m0) in Rocksky for your account","examples":["6794186bf-1157-4de6-80e5-uvb411f3ea2b"]},"handle":{"type":"string","description":"The **fully-qualified** handle for your ATPRoto/Bluesky account, like:\n\n* alice.bsky.social\n* foxxmd.com\n* mysuer.blacksky.app"}},"required":["handle","key"],"title":"RockSkyClientData"},"RockSkyClientOptions":{"type":"object","properties":{"nowPlaying":{"anyOf":[{"type":"boolean"},{"type":"array","items":{"type":"string"}}],"description":"Configure if this Client should report Now Playing from Sources that can scrobble to it\n\n* `true` (default) => Report Now Playing from any eligible Source. \n * If multiple Sources are Playing then reported Play is based on alphabetical order of Source names\n* `false` => Do not report Now Playing\n* `string` list => list of Source `names` that should be allowed to report Now Playing. Order of list determine priority of Play to Report.","default":true},"refreshEnabled":{"type":"boolean","description":"Try to get fresh scrobble history from client when tracks to be scrobbled are newer than the last scrobble found in client history","default":true,"examples":[true]},"refreshStaleAfter":{"type":"number","description":"Refresh scrobbled plays from upstream service if last refresh was at least X seconds ago\n\n**In most case this setting does NOT need to be changed.** The default value is sufficient for the majority of use-cases. Increasing this setting may increase upstream service load and slow down scrobbles.\n\nThis setting should only be changed in specific scenarios where MS is handling multiple \"relaying\" client-services (IE lfm -> lz -> lfm) and there is the potential for a client to be out of sync after more than a few seconds.","examples":[60],"default":60},"refreshMinInterval":{"type":"number","description":"Minimum time (milliseconds) required to pass before upstream scrobbles can be refreshed.\n\n**In most case this setting does NOT need to be changed.** This will always be equal to or smaller than `refreshStaleAfter`.","default":5000,"examples":[5000]},"refreshInitialCount":{"type":"number","description":"The number of tracks to retrieve on initial refresh (related to scrobbleBacklogCount). If not specified this is the maximum supported by the client in 1 API call."},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"checkExistingScrobbles":{"type":"boolean","description":"Check client for an existing scrobble at the same recorded time as the \"new\" track to be scrobbled. If an existing scrobble is found this track is not track scrobbled.","default":true,"examples":[true]},"verbose":{"type":"object","properties":{"match":{"$ref":"#/definitions/MatchLoggingOptions"}},"description":"Options used for increasing verbosity of logging in MS (used for debugging)"},"deadLetterRetries":{"type":"number","description":"Number of times MS should automatically retry scrobbles in dead letter queue","default":1,"examples":[1]},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"},"audioScrobblerUrl":{"type":"string","description":"URL for the Rocksky *Listenbrainz* endpoint, if not using the default","examples":["https://audioscrobbler.rocksky.app"],"default":"https://audioscrobbler.rocksky.app"},"apiUrl":{"type":"string","description":"URL for the Rocksky *API* endpoint, if not using the default","examples":["https://api.rocksky.app"],"default":"https://api.rocksky.app"}},"title":"RockSkyClientOptions"},"DiscordClientAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this client. Used with sources to restrict where scrobbles are sent.","examples":["MyConfig"]},"data":{"$ref":"#/definitions/DiscordClientData","description":"Specific data required to configure this client"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"options":{"$ref":"#/definitions/CommonClientOptions"},"configureAs":{"type":"string","enum":["client","source"],"description":"Should always be `client` when using Koito as a client","default":"client","examples":["client"]},"type":{"type":"string","enum":["discord"]}},"required":["data","name","type"],"title":"DiscordClientAIOConfig"},"DiscordClientData":{"type":"object","properties":{"token":{"type":"string"},"applicationId":{"type":"string"},"artwork":{"anyOf":[{"type":"boolean"},{"type":"string"},{"type":"array","items":{"type":"string"}}]},"artworkDefaultUrl":{"type":"string"},"statusOverrideAllow":{"anyOf":[{"type":"string"},{"type":"array","items":{"$ref":"#/definitions/StatusType"}}]},"listeningActivityAllow":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}]},"ipcLocations":{"anyOf":[{"type":"string"},{"type":"array","items":{"anyOf":[{"type":"string"},{"type":"array","minItems":2,"items":[{"type":"number"},{"type":"string"}],"maxItems":2}]}}]}},"title":"DiscordClientData"},"StatusType":{"type":"string","enum":["online","idle","dnd","invisible"],"title":"StatusType"}}} \ No newline at end of file diff --git a/src/backend/common/schema/aio-source.json b/src/backend/common/schema/aio-source.json index 853e3ae7..725d6511 100644 --- a/src/backend/common/schema/aio-source.json +++ b/src/backend/common/schema/aio-source.json @@ -1 +1 @@ -{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"sourceDefaults":{"$ref":"#/definitions/SourceRetryOptions"},"sources":{"type":"array","items":{"$ref":"#/definitions/SourceAIOConfig"}}},"definitions":{"SourceRetryOptions":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]}},"title":"SourceRetryOptions"},"SourceAIOConfig":{"anyOf":[{"$ref":"#/definitions/SpotifySourceAIOConfig"},{"$ref":"#/definitions/PlexApiSourceAIOConfig"},{"$ref":"#/definitions/DeezerSourceAIOConfig"},{"$ref":"#/definitions/DeezerInternalAIOConfig"},{"$ref":"#/definitions/ListenbrainzEndpointSourceAIOConfig"},{"$ref":"#/definitions/LastFMEndpointSourceAIOConfig"},{"$ref":"#/definitions/SubsonicSourceAIOConfig"},{"$ref":"#/definitions/JellyApiSourceAIOConfig"},{"$ref":"#/definitions/LastFmSouceAIOConfig"},{"$ref":"#/definitions/LibrefmSouceAIOConfig"},{"$ref":"#/definitions/YTMusicSourceAIOConfig"},{"$ref":"#/definitions/MPRISSourceAIOConfig"},{"$ref":"#/definitions/MopidySourceAIOConfig"},{"$ref":"#/definitions/ListenBrainzSourceAIOConfig"},{"$ref":"#/definitions/JRiverSourceAIOConfig"},{"$ref":"#/definitions/KodiSourceAIOConfig"},{"$ref":"#/definitions/WebScrobblerSourceAIOConfig"},{"$ref":"#/definitions/ChromecastSourceAIOConfig"},{"$ref":"#/definitions/MalojaSourceAIOConfig"},{"$ref":"#/definitions/MusikcubeSourceAIOConfig"},{"$ref":"#/definitions/MusicCastSourceAIOConfig"},{"$ref":"#/definitions/MPDSourceAIOConfig"},{"$ref":"#/definitions/VLCSourceAIOConfig"},{"$ref":"#/definitions/IcecastSourceAIOConfig"},{"$ref":"#/definitions/AzuracastSourceAIOConfig"},{"$ref":"#/definitions/KoitoSourceAIOConfig"},{"$ref":"#/definitions/TealSourceAIOConfig"},{"$ref":"#/definitions/RockskySourceAIOConfig"}],"title":"SourceAIOConfig"},"SpotifySourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/SpotifySourceData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"type":{"type":"string","enum":["spotify"]}},"required":["data","type"],"title":"SpotifySourceAIOConfig"},"SpotifySourceData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)\n\nIt is unlikely you should need to change this unless you scrobble many very short tracks often\n\nReading:\n* https://developer.spotify.com/documentation/web-api/guides/rate-limits/\n* https://medium.com/mendix/limiting-your-amount-of-calls-in-mendix-most-of-the-time-rest-835dde55b10e\n * Rate limit may ~180 req/min\n* https://community.spotify.com/t5/Spotify-for-Developers/Web-API-ratelimit/m-p/5503150/highlight/true#M7930\n * Informally indicated as 20 req/sec? Probably for burstiness","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"clientId":{"type":"string","description":"spotify client id","examples":["787c921a2a2ab42320831aba0c8f2fc2"]},"clientSecret":{"type":"string","description":"spotify client secret","examples":["ec42e09d5ae0ee0f0816ca151008412a"]},"redirectUri":{"type":"string","description":"spotify redirect URI -- required only if not the default shown here. URI must end in \"callback\"","default":"http://localhost:9078/callback","examples":["http://localhost:9078/callback"]}},"required":["clientId","clientSecret"],"title":"SpotifySourceData"},"CommonSourceOptions":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"CommonSourceOptions"},"LogLevel":{"type":"string","enum":["silent","fatal","error","warn","info","log","verbose","debug"],"description":"Names of log levels that can be invoked on the logger\n\nFrom lowest to highest:\n\n* `debug`\n* `verbose`\n* `log`\n* `info`\n* `warn`\n* `error`\n* `fatal`\n* `silent` (will never output anything)\n\nWhen used in `LogOptions` specifies the **minimum** level the output should log at.","title":"LogLevel"},"FileLogOptions":{"type":"object","properties":{"timestamp":{"type":"string","enum":["unix","iso","auto"],"description":"For rolling log files\n\nWhen\n* value passed to rolling destination is a string (`path` from LogOptions is a string) and\n* `frequency` is defined\n\nThis determines the format of the datetime inserted into the log file name:\n\n* `unix` - unix epoch timestamp in milliseconds\n* `iso` - Full [ISO8601](https://en.wikipedia.org/wiki/ISO_8601) datetime IE '2024-03-07T20:11:34Z'\n* `auto`\n * When frequency is `daily` only inserts date IE YYYY-MM-DD\n * Otherwise inserts full ISO8601 datetime","default":"auto"},"size":{"type":["number","string"],"description":"The maximum size of a given rolling log file.\n\nCan be combined with frequency. Use k, m and g to express values in KB, MB or GB.\n\nNumerical values will be considered as MB.","default":"10MB"},"frequency":{"anyOf":[{"type":"string","enum":["daily"]},{"type":"string","enum":["hourly"]},{"type":"number"}],"description":"The amount of time a given rolling log file is used. Can be combined with size.\n\nUse `daily` or `hourly` to rotate file every day (or every hour). Existing file within the current day (or hour) will be re-used.\n\nNumerical values will be considered as a number of milliseconds. Using a numerical value will always create a new file upon startup.","default":"daily"},"path":{"anyOf":[{"type":"string"},{"$comment":"() => string"}],"description":"The path and filename to use for log files.\n\nIf using rolling files the filename will be appended with `.N` (a number) BEFORE the extension based on rolling status.\n\nMay also be specified using env LOG_PATH or a function that returns a string.\n\nIf path is relative the absolute path will be derived from `logBaseDir` (in `LoggerAppExtras`) which defaults to CWD","default":"./logs/app.log"},"level":{"anyOf":[{"$ref":"#/definitions/LogLevel"},{"type":"boolean","const":false}],"description":"Specify the minimum log level to output to rotating files. If `false` no log files will be created."}},"title":"FileLogOptions"},"ScrobbleThresholds":{"type":"object","properties":{"duration":{"type":["number","null"],"description":"The number of seconds a track has been listened to before it should be considered scrobbled.\n\nSet to null to disable.","default":240,"examples":[240]},"percent":{"type":["number","null"],"description":"The percentage (as an integer) of a track that should have been seen played before it should be scrobbled. Only used if the Source provides information about how long the track is.\n\nSet to null to disable.\n\nNOTE: This should be used with care when the Source is a \"polling\" type (has an 'interval' property). If the track is short and the interval is too high MS may ignore the track if percentage is high because it had not \"seen\" the track for long enough from first discovery, even if you have been playing the track for longer.","default":50,"examples":[50]}},"title":"ScrobbleThresholds"},"PlayTransformOptions":{"type":"object","properties":{"log":{"anyOf":[{"type":"boolean"},{"type":"string","enum":["all"]}]},"preCompare":{"$ref":"#/definitions/PlayTransformPartsConfig%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%3E"},"compare":{"type":"object","properties":{"candidate":{"$ref":"#/definitions/PlayTransformPartsConfig%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%3E"},"existing":{"$ref":"#/definitions/PlayTransformPartsConfig%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%3E"}}},"postCompare":{"$ref":"#/definitions/PlayTransformPartsConfig%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%3E"}},"title":"PlayTransformOptions"},"PlayTransformPartsConfig<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm)>":{"anyOf":[{"$ref":"#/definitions/PlayTransformPartsArray%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%2CMaybeStageTyped%3E"},{"$ref":"#/definitions/PlayTransformParts%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%2CMaybeStageTyped%3E"}],"description":"Represents the weakly-defined user config. May be an array of parts or one parts object","title":"PlayTransformPartsConfig<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm)>"},"PlayTransformPartsArray<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm),MaybeStageTyped>":{"type":"array","items":{"$ref":"#/definitions/PlayTransformParts%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%2CMaybeStageTyped%3E"},"title":"PlayTransformPartsArray<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm),MaybeStageTyped>"},"PlayTransformParts<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm),MaybeStageTyped>":{"anyOf":[{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"title":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"artists":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"albumArtists":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"album":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"duration":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"meta":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"onSuccess":{"$ref":"#/definitions/FlowControlTerm"},"onFailure":{"$ref":"#/definitions/FlowControlTerm"},"onSkip":{"$ref":"#/definitions/FlowControlTerm"},"failureReturnPartial":{"type":"boolean"},"type":{"$ref":"#/definitions/StageTypeMetadata"},"name":{"type":"string"},"stageHash":{"type":"string"},"score":{"type":"number"}},"required":["type"]},{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"title":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"artists":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"albumArtists":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"album":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"duration":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"meta":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"onSuccess":{"$ref":"#/definitions/FlowControlTerm"},"onFailure":{"$ref":"#/definitions/FlowControlTerm"},"onSkip":{"$ref":"#/definitions/FlowControlTerm"},"failureReturnPartial":{"type":"boolean"},"type":{"$ref":"#/definitions/StageTypeUser"},"name":{"type":"string"},"stageHash":{"type":"string"}},"required":["type"]},{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"title":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"artists":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"albumArtists":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"album":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"duration":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"meta":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"onSuccess":{"$ref":"#/definitions/FlowControlTerm"},"onFailure":{"$ref":"#/definitions/FlowControlTerm"},"onSkip":{"$ref":"#/definitions/FlowControlTerm"},"failureReturnPartial":{"type":"boolean"},"type":{"type":"string","enum":["native"]},"name":{"type":"string"},"stageHash":{"type":"string"}},"required":["type"]},{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"title":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"artists":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"albumArtists":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"album":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"duration":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"meta":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"onSuccess":{"$ref":"#/definitions/FlowControlTerm"},"onFailure":{"$ref":"#/definitions/FlowControlTerm"},"onSkip":{"$ref":"#/definitions/FlowControlTerm"},"failureReturnPartial":{"type":"boolean"},"name":{"type":"string"}}},{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"title":{},"artists":{},"albumArtists":{},"album":{},"duration":{},"meta":{},"onSuccess":{"$ref":"#/definitions/FlowControlTerm"},"onFailure":{"$ref":"#/definitions/FlowControlTerm"},"onSkip":{"$ref":"#/definitions/FlowControlTerm"},"failureReturnPartial":{"type":"boolean"},"type":{"type":"string"},"name":{"type":"string"},"stageHash":{"type":"string"}},"required":["type"]}],"title":"PlayTransformParts<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm),MaybeStageTyped>"},"WhenConditionsConfig":{"$ref":"#/definitions/WhenConditions%3Cstring%3E","title":"WhenConditionsConfig"},"WhenConditions":{"type":"array","items":{"$ref":"#/definitions/WhenParts%3Cstring%3E"},"title":"WhenConditions"},"WhenParts":{"$ref":"#/definitions/PlayTransformPartsAtomic%3Cstring%3E","title":"WhenParts"},"PlayTransformPartsAtomic":{"type":"object","properties":{"title":{"type":"string"},"artists":{"type":"string"},"albumArtists":{"type":"string"},"album":{"type":"string"},"duration":{"type":"string"},"meta":{"type":"string"}},"title":"PlayTransformPartsAtomic"},"Whennable":{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"}},"title":"Whennable"},"FlowControlTerm":{"type":"string","enum":["continue","stop"],"title":"FlowControlTerm"},"StageTypeMetadata":{"type":"string","enum":["spotify","musicbrainz","native"],"title":"StageTypeMetadata"},"SearchAndReplaceTerm":{"anyOf":[{"type":"string"},{"$ref":"#/definitions/ConditionalSearchAndReplaceTerm"}],"title":"SearchAndReplaceTerm"},"ConditionalSearchAndReplaceTerm":{"$ref":"#/definitions/ConditionalSearchAndReplaceRegExp","title":"ConditionalSearchAndReplaceTerm"},"ConditionalSearchAndReplaceRegExp":{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"search":{"anyOf":[{"type":"string"},{"type":"string","format":"regex"}],"description":"The search value to test for\n\nCan be a normal string (converted to a case-sensitive literal) or a valid regular expression as a string, or an actual RegExp object","examples":[["find this string","/some string*/ig"]]},"replace":{"type":"string","description":"The replacement string/value to use when search is found\n\nThis can be a literal string like `'replace with this`, an empty string to remove the search value (`''`), or a special regex value\n\nSee replacement here for more information: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace"},"test":{"$comment":"(obj: SearchAndReplaceRegExp) => boolean","type":"object","properties":{"namedArgs":{"type":"object","properties":{"obj":{"$ref":"#/definitions/SearchAndReplaceRegExp"}},"required":["obj"],"additionalProperties":false}},"description":"An optional function to execute before running this search-and-replace that decides if it should run at all"}},"required":["replace","search"],"title":"ConditionalSearchAndReplaceRegExp"},"SearchAndReplaceRegExp":{"type":"object","properties":{"search":{"anyOf":[{"type":"string"},{"type":"string","format":"regex"}],"description":"The search value to test for\n\nCan be a normal string (converted to a case-sensitive literal) or a valid regular expression as a string, or an actual RegExp object","examples":[["find this string","/some string*/ig"]]},"replace":{"type":"string","description":"The replacement string/value to use when search is found\n\nThis can be a literal string like `'replace with this`, an empty string to remove the search value (`''`), or a special regex value\n\nSee replacement here for more information: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace"},"test":{"$comment":"(obj: SearchAndReplaceRegExp) => boolean","type":"object","properties":{"namedArgs":{"type":"object","properties":{"obj":{"$ref":"#/definitions/SearchAndReplaceRegExp"}},"required":["obj"],"additionalProperties":false}},"description":"An optional function to execute before running this search-and-replace that decides if it should run at all"}},"required":["search","replace"],"title":"SearchAndReplaceRegExp"},"ExternalMetadataTerm":{"anyOf":[{"type":"boolean"},{"not":{}},{"$ref":"#/definitions/Whennable"}],"title":"ExternalMetadataTerm"},"StageTypeUser":{"type":"string","enum":["user"],"title":"StageTypeUser"},"PlexApiSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/PlexApiData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/PlexApiOptions"},"type":{"type":"string","enum":["plex"]}},"required":["data","type"],"title":"PlexApiSourceAIOConfig"},"PlexApiData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"token":{"type":"string"},"url":{"type":"string","description":"http(s)://HOST:PORT of the Plex server to connect to"},"usersAllow":{"anyOf":[{"type":"string"},{"type":"boolean","enum":[true]},{"type":"array","items":{"type":"string"}}],"description":"Only scrobble for specific users (case-insensitive)\n\nIf `true` MS will scrobble activity from all users"},"usersBlock":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Do not scrobble for these users (case-insensitive)"},"devicesAllow":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Only scrobble if device or application name contains strings from this list (case-insensitive)"},"devicesBlock":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Do not scrobble if device or application name contains strings from this list (case-insensitive)"},"librariesAllow":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Only scrobble if library name contains string from this list (case-insensitive)"},"librariesBlock":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Do not scrobble if library name contains strings from this list (case-insensitive)"}},"required":["url"],"title":"PlexApiData"},"PlexApiOptions":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"},"ignoreInvalidCert":{"type":"boolean","description":"Ignore invalid cert errors when connecting to Plex\n\nUseful for Plex servers using \"Required\" Secure Connections with self-signed certificates\n\nDo not enable unless you know you need this.","default":false}},"title":"PlexApiOptions"},"DeezerSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/DeezerData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"type":{"type":"string","enum":["deezer"]}},"required":["data","type"],"title":"DeezerSourceAIOConfig"},"DeezerData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"clientId":{"type":"string","description":"deezer client id","examples":["a89cba1569901a0671d5a9875fed4be1"]},"clientSecret":{"type":"string","description":"deezer client secret","examples":["ec42e09d5ae0ee0f0816ca151008412a"]},"redirectUri":{"type":"string","description":"deezer redirect URI -- required only if not the default shown here. URI must end in \"callback\"","default":"http://localhost:9078/deezer/callback","examples":["http://localhost:9078/deezer/callback"]}},"required":["clientId","clientSecret"],"title":"DeezerData"},"DeezerInternalAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/DeezerInternalData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/DeezerInternalSourceOptions"},"type":{"type":"string","enum":["deezer"]}},"required":["data","type"],"title":"DeezerInternalAIOConfig"},"DeezerInternalData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"arl":{"type":"string","description":"ARL retrieved from Deezer response header"},"userAgent":{"type":"string","description":"User agent","default":"Mozilla/5.0 (X11; Linux i686; rv:135.0) Gecko/20100101 Firefox/135.0"}},"required":["arl"],"title":"DeezerInternalData"},"DeezerInternalSourceOptions":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"},"fuzzyDiscoveryIgnore":{"anyOf":[{"type":"boolean"},{"type":"string","enum":["aggressive"]}]}},"title":"DeezerInternalSourceOptions"},"ListenbrainzEndpointSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/ListenbrainzEndpointData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"type":{"type":"string","enum":["endpointlz"]}},"required":["type"],"title":"ListenbrainzEndpointSourceAIOConfig"},"ListenbrainzEndpointData":{"type":"object","properties":{"slug":{"type":["string","null"],"description":"The URL ending that should be used to identify scrobbles for this source\n\nIf you are using multiple Listenbrainz endpoint sources (scrobbles for many users) you can use a slug to match Sources with individual users/origins\n\nExample:\n\n* slug: 'usera' => API URL: http://localhost:9078/api/listenbrainz/usera\n* slug: 'originb' => API URL: http://localhost:9078/api/listenbrainz/originb\n\nIf no slug is found from an extension's incoming webhook event the first Listenbrainz source without a slug will be used"},"token":{"type":["string","null"],"description":"If an LZ submission request contains this token in the Authorization Header it will be used to match the submission with this Source\n\nSee: https://listenbrainz.readthedocs.io/en/latest/users/api/index.html#add-the-user-token-to-your-requests"}},"title":"ListenbrainzEndpointData"},"LastFMEndpointSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/LastFMEndpointData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"type":{"type":"string","enum":["endpointlfm"]}},"required":["type"],"title":"LastFMEndpointSourceAIOConfig"},"LastFMEndpointData":{"type":"object","properties":{"slug":{"type":["string","null"],"description":"The URL ending that should be used to identify scrobbles for this source\n\nIf you are using multiple Last.fm endpoint sources (scrobbles for many users) you can use a slug to match Sources with individual users/origins\n\nExample:\n\n* slug: 'usera' => API URL: http://localhost:9078/api/lastfm/usera\n* slug: 'originb' => API URL: http://localhost:9078/api/lastfm/originb\n\nIf no slug is found from an extension's incoming webhook event the first Last.fm source without a slug will be used"}},"title":"LastFMEndpointData"},"SubsonicSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/SubsonicData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"type":{"type":"string","enum":["subsonic"]}},"required":["data","type"],"title":"SubsonicSourceAIOConfig"},"SubsonicData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"url":{"type":"string","description":"URL of the subsonic media server to query","examples":["http://airsonic.local"]},"user":{"type":"string","description":"Username to login to the server with","examples":[["MyUser"]]},"password":{"type":"string","description":"Password for the user to login to the server with","examples":["MyPassword"]},"ignoreTlsErrors":{"type":"boolean","description":"If your subsonic server is using self-signed certs you may need to disable TLS errors in order to get a connection\n\nWARNING: This should be used with caution as your traffic may not be encrypted.","default":false},"legacyAuthentication":{"type":"boolean","description":"Older Subsonic versions, and some badly implemented servers (Nextcloud), use legacy authentication which sends your password in CLEAR TEXT. This is less secure than the newer, recommended hashing authentication method but in some cases it is needed. See \"Authentication\" section here => https://www.subsonic.org/pages/api.jsp\n\nIf this option is not specified it will be turned on if the subsonic server responds with error code 41 \"Token authentication not supported for LDAP users.\" -- See Error Handling section => https://www.subsonic.org/pages/api.jsp","default":false},"usersAllow":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Only scrobble for specific users (case-insensitive)\n\nIf undefined or an empty string/list MS will scrobble activity from all users"}},"required":["url","user","password"],"title":"SubsonicData"},"JellyApiSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/JellyApiData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/JellyApiOptions"},"type":{"type":"string","enum":["jellyfin"]}},"required":["data","options","type"],"title":"JellyApiSourceAIOConfig"},"JellyApiData":{"type":"object","properties":{"url":{"type":"string","description":"HOST:PORT of the Jellyfin server to connect to"},"user":{"type":"string","description":"The username of the user to authenticate for or track scrobbles for"},"password":{"type":"string","description":"Password of the username to authenticate for\n\nRequired if `apiKey` is not provided."},"apiKey":{"type":"string","description":"API Key to authenticate with.\n\nRequired if `password` is not provided."},"usersAllow":{"anyOf":[{"type":"string"},{"type":"boolean","enum":[true]},{"type":"array","items":{"type":"string"}}],"description":"Only scrobble for specific users (case-insensitive)\n\nIf `true` MS will scrobble activity from all users"},"usersBlock":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Do not scrobble for these users (case-insensitive)"},"devicesAllow":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Only scrobble if device or application name contains strings from this list (case-insensitive)"},"devicesBlock":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Do not scrobble if device or application name contains strings from this list (case-insensitive)"},"librariesAllow":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Only scrobble if library name contains string from this list (case-insensitive)"},"librariesBlock":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Do not scrobble if library name contains strings from this list (case-insensitive)"},"additionalAllowedLibraryTypes":{"type":"array","items":{},"description":"Allow MS to scrobble audio media in libraries classified other than 'music'\n\n`librariesAllow` will achieve the same result as this but this is more convenient if you do not want to explicitly list every library name or are only using `librariesBlock`"},"allowUnknown":{"type":"boolean","description":"Force media with a type of \"Unknown\" to be counted as Audio","default":false},"frontendUrlOverride":{"type":"string","description":"HOST:PORT of the Jellyfin server that your browser will be able to access from the frontend (and thus load images and links from)\nIf unspecified it will use the normal server HOST and PORT from the `url`\nNecessary if you are using a reverse proxy or other network configuration that prevents the frontend from accessing the server directly\n\nENV: JELLYFIN_FRONTEND_URL_OVERRIDE"}},"required":["url","user"],"title":"JellyApiData"},"JellyApiOptions":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"JellyApiOptions"},"LastFmSouceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/LastFmSourceData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"configureAs":{"type":"string","enum":["source"],"description":"When used in `lastfm.config` this tells multi-scrobbler whether to use this data to configure a source or client.","default":"source","examples":["source"]},"type":{"type":"string","enum":["lastfm"]}},"required":["data","type"],"title":"LastFmSouceAIOConfig"},"LastFmSourceData":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"apiKey":{"type":"string","description":"API Key generated from Last.fm/Libre.fm account","examples":["787c921a2a2ab42320831aba0c8f2fc2"]},"secret":{"type":"string","description":"Secret generated from Last.fm/Libre.fm account","examples":["ec42e09d5ae0ee0f0816ca151008412a"]},"session":{"type":"string","description":"Optional session id returned from a completed auth flow"},"redirectUri":{"type":"string","description":"Optional URI to use for callback. Specify this if callback should be different than the default. MUST have \"lastfm/callback\" in the URL somewhere.","default":"http://localhost:9078/lastfm/callback","examples":["http://localhost:9078/lastfm/callback"]},"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"}},"required":["apiKey","secret"],"title":"LastFmSourceData"},"LibrefmSouceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/LibrefmData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"configureAs":{"type":"string","enum":["source"],"description":"When used in `librefm.config` this tells multi-scrobbler whether to use this data to configure a source or client.","default":"source","examples":["source"]},"type":{"type":"string","enum":["librefm"]}},"required":["data","type"],"title":"LibrefmSouceAIOConfig"},"LibrefmData":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"apiKey":{"type":"string","description":"Optional Secret for Libre.fm account\n\nThis can be anything, or it will be generated by multi-scrobbler","examples":["anyValue"]},"secret":{"type":"string","description":"Optional Secret for Libre.fm account\n\nThis can be anything, or it will be generated by multi-scrobbler","examples":["anyValue"]},"session":{"type":"string","description":"Optional session id returned from a completed auth flow"},"path":{"type":"string"},"urlBase":{"type":"string","description":"(Optional) The host and path prefix for your Libre.fm instance","default":"https://libre.fm/2.0/"},"redirectUri":{"type":"string","description":"Optional URI to use for callback. Specify this if callback should be different than the default. MUST have \"librefm/callback\" in the URL somewhere.","default":"http://localhost:9078/librefm/callback","examples":["http://localhost:9078/librefm/callback"]}},"title":"LibrefmData"},"YTMusicSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/YTMusicData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"type":"object","properties":{"logAuth":{"type":"boolean","description":"When true MS will log to DEBUG all of the credentials data it receives from YTM"},"logDiff":{"type":"boolean","description":"Always log history diff\n\nBy default MS will log to `WARN` if history diff is inconsistent but does not log if diff is expected (on new tracks found)\nSet this to `true` to ALWAYS log diff on new tracks. Expected diffs will log to `DEBUG` and inconsistent diffs will continue to log to `WARN`","default":false},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}}},"type":{"type":"string","enum":["ytmusic"]}},"required":["type"],"title":"YTMusicSourceAIOConfig"},"YTMusicData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"cookie":{"type":"string","description":"The cookie retrieved from the Request Headers of music.youtube.com after logging in.\n\nSee https://ytmusicapi.readthedocs.io/en/stable/setup/browser.html#copy-authentication-headers for how to retrieve this value.","examples":["VISITOR_INFO1_LIVE=jMp2xA1Xz2_PbVc; __Secure-3PAPISID=3AxsXpy0M/AkISpjek; ..."]},"clientId":{"type":"string","description":"Google Cloud Console project OAuth Client ID\n\nGenerated from a custom OAuth Client, see docs"},"clientSecret":{"type":"string","description":"Google Cloud Console project OAuth Client Secret\n\nGenerated from a custom OAuth Client, see docs"},"redirectUri":{"type":"string","description":"Google Cloud Console project OAuth Client Authorized redirect URI\n\nGenerated from a custom OAuth Client, see docs. multi-scrobbler will generate a default based on BASE_URL.\nOnly specify this if the default does not work for you."},"innertubeOptions":{"$ref":"#/definitions/InnertubeOptions","description":"Additional options for authorization and tailoring YTM client"}},"title":"YTMusicData"},"InnertubeOptions":{"type":"object","properties":{"po_token":{"type":"string","description":"Proof of Origin token\n\nMay be required if YTM starts returning 403"},"visitor_data":{"type":"string","description":"Visitor ID value found in VISITOR_INFO1_LIVE or visitorData cookie\n\nMay be required if YTM starts returning 403"},"account_index":{"type":"number","description":"If account login results in being able to choose multiple account, use a zero-based index to choose which one to monitor","examples":[0,1]},"location":{"type":"string"},"lang":{"type":"string"},"generate_session_locally":{"type":"boolean"},"device_category":{"type":"string"},"client_type":{"type":"string"},"timezone":{"type":"string"}},"title":"InnertubeOptions"},"MPRISSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/MPRISData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"type":{"type":"string","enum":["mpris"]}},"required":["data","type"],"title":"MPRISSourceAIOConfig"},"MPRISData":{"type":"object","properties":{"blacklist":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"DO NOT scrobble from any players that START WITH these values, case-insensitive","examples":[["spotify","vlc"]]},"whitelist":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"ONLY from any players that START WITH these values, case-insensitive\n\nIf whitelist is present then blacklist is ignored","examples":[["spotify","vlc"]]}},"title":"MPRISData"},"MopidySourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/MopidyData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"type":{"type":"string","enum":["mopidy"]}},"required":["data","type"],"title":"MopidySourceAIOConfig"},"MopidyData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"url":{"type":"string","description":"URL of the Mopidy HTTP server to connect to\n\nYou MUST have Mopidy-HTTP extension enabled: https://mopidy.com/ext/http\n\nmulti-scrobbler connects to the WebSocket endpoint that ultimately looks like this => `ws://localhost:6680/mopidy/ws/`\n\nThe URL you provide here will have all parts not explicitly defined filled in for you so if these are not the default you must define them.\n\nParts => [default value]\n\n* Protocol => `ws://`\n* Hostname => `localhost`\n* Port => `6680`\n* Path => `/mopidy/ws/`","examples":["ws://localhost:6680/mopidy/ws/"],"default":"ws://localhost:6680/mopidy/ws/"},"uriBlacklist":{"type":"array","items":{"type":"string"},"description":"Do not scrobble tracks whose URI STARTS WITH any of these strings, case-insensitive\n\nEX: Don't scrobble tracks from soundcloud by adding 'soundcloud' to this list.\n\nList is ignored if uriWhitelist is used."},"uriWhitelist":{"type":"array","items":{"type":"string"},"description":"Only scrobble tracks whose URI STARTS WITH any of these strings, case-insensitive\n\nEX: Only scrobble tracks from soundcloud by adding 'soundcloud' to this list."},"albumBlacklist":{"type":"array","items":{"type":"string"},"description":"Remove album data that matches any case-insensitive string from this list when scrobbling,\n\nFor certain sources (Soundcloud) Mopidy does not have all track info (Album) and will instead use \"Soundcloud\" as the Album name. You can prevent multi-scrobbler from using this bad Album data by adding the fake name to this list. Multi-scrobbler will still scrobble the track, just without the bad data.","examples":[["Soundcloud","Mixcloud"]],"default":["Soundcloud"]}},"title":"MopidyData"},"ListenBrainzSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/ListenBrainzSourceData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"configureAs":{"type":"string","enum":["source"],"description":"When used in `listenbrainz.config` this tells multi-scrobbler whether to use this data to configure a source or client.","default":"source","examples":["source"]},"type":{"type":"string","enum":["listenbrainz"]}},"required":["data","type"],"title":"ListenBrainzSourceAIOConfig"},"ListenBrainzSourceData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"url":{"type":"string","description":"URL for the ListenBrainz server, if not using the default","examples":["https://api.listenbrainz.org/"],"default":"https://api.listenbrainz.org/"},"token":{"type":"string","description":"User token for the user to scrobble for","examples":["6794186bf-1157-4de6-80e5-uvb411f3ea2b"]},"username":{"type":"string","description":"Username of the user to scrobble for"}},"required":["token","username"],"title":"ListenBrainzSourceData"},"JRiverSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/JRiverData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"type":{"type":"string","enum":["jriver"]}},"required":["data","type"],"title":"JRiverSourceAIOConfig"},"JRiverData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"url":{"type":"string","description":"URL of the JRiver HTTP server to connect to\n\nmulti-scrobbler connects to the Web Service Interface endpoint that ultimately looks like this => `http://yourDomain:52199/MCWS/v1/`\n\nThe URL you provide here will have all parts not explicitly defined filled in for you so if these are not the default you must define them.\n\nParts => [default value]\n\n* Protocol => `http://`\n* Hostname => `localhost`\n* Port => `52199`\n* Path => `/MCWS/v1/`","examples":["http://localhost:52199/MCWS/v1/"],"default":"http://localhost:52199/MCWS/v1/"},"username":{"type":"string","description":"If you have enabled authentication, the username you set"},"password":{"type":"string","description":"If you have enabled authentication, the password you set"}},"required":["url"],"title":"JRiverData"},"KodiSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/KodiData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"type":{"type":"string","enum":["kodi"]}},"required":["data","type"],"title":"KodiSourceAIOConfig"},"KodiData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"url":{"type":"string","description":"URL of the Kodi HTTP server to connect to\n\nmulti-scrobbler connects to the Web Service Interface endpoint that ultimately looks like this => `http://yourDomain:8080/jsonrpc`\n\nThe URL you provide here will have all parts not explicitly defined filled in for you so if these are not the default you must define them.\n\nParts => [default value]\n\n* Protocol => `http://`\n* Hostname => `localhost`\n* Port => `8080`\n* Path => `/jsonrpc`","examples":["http://localhost:8080/jsonrpc"],"default":"http://localhost:8080/jsonrpc"},"username":{"type":"string","description":"The username set for Remote Control via Web Sever"},"password":{"type":"string","description":"The password set for Remote Control via Web Sever"}},"required":["url","username","password"],"title":"KodiData"},"WebScrobblerSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/WebScrobblerData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"type":{"type":"string","enum":["webscrobbler"]}},"required":["type"],"title":"WebScrobblerSourceAIOConfig"},"WebScrobblerData":{"type":"object","properties":{"slug":{"type":["string","null"],"description":"The URL ending that should be used to identify scrobbles for this source\n\nIn WebScrobbler's Webhook you must set an 'API URL'. All MS WebScrobbler sources must start like:\n\nhttp://localhost:9078/api/webscrobbler\n\nIf you are using multiple WebScrobbler sources (scrobbles for many users) you must use a slug to match Sources with each users extension.\n\nExample:\n\n* slug: 'usera' => API URL: http://localhost:9078/api/webscrobbler/usera\n* slug: 'userb' => API URL: http://localhost:9078/api/webscrobbler/userb\n\nIf no slug is found from an extension's incoming webhook event the first WebScrobbler source without a slug will be used"},"blacklist":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Block scrobbling from specific WebScrobbler Connectors","examples":[["youtube"]]},"whitelist":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Only allow scrobbling from specific WebScrobbler Connectors","examples":[["mixcloud","soundcloud","bandcamp"]]}},"title":"WebScrobblerData"},"ChromecastSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/ChromecastData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"type":{"type":"string","enum":["chromecast"]}},"required":["data","type"],"title":"ChromecastSourceAIOConfig"},"ChromecastData":{"type":"object","properties":{"blacklistDevices":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"DO NOT scrobble from any cast devices that START WITH these values, case-insensitive\n\nUseful when used with auto discovery","examples":[["home-mini","family-tv"]]},"whitelistDevices":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"ONLY scrobble from any cast device that START WITH these values, case-insensitive\n\nIf whitelist is present then blacklist is ignored\n\nUseful when used with auto discovery","examples":[["home-mini","family-tv"]]},"blacklistApps":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"DO NOT scrobble from any application that START WITH these values, case-insensitive","examples":[["spotify","pandora"]]},"whitelistApps":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"ONLY scrobble from any application that START WITH these values, case-insensitive\n\nIf whitelist is present then blacklist is ignored","examples":[["spotify","pandora"]]},"useAvahi":{"type":"boolean","description":"Try to use Avahi and avahi-browse to resolve mDNS devices instead of native mDNS querying\n\nUseful for docker (alpine) container where mDNS resolution is not yet supported. Avahi socket must be exposed to the container and avahi-tools must be installed.","default":false},"useAutoDiscovery":{"type":"boolean","description":"Use mDNS to discovery Google Cast devices on your next automatically?\n\nIf not explicitly set then it is TRUE if `devices` is not set"},"devices":{"type":"array","items":{"$ref":"#/definitions/ChromecastDeviceInfo"},"description":"A list of Google Cast devices to monitor\n\nIf this is used then `useAutoDiscovery` is set to FALSE, if not explicitly set"},"allowUnknownMedia":{"anyOf":[{"type":"boolean"},{"type":"array","items":{"type":"string"}}],"description":"Chromecast Apps report a \"media type\" in the status info returned for whatever is currently playing\n\n* If set to TRUE then Music AND Generic/Unknown media will be tracked for ALL APPS\n* If set to FALSE then only media explicitly typed as Music will be tracked for ALL APPS\n* If set to a list then only Apps whose name contain one of these values, case-insensitive, will have Music AND Generic/Unknown tracked\n\nSee https://developers.google.com/cast/docs/media/messages#MediaInformation \"metadata\" property","default":false},"forceMediaRecognitionOn":{"type":"array","items":{"type":"string"},"description":"Media provided by any App whose name is listed here will ALWAYS be tracked, regardless of the \"media type\" reported\n\nApps will be recognized if they CONTAIN any of these values, case-insensitive"}},"title":"ChromecastData"},"ChromecastDeviceInfo":{"type":"object","properties":{"name":{"type":"string","description":"A friendly name to identify this device","examples":["MySmartTV"]},"address":{"type":"string","description":"The IP address of the device","examples":["192.168.0.115"]}},"required":["name","address"],"title":"ChromecastDeviceInfo"},"MalojaSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/MalojaSourceData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"configureAs":{"type":"string","enum":["source"],"description":"When used in `maloja.config` this tells multi-scrobbler whether to use this data to configure a source or client.","default":"source","examples":["source"]},"type":{"type":"string","enum":["maloja"]}},"required":["data","type"],"title":"MalojaSourceAIOConfig"},"MalojaSourceData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"url":{"type":"string","description":"URL for maloja server","examples":["http://localhost:42010"]},"apiKey":{"type":"string","description":"API Key for Maloja server","examples":["myApiKey"]}},"required":["apiKey","url"],"title":"MalojaSourceData"},"MusikcubeSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/MusikcubeData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"type":{"type":"string","enum":["musikcube"]}},"required":["data","type"],"title":"MusikcubeSourceAIOConfig"},"MusikcubeData":{"type":"object","properties":{"url":{"type":"string","description":"URL of the Musikcube Websocket (Metadata) server to connect to\n\nYou MUST have enabled 'metadata' server and set a password: https://github.com/clangen/musikcube/wiki/remote-api-documentation\n * musikcube -> settings -> server setup\n\nThe URL you provide here will have all parts not explicitly defined filled in for you so if these are not the default you must define them.\n\nParts => [default value]\n\n* Protocol => `ws://`\n* Hostname => `localhost`\n* Port => `7905`","examples":["ws://localhost:7905"],"default":"ws://localhost:7905"},"password":{"type":"string","description":"Password set in Musikcube https://github.com/clangen/musikcube/wiki/remote-api-documentation\n\n* musikcube -> settings -> server setup -> password"},"device_id":{"type":"string"}},"required":["password"],"title":"MusikcubeData"},"MusicCastSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/MusicCastData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"type":{"type":"string","enum":["musiccast"]}},"required":["data","type"],"title":"MusicCastSourceAIOConfig"},"MusicCastData":{"type":"object","properties":{"url":{"type":"string","description":"The host or URL of the YamahaExtendedControl endpoint to use","examples":[["192.168.0.101","http://192.168.0.101/YamahaExtendedControl"]]}},"required":["url"],"title":"MusicCastData"},"MPDSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/MPDData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/MPDSourceOptions"},"type":{"type":"string","enum":["mpd"]}},"required":["data","options","type"],"title":"MPDSourceAIOConfig"},"MPDData":{"type":"object","properties":{"url":{"type":"string","description":"URL:PORT of the MPD server to connect to\n\nTo use this you must have TCP connections enabled for your MPD server https://mpd.readthedocs.io/en/stable/user.html#client-connections","examples":["localhost:6600"],"default":"localhost:6600"},"path":{"type":"string","description":"If using socket specify the path instead of url.\n\ntrailing `~` is replaced by your home directory"},"password":{"type":"string","description":"Password for the server, if set https://mpd.readthedocs.io/en/stable/user.html#permissions-and-passwords"}},"title":"MPDData"},"MPDSourceOptions":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"MPDSourceOptions"},"VLCSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/VLCData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/VLCSourceOptions"},"type":{"type":"string","enum":["vlc"]}},"required":["data","type"],"title":"VLCSourceAIOConfig"},"VLCData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"url":{"type":"string","description":"URL:PORT of the VLC server to connect to\n\nTo use this you must have the Web (http) interface module enabled and a password set https://foxxmd.github.io/multi-scrobbler/docs/configuration#vlc","examples":["localhost:8080"],"default":"localhost:8080"},"password":{"type":"string","description":"Password for the server"}},"required":["password"],"title":"VLCData"},"VLCSourceOptions":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"},"filenamePatterns":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"A list of regular expressions to use to extract metadata (title, album, artist) from a filename\n\nUsed when VLC reports only the filename for the current audio track"},"logFilenamePatterns":{"type":"boolean","description":"Log to DEBUG when a filename-only track is matched or not matched by filenamePatterns","default":false},"dumpVlcMetadata":{"type":"boolean","description":"Dump all the metadata VLC reports for an audio track to DEBUG.\n\nUse this if reporting an issue with VLC not correctly capturing metadata for a track.","default":false}},"title":"VLCSourceOptions"},"IcecastSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/IcecastData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/IcecastSourceOptions"},"type":{"type":"string","enum":["icecast"]}},"required":["data","type"],"title":"IcecastSourceAIOConfig"},"IcecastData":{"type":"object","properties":{"sources":{"type":"array","items":{"$ref":"#/definitions/IcecastSource"}},"icestatsEndpoint":{"type":"string"},"statsEndpoint":{"type":"string"},"nextsongsEndpoint":{"type":"string"},"sevenhtmlEndpoint":{"type":"string"},"icyMetaInt":{"type":"number"},"url":{"type":"string","description":"The Icecast stream URL"}},"required":["url"],"title":"IcecastData"},"IcecastSource":{"type":"string","enum":["icy","ogg","icestats","stats","sevenhtml","nextsongs"],"title":"IcecastSource"},"IcecastSourceOptions":{"type":"object","properties":{"systemScrobble":{"type":"boolean","description":"For Sources that support manual listening, should MS default to scrobbling when no user interaction has occurred?\n\nIf not specified MS will use a Source's specific behavior, see Source's documentation."},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"IcecastSourceOptions"},"AzuracastSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/AzuracastData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"type":{"type":"string","enum":["azuracast"]}},"required":["data","type"],"title":"AzuracastSourceAIOConfig"},"AzuracastData":{"type":"object","properties":{"url":{"type":"string","description":"Base URL of the Azuracast instance\n\nThis does NOT include the station. If a station is included it will be ignored. Use `station` field to specify station, if necessary","examples":["https://radio.mydomain.tld","http://localhost:80"]},"station":{"type":"string","description":"The specific station to monitor\n\nScrobbling will only occur if any of the monitor conditions are met AND the station is ONLINE.\n\nTo monitor multiple stations create a Source for each station.","examples":["my-station-1"]},"monitorWhenListeners":{"type":["boolean","number"],"description":"Only activate scrobble monitoring if station\n\n* `true` => has any current listeners\n* `number` => has EQUAL TO or MORE THAN X number of listeners"},"monitorWhenLive":{"type":"boolean","description":"Only activate scrobble monitoring if station has a live DJ/Streamer","default":true},"apiKey":{"type":"string","description":"API Key used to access data about private streams\n\nhttps://www.azuracast.com/docs/developers/apis/#api-authentication"}},"required":["url","station"],"title":"AzuracastData"},"KoitoSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/KoitoSourceData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"configureAs":{"type":"string","enum":["source"],"description":"When used in `koito.config` this tells multi-scrobbler whether to use this data to configure a source or client.","default":"source","examples":["source"]},"type":{"type":"string","enum":["koito"]}},"required":["data","type"],"title":"KoitoSourceAIOConfig"},"KoitoSourceData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"url":{"type":"string","description":"URL for the Koito server","examples":["http://192.168.0.100:4110"]},"token":{"type":"string","description":"User token for the user to scrobble for","examples":["pM195xPV98CDpk0QW47FIIOR8AKATAX5DblBF-Jq0t1MbbKL"]},"username":{"type":"string","description":"Username of the user to scrobble for"}},"required":["token","url","username"],"title":"KoitoSourceData"},"TealSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/TealSourceData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/TealSourceOptions"},"configureAs":{"type":"string","enum":["source"],"description":"Should always be `souce` when using Tealfm as a Source","default":"source","examples":["source"]},"type":{"type":"string","enum":["tealfm"]}},"required":["data","type"],"title":"TealSourceAIOConfig"},"TealSourceData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"baseUri":{"type":"string","description":"The base URI of the Multi-Scrobbler to use for ATProto OAuth\n\nOnly include this if you want to use OAuth. The URI must be a non-IP/non-local domain using https: protocol."},"identifier":{"type":"string","description":"Identify the account to login as\n\n* For **App Password** Auth - your email\n* For **Oauth** - your handle minus the @"},"appPassword":{"type":"string","description":"The [App Password](https://atproto.com/specs/xrpc#app-passwords) you created for your account\n\nThis is created under https://bsky.app/settings/app-passwords\n\n**Use this if you are self-hosting Multi-Scrobbler on localhost or accessed like http://IP:PORT**"},"serviceAllow":{"type":"array","items":{"type":"string"}},"serviceDeny":{"type":"array","items":{"type":"string"}}},"required":["identifier"],"title":"TealSourceData"},"TealSourceOptions":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"TealSourceOptions"},"RockskySourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/RockskySourceData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/RockskySourceOptions"},"configureAs":{"type":"string","enum":["source"],"description":"When used in `rocksky.config` this tells multi-scrobbler whether to use this data to configure a source or client.","default":"source","examples":["source"]},"type":{"type":"string","enum":["rocksky"]}},"required":["data","type"],"title":"RockskySourceAIOConfig"},"RockskySourceData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"key":{"type":"string","description":"API Key generated from [API Applications](https://docs.rocksky.app/migrating-from-listenbrainz-to-rocksky-1040189m0) in Rocksky for your account","examples":["6794186bf-1157-4de6-80e5-uvb411f3ea2b"]},"handle":{"type":"string","description":"The **fully-qualified** handle for your ATPRoto/Bluesky account, like:\n\n* alice.bsky.social\n* foxxmd.com\n* mysuer.blacksky.app"}},"required":["handle","key"],"title":"RockskySourceData"},"RockskySourceOptions":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"},"audioScrobblerUrl":{"type":"string","description":"URL for the Rocksky *Listenbrainz* endpoint, if not using the default","examples":["https://audioscrobbler.rocksky.app"],"default":"https://audioscrobbler.rocksky.app"},"apiUrl":{"type":"string","description":"URL for the Rocksky *API* endpoint, if not using the default","examples":["https://api.rocksky.app"],"default":"https://api.rocksky.app"}},"title":"RockskySourceOptions"}}} \ No newline at end of file +{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"sourceDefaults":{"$ref":"#/definitions/SourceRetryOptions"},"sources":{"type":"array","items":{"$ref":"#/definitions/SourceAIOConfig"}}},"definitions":{"SourceRetryOptions":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]}},"title":"SourceRetryOptions"},"SourceAIOConfig":{"anyOf":[{"$ref":"#/definitions/SpotifySourceAIOConfig"},{"$ref":"#/definitions/PlexApiSourceAIOConfig"},{"$ref":"#/definitions/DeezerSourceAIOConfig"},{"$ref":"#/definitions/DeezerInternalAIOConfig"},{"$ref":"#/definitions/ListenbrainzEndpointSourceAIOConfig"},{"$ref":"#/definitions/LastFMEndpointSourceAIOConfig"},{"$ref":"#/definitions/SubsonicSourceAIOConfig"},{"$ref":"#/definitions/JellyApiSourceAIOConfig"},{"$ref":"#/definitions/LastFmSouceAIOConfig"},{"$ref":"#/definitions/LibrefmSouceAIOConfig"},{"$ref":"#/definitions/YTMusicSourceAIOConfig"},{"$ref":"#/definitions/MPRISSourceAIOConfig"},{"$ref":"#/definitions/MopidySourceAIOConfig"},{"$ref":"#/definitions/ListenBrainzSourceAIOConfig"},{"$ref":"#/definitions/JRiverSourceAIOConfig"},{"$ref":"#/definitions/KodiSourceAIOConfig"},{"$ref":"#/definitions/WebScrobblerSourceAIOConfig"},{"$ref":"#/definitions/ChromecastSourceAIOConfig"},{"$ref":"#/definitions/MalojaSourceAIOConfig"},{"$ref":"#/definitions/MusikcubeSourceAIOConfig"},{"$ref":"#/definitions/MusicCastSourceAIOConfig"},{"$ref":"#/definitions/MPDSourceAIOConfig"},{"$ref":"#/definitions/VLCSourceAIOConfig"},{"$ref":"#/definitions/IcecastSourceAIOConfig"},{"$ref":"#/definitions/AzuracastSourceAIOConfig"},{"$ref":"#/definitions/KoitoSourceAIOConfig"},{"$ref":"#/definitions/TealSourceAIOConfig"},{"$ref":"#/definitions/RockskySourceAIOConfig"},{"$ref":"#/definitions/SonosSourceAIOConfig"}],"title":"SourceAIOConfig"},"SpotifySourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/SpotifySourceData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"type":{"type":"string","enum":["spotify"]}},"required":["data","type"],"title":"SpotifySourceAIOConfig"},"SpotifySourceData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)\n\nIt is unlikely you should need to change this unless you scrobble many very short tracks often\n\nReading:\n* https://developer.spotify.com/documentation/web-api/guides/rate-limits/\n* https://medium.com/mendix/limiting-your-amount-of-calls-in-mendix-most-of-the-time-rest-835dde55b10e\n * Rate limit may ~180 req/min\n* https://community.spotify.com/t5/Spotify-for-Developers/Web-API-ratelimit/m-p/5503150/highlight/true#M7930\n * Informally indicated as 20 req/sec? Probably for burstiness","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"clientId":{"type":"string","description":"spotify client id","examples":["787c921a2a2ab42320831aba0c8f2fc2"]},"clientSecret":{"type":"string","description":"spotify client secret","examples":["ec42e09d5ae0ee0f0816ca151008412a"]},"redirectUri":{"type":"string","description":"spotify redirect URI -- required only if not the default shown here. URI must end in \"callback\"","default":"http://localhost:9078/callback","examples":["http://localhost:9078/callback"]}},"required":["clientId","clientSecret"],"title":"SpotifySourceData"},"CommonSourceOptions":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"CommonSourceOptions"},"LogLevel":{"type":"string","enum":["silent","fatal","error","warn","info","log","verbose","debug","trace"],"description":"Names of log levels that can be invoked on the logger\n\nFrom lowest to highest:\n\n* `trace`\n* `debug`\n* `verbose`\n* `log`\n* `info`\n* `warn`\n* `error`\n* `fatal`\n* `silent` (will never output anything)\n\nWhen used in `LogOptions` specifies the **minimum** level the output should log at.","title":"LogLevel"},"FileLogOptions":{"type":"object","properties":{"timestamp":{"type":"string","enum":["unix","iso","auto"],"description":"For rolling log files\n\nWhen\n* value passed to rolling destination is a string (`path` from LogOptions is a string) and\n* `frequency` is defined\n\nThis determines the format of the datetime inserted into the log file name:\n\n* `unix` - unix epoch timestamp in milliseconds\n* `iso` - Full [ISO8601](https://en.wikipedia.org/wiki/ISO_8601) datetime IE '2024-03-07T20:11:34Z'\n* `auto`\n * When frequency is `daily` only inserts date IE YYYY-MM-DD\n * Otherwise inserts full ISO8601 datetime","default":"auto"},"size":{"type":["number","string"],"description":"The maximum size of a given rolling log file.\n\nCan be combined with frequency. Use k, m and g to express values in KB, MB or GB.\n\nNumerical values will be considered as MB.","default":"10MB"},"frequency":{"anyOf":[{"type":"string","enum":["daily"]},{"type":"string","enum":["hourly"]},{"type":"number"}],"description":"The amount of time a given rolling log file is used. Can be combined with size.\n\nUse `daily` or `hourly` to rotate file every day (or every hour). Existing file within the current day (or hour) will be re-used.\n\nNumerical values will be considered as a number of milliseconds. Using a numerical value will always create a new file upon startup.","default":"daily"},"path":{"anyOf":[{"type":"string"},{"$comment":"() => string"}],"description":"The path and filename to use for log files.\n\nIf using rolling files the filename will be appended with `.N` (a number) BEFORE the extension based on rolling status.\n\nMay also be specified using env LOG_PATH or a function that returns a string.\n\nIf path is relative the absolute path will be derived from `logBaseDir` (in `LoggerAppExtras`) which defaults to CWD","default":"./logs/app.log"},"level":{"anyOf":[{"$ref":"#/definitions/LogLevel"},{"type":"boolean","const":false}],"description":"Specify the minimum log level to output to rotating files. If `false` no log files will be created."}},"title":"FileLogOptions"},"ScrobbleThresholds":{"type":"object","properties":{"duration":{"type":["number","null"],"description":"The number of seconds a track has been listened to before it should be considered scrobbled.\n\nSet to null to disable.","default":240,"examples":[240]},"percent":{"type":["number","null"],"description":"The percentage (as an integer) of a track that should have been seen played before it should be scrobbled. Only used if the Source provides information about how long the track is.\n\nSet to null to disable.\n\nNOTE: This should be used with care when the Source is a \"polling\" type (has an 'interval' property). If the track is short and the interval is too high MS may ignore the track if percentage is high because it had not \"seen\" the track for long enough from first discovery, even if you have been playing the track for longer.","default":50,"examples":[50]}},"title":"ScrobbleThresholds"},"PlayTransformOptions":{"type":"object","properties":{"log":{"anyOf":[{"type":"boolean"},{"type":"string","enum":["all"]}]},"preCompare":{"$ref":"#/definitions/PlayTransformPartsConfig%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%3E"},"compare":{"type":"object","properties":{"candidate":{"$ref":"#/definitions/PlayTransformPartsConfig%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%3E"},"existing":{"$ref":"#/definitions/PlayTransformPartsConfig%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%3E"}}},"postCompare":{"$ref":"#/definitions/PlayTransformPartsConfig%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%3E"}},"title":"PlayTransformOptions"},"PlayTransformPartsConfig<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm)>":{"anyOf":[{"$ref":"#/definitions/PlayTransformPartsArray%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%2CMaybeStageTyped%3E"},{"$ref":"#/definitions/PlayTransformParts%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%2CMaybeStageTyped%3E"}],"description":"Represents the weakly-defined user config. May be an array of parts or one parts object","title":"PlayTransformPartsConfig<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm)>"},"PlayTransformPartsArray<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm),MaybeStageTyped>":{"type":"array","items":{"$ref":"#/definitions/PlayTransformParts%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%2CMaybeStageTyped%3E"},"title":"PlayTransformPartsArray<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm),MaybeStageTyped>"},"PlayTransformParts<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm),MaybeStageTyped>":{"anyOf":[{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"title":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"artists":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"albumArtists":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"album":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"duration":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"meta":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"onSuccess":{"$ref":"#/definitions/FlowControlTerm"},"onFailure":{"$ref":"#/definitions/FlowControlTerm"},"onSkip":{"$ref":"#/definitions/FlowControlTerm"},"failureReturnPartial":{"type":"boolean"},"type":{"$ref":"#/definitions/StageTypeMetadata"},"name":{"type":"string"},"stageHash":{"type":"string"},"score":{"type":"number"}},"required":["type"]},{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"title":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"artists":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"albumArtists":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"album":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"duration":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"meta":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"onSuccess":{"$ref":"#/definitions/FlowControlTerm"},"onFailure":{"$ref":"#/definitions/FlowControlTerm"},"onSkip":{"$ref":"#/definitions/FlowControlTerm"},"failureReturnPartial":{"type":"boolean"},"type":{"$ref":"#/definitions/StageTypeUser"},"name":{"type":"string"},"stageHash":{"type":"string"}},"required":["type"]},{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"title":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"artists":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"albumArtists":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"album":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"duration":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"meta":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"onSuccess":{"$ref":"#/definitions/FlowControlTerm"},"onFailure":{"$ref":"#/definitions/FlowControlTerm"},"onSkip":{"$ref":"#/definitions/FlowControlTerm"},"failureReturnPartial":{"type":"boolean"},"type":{"type":"string","enum":["native"]},"name":{"type":"string"},"stageHash":{"type":"string"}},"required":["type"]},{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"title":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"artists":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"albumArtists":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"album":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"duration":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"meta":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"onSuccess":{"$ref":"#/definitions/FlowControlTerm"},"onFailure":{"$ref":"#/definitions/FlowControlTerm"},"onSkip":{"$ref":"#/definitions/FlowControlTerm"},"failureReturnPartial":{"type":"boolean"},"name":{"type":"string"}}},{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"title":{},"artists":{},"albumArtists":{},"album":{},"duration":{},"meta":{},"onSuccess":{"$ref":"#/definitions/FlowControlTerm"},"onFailure":{"$ref":"#/definitions/FlowControlTerm"},"onSkip":{"$ref":"#/definitions/FlowControlTerm"},"failureReturnPartial":{"type":"boolean"},"type":{"type":"string"},"name":{"type":"string"},"stageHash":{"type":"string"}},"required":["type"]}],"title":"PlayTransformParts<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm),MaybeStageTyped>"},"WhenConditionsConfig":{"$ref":"#/definitions/WhenConditions%3Cstring%3E","title":"WhenConditionsConfig"},"WhenConditions":{"type":"array","items":{"$ref":"#/definitions/WhenParts%3Cstring%3E"},"title":"WhenConditions"},"WhenParts":{"$ref":"#/definitions/PlayTransformPartsAtomic%3Cstring%3E","title":"WhenParts"},"PlayTransformPartsAtomic":{"type":"object","properties":{"title":{"type":"string"},"artists":{"type":"string"},"albumArtists":{"type":"string"},"album":{"type":"string"},"duration":{"type":"string"},"meta":{"type":"string"}},"title":"PlayTransformPartsAtomic"},"Whennable":{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"}},"title":"Whennable"},"FlowControlTerm":{"type":"string","enum":["continue","stop"],"title":"FlowControlTerm"},"StageTypeMetadata":{"type":"string","enum":["spotify","musicbrainz","native"],"title":"StageTypeMetadata"},"SearchAndReplaceTerm":{"anyOf":[{"type":"string"},{"$ref":"#/definitions/ConditionalSearchAndReplaceTerm"}],"title":"SearchAndReplaceTerm"},"ConditionalSearchAndReplaceTerm":{"$ref":"#/definitions/ConditionalSearchAndReplaceRegExp","title":"ConditionalSearchAndReplaceTerm"},"ConditionalSearchAndReplaceRegExp":{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"search":{"anyOf":[{"type":"string"},{"type":"string","format":"regex"}],"description":"The search value to test for\n\nCan be a normal string (converted to a case-sensitive literal) or a valid regular expression as a string, or an actual RegExp object","examples":[["find this string","/some string*/ig"]]},"replace":{"type":"string","description":"The replacement string/value to use when search is found\n\nThis can be a literal string like `'replace with this`, an empty string to remove the search value (`''`), or a special regex value\n\nSee replacement here for more information: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace"},"test":{"$comment":"(obj: SearchAndReplaceRegExp) => boolean","type":"object","properties":{"namedArgs":{"type":"object","properties":{"obj":{"$ref":"#/definitions/SearchAndReplaceRegExp"}},"required":["obj"],"additionalProperties":false}},"description":"An optional function to execute before running this search-and-replace that decides if it should run at all"}},"required":["replace","search"],"title":"ConditionalSearchAndReplaceRegExp"},"SearchAndReplaceRegExp":{"type":"object","properties":{"search":{"anyOf":[{"type":"string"},{"type":"string","format":"regex"}],"description":"The search value to test for\n\nCan be a normal string (converted to a case-sensitive literal) or a valid regular expression as a string, or an actual RegExp object","examples":[["find this string","/some string*/ig"]]},"replace":{"type":"string","description":"The replacement string/value to use when search is found\n\nThis can be a literal string like `'replace with this`, an empty string to remove the search value (`''`), or a special regex value\n\nSee replacement here for more information: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace"},"test":{"$comment":"(obj: SearchAndReplaceRegExp) => boolean","type":"object","properties":{"namedArgs":{"type":"object","properties":{"obj":{"$ref":"#/definitions/SearchAndReplaceRegExp"}},"required":["obj"],"additionalProperties":false}},"description":"An optional function to execute before running this search-and-replace that decides if it should run at all"}},"required":["search","replace"],"title":"SearchAndReplaceRegExp"},"ExternalMetadataTerm":{"anyOf":[{"type":"boolean"},{"not":{}},{"$ref":"#/definitions/Whennable"}],"title":"ExternalMetadataTerm"},"StageTypeUser":{"type":"string","enum":["user"],"title":"StageTypeUser"},"PlexApiSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/PlexApiData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/PlexApiOptions"},"type":{"type":"string","enum":["plex"]}},"required":["data","type"],"title":"PlexApiSourceAIOConfig"},"PlexApiData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"token":{"type":"string"},"url":{"type":"string","description":"http(s)://HOST:PORT of the Plex server to connect to"},"usersAllow":{"anyOf":[{"type":"string"},{"type":"boolean","enum":[true]},{"type":"array","items":{"type":"string"}}],"description":"Only scrobble for specific users (case-insensitive)\n\nIf `true` MS will scrobble activity from all users"},"usersBlock":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Do not scrobble for these users (case-insensitive)"},"devicesAllow":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Only scrobble if device or application name contains strings from this list (case-insensitive)"},"devicesBlock":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Do not scrobble if device or application name contains strings from this list (case-insensitive)"},"librariesAllow":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Only scrobble if library name contains string from this list (case-insensitive)"},"librariesBlock":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Do not scrobble if library name contains strings from this list (case-insensitive)"}},"required":["url"],"title":"PlexApiData"},"PlexApiOptions":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"},"ignoreInvalidCert":{"type":"boolean","description":"Ignore invalid cert errors when connecting to Plex\n\nUseful for Plex servers using \"Required\" Secure Connections with self-signed certificates\n\nDo not enable unless you know you need this.","default":false}},"title":"PlexApiOptions"},"DeezerSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/DeezerData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"type":{"type":"string","enum":["deezer"]}},"required":["data","type"],"title":"DeezerSourceAIOConfig"},"DeezerData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"clientId":{"type":"string","description":"deezer client id","examples":["a89cba1569901a0671d5a9875fed4be1"]},"clientSecret":{"type":"string","description":"deezer client secret","examples":["ec42e09d5ae0ee0f0816ca151008412a"]},"redirectUri":{"type":"string","description":"deezer redirect URI -- required only if not the default shown here. URI must end in \"callback\"","default":"http://localhost:9078/deezer/callback","examples":["http://localhost:9078/deezer/callback"]}},"required":["clientId","clientSecret"],"title":"DeezerData"},"DeezerInternalAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/DeezerInternalData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/DeezerInternalSourceOptions"},"type":{"type":"string","enum":["deezer"]}},"required":["data","type"],"title":"DeezerInternalAIOConfig"},"DeezerInternalData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"arl":{"type":"string","description":"ARL retrieved from Deezer response header"},"userAgent":{"type":"string","description":"User agent","default":"Mozilla/5.0 (X11; Linux i686; rv:135.0) Gecko/20100101 Firefox/135.0"},"accountId":{"type":"string","description":"The ID (USER_ID) of the linked account to monitor. If not set, monitors the main ARL account"}},"required":["arl"],"title":"DeezerInternalData"},"DeezerInternalSourceOptions":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"},"fuzzyDiscoveryIgnore":{"anyOf":[{"type":"boolean"},{"type":"string","enum":["aggressive"]}]}},"title":"DeezerInternalSourceOptions"},"ListenbrainzEndpointSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/ListenbrainzEndpointData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"type":{"type":"string","enum":["endpointlz"]}},"required":["type"],"title":"ListenbrainzEndpointSourceAIOConfig"},"ListenbrainzEndpointData":{"type":"object","properties":{"slug":{"type":["string","null"],"description":"The URL ending that should be used to identify scrobbles for this source\n\nIf you are using multiple Listenbrainz endpoint sources (scrobbles for many users) you can use a slug to match Sources with individual users/origins\n\nExample:\n\n* slug: 'usera' => API URL: http://localhost:9078/api/listenbrainz/usera\n* slug: 'originb' => API URL: http://localhost:9078/api/listenbrainz/originb\n\nIf no slug is found from an extension's incoming webhook event the first Listenbrainz source without a slug will be used"},"token":{"type":["string","null"],"description":"If an LZ submission request contains this token in the Authorization Header it will be used to match the submission with this Source\n\nSee: https://listenbrainz.readthedocs.io/en/latest/users/api/index.html#add-the-user-token-to-your-requests"}},"title":"ListenbrainzEndpointData"},"LastFMEndpointSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/LastFMEndpointData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"type":{"type":"string","enum":["endpointlfm"]}},"required":["type"],"title":"LastFMEndpointSourceAIOConfig"},"LastFMEndpointData":{"type":"object","properties":{"slug":{"type":["string","null"],"description":"The URL ending that should be used to identify scrobbles for this source\n\nIf you are using multiple Last.fm endpoint sources (scrobbles for many users) you can use a slug to match Sources with individual users/origins\n\nExample:\n\n* slug: 'usera' => API URL: http://localhost:9078/api/lastfm/usera\n* slug: 'originb' => API URL: http://localhost:9078/api/lastfm/originb\n\nIf no slug is found from an extension's incoming webhook event the first Last.fm source without a slug will be used"}},"title":"LastFMEndpointData"},"SubsonicSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/SubsonicData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"type":{"type":"string","enum":["subsonic"]}},"required":["data","type"],"title":"SubsonicSourceAIOConfig"},"SubsonicData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"url":{"type":"string","description":"URL of the subsonic media server to query","examples":["http://airsonic.local"]},"user":{"type":"string","description":"Username to login to the server with","examples":[["MyUser"]]},"password":{"type":"string","description":"Password for the user to login to the server with","examples":["MyPassword"]},"ignoreTlsErrors":{"type":"boolean","description":"If your subsonic server is using self-signed certs you may need to disable TLS errors in order to get a connection\n\nWARNING: This should be used with caution as your traffic may not be encrypted.","default":false},"legacyAuthentication":{"type":"boolean","description":"Older Subsonic versions, and some badly implemented servers (Nextcloud), use legacy authentication which sends your password in CLEAR TEXT. This is less secure than the newer, recommended hashing authentication method but in some cases it is needed. See \"Authentication\" section here => https://www.subsonic.org/pages/api.jsp\n\nIf this option is not specified it will be turned on if the subsonic server responds with error code 41 \"Token authentication not supported for LDAP users.\" -- See Error Handling section => https://www.subsonic.org/pages/api.jsp","default":false},"usersAllow":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Only scrobble for specific users (case-insensitive)\n\nIf undefined or an empty string/list MS will scrobble activity from all users"}},"required":["url","user","password"],"title":"SubsonicData"},"JellyApiSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/JellyApiData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/JellyApiOptions"},"type":{"type":"string","enum":["jellyfin"]}},"required":["data","type"],"title":"JellyApiSourceAIOConfig"},"JellyApiData":{"type":"object","properties":{"url":{"type":"string","description":"HOST:PORT of the Jellyfin server to connect to"},"user":{"type":"string","description":"The username of the user to authenticate for or track scrobbles for"},"password":{"type":"string","description":"Password of the username to authenticate for\n\nRequired if `apiKey` is not provided."},"apiKey":{"type":"string","description":"API Key to authenticate with.\n\nRequired if `password` is not provided."},"usersAllow":{"anyOf":[{"type":"string"},{"type":"boolean","enum":[true]},{"type":"array","items":{"type":"string"}}],"description":"Only scrobble for specific users (case-insensitive)\n\nIf `true` MS will scrobble activity from all users"},"usersBlock":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Do not scrobble for these users (case-insensitive)"},"devicesAllow":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Only scrobble if device or application name contains strings from this list (case-insensitive)"},"devicesBlock":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Do not scrobble if device or application name contains strings from this list (case-insensitive)"},"librariesAllow":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Only scrobble if library name contains string from this list (case-insensitive)"},"librariesBlock":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Do not scrobble if library name contains strings from this list (case-insensitive)"},"additionalAllowedLibraryTypes":{"type":"array","items":{},"description":"Allow MS to scrobble audio media in libraries classified other than 'music'\n\n`librariesAllow` will achieve the same result as this but this is more convenient if you do not want to explicitly list every library name or are only using `librariesBlock`"},"allowUnknown":{"type":"boolean","description":"Force media with a type of \"Unknown\" to be counted as Audio","default":false,"deprecated":"use allowMediaTypes instead"},"allowMediaTypes":{"anyOf":[{"type":"array","items":{}},{"type":"string"}],"description":"Allow these media types to be scrobbled.\n\nIf not defined or empty, uses 'Audio' as default. If non-empty then *only* uses these types (make sure you include Audio!)\n\nValues are case-insensitive.\n\nSee https://github.com/jellyfin/jellyfin-sdk-typescript/blob/master/src/generated-client/models/media-type.ts#L22 for possible types"},"frontendUrlOverride":{"type":"string","description":"HOST:PORT of the Jellyfin server that your browser will be able to access from the frontend (and thus load images and links from)\nIf unspecified it will use the normal server HOST and PORT from the `url`\nNecessary if you are using a reverse proxy or other network configuration that prevents the frontend from accessing the server directly\n\nENV: JELLYFIN_FRONTEND_URL_OVERRIDE"}},"required":["url","user"],"title":"JellyApiData"},"JellyApiOptions":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"JellyApiOptions"},"LastFmSouceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/LastFmSourceData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"configureAs":{"type":"string","enum":["source"],"description":"When used in `lastfm.config` this tells multi-scrobbler whether to use this data to configure a source or client.","default":"source","examples":["source"]},"type":{"type":"string","enum":["lastfm"]}},"required":["data","type"],"title":"LastFmSouceAIOConfig"},"LastFmSourceData":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"apiKey":{"type":"string","description":"API Key generated from Last.fm/Libre.fm account","examples":["787c921a2a2ab42320831aba0c8f2fc2"]},"secret":{"type":"string","description":"Secret generated from Last.fm/Libre.fm account","examples":["ec42e09d5ae0ee0f0816ca151008412a"]},"session":{"type":"string","description":"Optional session id returned from a completed auth flow"},"redirectUri":{"type":"string","description":"Optional URI to use for callback. Specify this if callback should be different than the default. MUST have \"lastfm/callback\" in the URL somewhere.","default":"http://localhost:9078/lastfm/callback","examples":["http://localhost:9078/lastfm/callback"]},"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"}},"required":["apiKey","secret"],"title":"LastFmSourceData"},"LibrefmSouceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/LibrefmData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"configureAs":{"type":"string","enum":["source"],"description":"When used in `librefm.config` this tells multi-scrobbler whether to use this data to configure a source or client.","default":"source","examples":["source"]},"type":{"type":"string","enum":["librefm"]}},"required":["data","type"],"title":"LibrefmSouceAIOConfig"},"LibrefmData":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"apiKey":{"type":"string","description":"Optional Secret for Libre.fm account\n\nThis can be anything, or it will be generated by multi-scrobbler","examples":["anyValue"]},"secret":{"type":"string","description":"Optional Secret for Libre.fm account\n\nThis can be anything, or it will be generated by multi-scrobbler","examples":["anyValue"]},"session":{"type":"string","description":"Optional session id returned from a completed auth flow"},"path":{"type":"string"},"urlBase":{"type":"string","description":"(Optional) The host and path prefix for your Libre.fm instance","default":"https://libre.fm/2.0/"},"redirectUri":{"type":"string","description":"Optional URI to use for callback. Specify this if callback should be different than the default. MUST have \"librefm/callback\" in the URL somewhere.","default":"http://localhost:9078/librefm/callback","examples":["http://localhost:9078/librefm/callback"]}},"title":"LibrefmData"},"YTMusicSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/YTMusicData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"type":"object","properties":{"logAuth":{"type":"boolean","description":"When true MS will log to DEBUG all of the credentials data it receives from YTM"},"logDiff":{"type":"boolean","description":"Always log history diff\n\nBy default MS will log to `WARN` if history diff is inconsistent but does not log if diff is expected (on new tracks found)\nSet this to `true` to ALWAYS log diff on new tracks. Expected diffs will log to `DEBUG` and inconsistent diffs will continue to log to `WARN`","default":false},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}}},"type":{"type":"string","enum":["ytmusic"]}},"required":["type"],"title":"YTMusicSourceAIOConfig"},"YTMusicData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"cookie":{"type":"string","description":"The cookie retrieved from the Request Headers of music.youtube.com after logging in.\n\nSee https://ytmusicapi.readthedocs.io/en/stable/setup/browser.html#copy-authentication-headers for how to retrieve this value.","examples":["VISITOR_INFO1_LIVE=jMp2xA1Xz2_PbVc; __Secure-3PAPISID=3AxsXpy0M/AkISpjek; ..."]},"clientId":{"type":"string","description":"Google Cloud Console project OAuth Client ID\n\nGenerated from a custom OAuth Client, see docs"},"clientSecret":{"type":"string","description":"Google Cloud Console project OAuth Client Secret\n\nGenerated from a custom OAuth Client, see docs"},"redirectUri":{"type":"string","description":"Google Cloud Console project OAuth Client Authorized redirect URI\n\nGenerated from a custom OAuth Client, see docs. multi-scrobbler will generate a default based on BASE_URL.\nOnly specify this if the default does not work for you."},"innertubeOptions":{"$ref":"#/definitions/InnertubeOptions","description":"Additional options for authorization and tailoring YTM client"}},"title":"YTMusicData"},"InnertubeOptions":{"type":"object","properties":{"po_token":{"type":"string","description":"Proof of Origin token\n\nMay be required if YTM starts returning 403"},"visitor_data":{"type":"string","description":"Visitor ID value found in VISITOR_INFO1_LIVE or visitorData cookie\n\nMay be required if YTM starts returning 403"},"account_index":{"type":"number","description":"If account login results in being able to choose multiple account, use a zero-based index to choose which one to monitor","examples":[0,1]},"location":{"type":"string"},"lang":{"type":"string"},"generate_session_locally":{"type":"boolean"},"device_category":{"type":"string"},"client_type":{"type":"string"},"timezone":{"type":"string"}},"title":"InnertubeOptions"},"MPRISSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/MPRISData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"type":{"type":"string","enum":["mpris"]}},"required":["data","type"],"title":"MPRISSourceAIOConfig"},"MPRISData":{"type":"object","properties":{"blacklist":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"DO NOT scrobble from any players that START WITH these values, case-insensitive","examples":[["spotify","vlc"]]},"whitelist":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"ONLY from any players that START WITH these values, case-insensitive\n\nIf whitelist is present then blacklist is ignored","examples":[["spotify","vlc"]]}},"title":"MPRISData"},"MopidySourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/MopidyData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"type":{"type":"string","enum":["mopidy"]}},"required":["data","type"],"title":"MopidySourceAIOConfig"},"MopidyData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"url":{"type":"string","description":"URL of the Mopidy HTTP server to connect to\n\nYou MUST have Mopidy-HTTP extension enabled: https://mopidy.com/ext/http\n\nmulti-scrobbler connects to the WebSocket endpoint that ultimately looks like this => `ws://localhost:6680/mopidy/ws/`\n\nThe URL you provide here will have all parts not explicitly defined filled in for you so if these are not the default you must define them.\n\nParts => [default value]\n\n* Protocol => `ws://`\n* Hostname => `localhost`\n* Port => `6680`\n* Path => `/mopidy/ws/`","examples":["ws://localhost:6680/mopidy/ws/"],"default":"ws://localhost:6680/mopidy/ws/"},"uriBlacklist":{"type":"array","items":{"type":"string"},"description":"Do not scrobble tracks whose URI STARTS WITH any of these strings, case-insensitive\n\nEX: Don't scrobble tracks from soundcloud by adding 'soundcloud' to this list.\n\nList is ignored if uriWhitelist is used."},"uriWhitelist":{"type":"array","items":{"type":"string"},"description":"Only scrobble tracks whose URI STARTS WITH any of these strings, case-insensitive\n\nEX: Only scrobble tracks from soundcloud by adding 'soundcloud' to this list."},"albumBlacklist":{"type":"array","items":{"type":"string"},"description":"Remove album data that matches any case-insensitive string from this list when scrobbling,\n\nFor certain sources (Soundcloud) Mopidy does not have all track info (Album) and will instead use \"Soundcloud\" as the Album name. You can prevent multi-scrobbler from using this bad Album data by adding the fake name to this list. Multi-scrobbler will still scrobble the track, just without the bad data.","examples":[["Soundcloud","Mixcloud"]],"default":["Soundcloud"]}},"title":"MopidyData"},"ListenBrainzSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/ListenBrainzSourceData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"configureAs":{"type":"string","enum":["source"],"description":"When used in `listenbrainz.config` this tells multi-scrobbler whether to use this data to configure a source or client.","default":"source","examples":["source"]},"type":{"type":"string","enum":["listenbrainz"]}},"required":["data","type"],"title":"ListenBrainzSourceAIOConfig"},"ListenBrainzSourceData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"url":{"type":"string","description":"URL for the ListenBrainz server, if not using the default","examples":["https://api.listenbrainz.org/"],"default":"https://api.listenbrainz.org/"},"token":{"type":"string","description":"User token for the user to scrobble for","examples":["6794186bf-1157-4de6-80e5-uvb411f3ea2b"]},"username":{"type":"string","description":"Username of the user to scrobble for"}},"required":["token","username"],"title":"ListenBrainzSourceData"},"JRiverSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/JRiverData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"type":{"type":"string","enum":["jriver"]}},"required":["data","type"],"title":"JRiverSourceAIOConfig"},"JRiverData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"url":{"type":"string","description":"URL of the JRiver HTTP server to connect to\n\nmulti-scrobbler connects to the Web Service Interface endpoint that ultimately looks like this => `http://yourDomain:52199/MCWS/v1/`\n\nThe URL you provide here will have all parts not explicitly defined filled in for you so if these are not the default you must define them.\n\nParts => [default value]\n\n* Protocol => `http://`\n* Hostname => `localhost`\n* Port => `52199`\n* Path => `/MCWS/v1/`","examples":["http://localhost:52199/MCWS/v1/"],"default":"http://localhost:52199/MCWS/v1/"},"username":{"type":"string","description":"If you have enabled authentication, the username you set"},"password":{"type":"string","description":"If you have enabled authentication, the password you set"}},"required":["url"],"title":"JRiverData"},"KodiSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/KodiData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"type":{"type":"string","enum":["kodi"]}},"required":["data","type"],"title":"KodiSourceAIOConfig"},"KodiData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"url":{"type":"string","description":"URL of the Kodi HTTP server to connect to\n\nmulti-scrobbler connects to the Web Service Interface endpoint that ultimately looks like this => `http://yourDomain:8080/jsonrpc`\n\nThe URL you provide here will have all parts not explicitly defined filled in for you so if these are not the default you must define them.\n\nParts => [default value]\n\n* Protocol => `http://`\n* Hostname => `localhost`\n* Port => `8080`\n* Path => `/jsonrpc`","examples":["http://localhost:8080/jsonrpc"],"default":"http://localhost:8080/jsonrpc"},"username":{"type":"string","description":"The username set for Remote Control via Web Sever"},"password":{"type":"string","description":"The password set for Remote Control via Web Sever"}},"required":["url","username","password"],"title":"KodiData"},"WebScrobblerSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/WebScrobblerData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"type":{"type":"string","enum":["webscrobbler"]}},"required":["type"],"title":"WebScrobblerSourceAIOConfig"},"WebScrobblerData":{"type":"object","properties":{"slug":{"type":["string","null"],"description":"The URL ending that should be used to identify scrobbles for this source\n\nIn WebScrobbler's Webhook you must set an 'API URL'. All MS WebScrobbler sources must start like:\n\nhttp://localhost:9078/api/webscrobbler\n\nIf you are using multiple WebScrobbler sources (scrobbles for many users) you must use a slug to match Sources with each users extension.\n\nExample:\n\n* slug: 'usera' => API URL: http://localhost:9078/api/webscrobbler/usera\n* slug: 'userb' => API URL: http://localhost:9078/api/webscrobbler/userb\n\nIf no slug is found from an extension's incoming webhook event the first WebScrobbler source without a slug will be used"},"blacklist":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Block scrobbling from specific WebScrobbler Connectors","examples":[["youtube"]]},"whitelist":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Only allow scrobbling from specific WebScrobbler Connectors","examples":[["mixcloud","soundcloud","bandcamp"]]}},"title":"WebScrobblerData"},"ChromecastSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/ChromecastData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"type":{"type":"string","enum":["chromecast"]}},"required":["data","type"],"title":"ChromecastSourceAIOConfig"},"ChromecastData":{"type":"object","properties":{"blacklistDevices":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"DO NOT scrobble from any cast devices that START WITH these values, case-insensitive\n\nUseful when used with auto discovery","examples":[["home-mini","family-tv"]]},"whitelistDevices":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"ONLY scrobble from any cast device that START WITH these values, case-insensitive\n\nIf whitelist is present then blacklist is ignored\n\nUseful when used with auto discovery","examples":[["home-mini","family-tv"]]},"blacklistApps":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"DO NOT scrobble from any application that START WITH these values, case-insensitive","examples":[["spotify","pandora"]]},"whitelistApps":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"ONLY scrobble from any application that START WITH these values, case-insensitive\n\nIf whitelist is present then blacklist is ignored","examples":[["spotify","pandora"]]},"useAvahi":{"type":"boolean","description":"Try to use Avahi and avahi-browse to resolve mDNS devices instead of native mDNS querying\n\nUseful for docker (alpine) container where mDNS resolution is not yet supported. Avahi socket must be exposed to the container and avahi-tools must be installed.","default":false},"useAutoDiscovery":{"type":"boolean","description":"Use mDNS to discovery Google Cast devices on your next automatically?\n\nIf not explicitly set then it is TRUE if `devices` is not set"},"devices":{"type":"array","items":{"$ref":"#/definitions/ChromecastDeviceInfo"},"description":"A list of Google Cast devices to monitor\n\nIf this is used then `useAutoDiscovery` is set to FALSE, if not explicitly set"},"allowUnknownMedia":{"anyOf":[{"type":"boolean"},{"type":"array","items":{"type":"string"}}],"description":"Chromecast Apps report a \"media type\" in the status info returned for whatever is currently playing\n\n* If set to TRUE then Music AND Generic/Unknown media will be tracked for ALL APPS\n* If set to FALSE then only media explicitly typed as Music will be tracked for ALL APPS\n* If set to a list then only Apps whose name contain one of these values, case-insensitive, will have Music AND Generic/Unknown tracked\n\nSee https://developers.google.com/cast/docs/media/messages#MediaInformation \"metadata\" property","default":false},"forceMediaRecognitionOn":{"type":"array","items":{"type":"string"},"description":"Media provided by any App whose name is listed here will ALWAYS be tracked, regardless of the \"media type\" reported\n\nApps will be recognized if they CONTAIN any of these values, case-insensitive"}},"title":"ChromecastData"},"ChromecastDeviceInfo":{"type":"object","properties":{"name":{"type":"string","description":"A friendly name to identify this device","examples":["MySmartTV"]},"address":{"type":"string","description":"The IP address of the device","examples":["192.168.0.115"]}},"required":["name","address"],"title":"ChromecastDeviceInfo"},"MalojaSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/MalojaSourceData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"configureAs":{"type":"string","enum":["source"],"description":"When used in `maloja.config` this tells multi-scrobbler whether to use this data to configure a source or client.","default":"source","examples":["source"]},"type":{"type":"string","enum":["maloja"]}},"required":["data","type"],"title":"MalojaSourceAIOConfig"},"MalojaSourceData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"url":{"type":"string","description":"URL for maloja server","examples":["http://localhost:42010"]},"apiKey":{"type":"string","description":"API Key for Maloja server","examples":["myApiKey"]}},"required":["apiKey","url"],"title":"MalojaSourceData"},"MusikcubeSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/MusikcubeData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"type":{"type":"string","enum":["musikcube"]}},"required":["data","type"],"title":"MusikcubeSourceAIOConfig"},"MusikcubeData":{"type":"object","properties":{"url":{"type":"string","description":"URL of the Musikcube Websocket (Metadata) server to connect to\n\nYou MUST have enabled 'metadata' server and set a password: https://github.com/clangen/musikcube/wiki/remote-api-documentation\n * musikcube -> settings -> server setup\n\nThe URL you provide here will have all parts not explicitly defined filled in for you so if these are not the default you must define them.\n\nParts => [default value]\n\n* Protocol => `ws://`\n* Hostname => `localhost`\n* Port => `7905`","examples":["ws://localhost:7905"],"default":"ws://localhost:7905"},"password":{"type":"string","description":"Password set in Musikcube https://github.com/clangen/musikcube/wiki/remote-api-documentation\n\n* musikcube -> settings -> server setup -> password"},"device_id":{"type":"string"}},"required":["password"],"title":"MusikcubeData"},"MusicCastSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/MusicCastData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"type":{"type":"string","enum":["musiccast"]}},"required":["data","type"],"title":"MusicCastSourceAIOConfig"},"MusicCastData":{"type":"object","properties":{"url":{"type":"string","description":"The host or URL of the YamahaExtendedControl endpoint to use","examples":[["192.168.0.101","http://192.168.0.101/YamahaExtendedControl"]]}},"required":["url"],"title":"MusicCastData"},"MPDSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/MPDData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/MPDSourceOptions"},"type":{"type":"string","enum":["mpd"]}},"required":["data","options","type"],"title":"MPDSourceAIOConfig"},"MPDData":{"type":"object","properties":{"url":{"type":"string","description":"URL:PORT of the MPD server to connect to\n\nTo use this you must have TCP connections enabled for your MPD server https://mpd.readthedocs.io/en/stable/user.html#client-connections","examples":["localhost:6600"],"default":"localhost:6600"},"path":{"type":"string","description":"If using socket specify the path instead of url.\n\ntrailing `~` is replaced by your home directory"},"password":{"type":"string","description":"Password for the server, if set https://mpd.readthedocs.io/en/stable/user.html#permissions-and-passwords"}},"title":"MPDData"},"MPDSourceOptions":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"MPDSourceOptions"},"VLCSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/VLCData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/VLCSourceOptions"},"type":{"type":"string","enum":["vlc"]}},"required":["data","type"],"title":"VLCSourceAIOConfig"},"VLCData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"url":{"type":"string","description":"URL:PORT of the VLC server to connect to\n\nTo use this you must have the Web (http) interface module enabled and a password set https://foxxmd.github.io/multi-scrobbler/docs/configuration#vlc","examples":["localhost:8080"],"default":"localhost:8080"},"password":{"type":"string","description":"Password for the server"}},"required":["password"],"title":"VLCData"},"VLCSourceOptions":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"},"filenamePatterns":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"A list of regular expressions to use to extract metadata (title, album, artist) from a filename\n\nUsed when VLC reports only the filename for the current audio track"},"logFilenamePatterns":{"type":"boolean","description":"Log to DEBUG when a filename-only track is matched or not matched by filenamePatterns","default":false},"dumpVlcMetadata":{"type":"boolean","description":"Dump all the metadata VLC reports for an audio track to DEBUG.\n\nUse this if reporting an issue with VLC not correctly capturing metadata for a track.","default":false}},"title":"VLCSourceOptions"},"IcecastSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/IcecastData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/IcecastSourceOptions"},"type":{"type":"string","enum":["icecast"]}},"required":["data","type"],"title":"IcecastSourceAIOConfig"},"IcecastData":{"type":"object","properties":{"sources":{"type":"array","items":{"$ref":"#/definitions/IcecastSource"}},"icestatsEndpoint":{"type":"string"},"statsEndpoint":{"type":"string"},"nextsongsEndpoint":{"type":"string"},"sevenhtmlEndpoint":{"type":"string"},"icyMetaInt":{"type":"number"},"url":{"type":"string","description":"The Icecast stream URL"}},"required":["url"],"title":"IcecastData"},"IcecastSource":{"type":"string","enum":["icy","ogg","icestats","stats","sevenhtml","nextsongs"],"title":"IcecastSource"},"IcecastSourceOptions":{"type":"object","properties":{"systemScrobble":{"type":"boolean","description":"For Sources that support manual listening, should MS default to scrobbling when no user interaction has occurred?\n\nIf not specified MS will use a Source's specific behavior, see Source's documentation."},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"IcecastSourceOptions"},"AzuracastSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/AzuracastData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"type":{"type":"string","enum":["azuracast"]}},"required":["data","type"],"title":"AzuracastSourceAIOConfig"},"AzuracastData":{"type":"object","properties":{"url":{"type":"string","description":"Base URL of the Azuracast instance\n\nThis does NOT include the station. If a station is included it will be ignored. Use `station` field to specify station, if necessary","examples":["https://radio.mydomain.tld","http://localhost:80"]},"station":{"type":"string","description":"The specific station to monitor\n\nScrobbling will only occur if any of the monitor conditions are met AND the station is ONLINE.\n\nTo monitor multiple stations create a Source for each station.","examples":["my-station-1"]},"monitorWhenListeners":{"type":["boolean","number"],"description":"Only activate scrobble monitoring if station\n\n* `true` => has any current listeners\n* `number` => has EQUAL TO or MORE THAN X number of listeners"},"monitorWhenLive":{"type":"boolean","description":"Only activate scrobble monitoring if station has a live DJ/Streamer","default":true},"apiKey":{"type":"string","description":"API Key used to access data about private streams\n\nhttps://www.azuracast.com/docs/developers/apis/#api-authentication"}},"required":["url","station"],"title":"AzuracastData"},"KoitoSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/KoitoSourceData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"configureAs":{"type":"string","enum":["source"],"description":"When used in `koito.config` this tells multi-scrobbler whether to use this data to configure a source or client.","default":"source","examples":["source"]},"type":{"type":"string","enum":["koito"]}},"required":["data","type"],"title":"KoitoSourceAIOConfig"},"KoitoSourceData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"url":{"type":"string","description":"URL for the Koito server","examples":["http://192.168.0.100:4110"]},"token":{"type":"string","description":"User token for the user to scrobble for","examples":["pM195xPV98CDpk0QW47FIIOR8AKATAX5DblBF-Jq0t1MbbKL"]},"username":{"type":"string","description":"Username of the user to scrobble for"}},"required":["token","url","username"],"title":"KoitoSourceData"},"TealSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/TealSourceData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/TealSourceOptions"},"configureAs":{"type":"string","enum":["source"],"description":"Should always be `souce` when using Tealfm as a Source","default":"source","examples":["source"]},"type":{"type":"string","enum":["tealfm"]}},"required":["data","type"],"title":"TealSourceAIOConfig"},"TealSourceData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"baseUri":{"type":"string","description":"The base URI of the Multi-Scrobbler to use for ATProto OAuth\n\nOnly include this if you want to use OAuth. The URI must be a non-IP/non-local domain using https: protocol."},"identifier":{"type":"string","description":"Identify the account to login as\n\n* For **App Password** Auth - your email\n* For **Oauth** - your handle minus the @"},"appPassword":{"type":"string","description":"The [App Password](https://atproto.com/specs/xrpc#app-passwords) you created for your account\n\nThis is created under https://bsky.app/settings/app-passwords\n\n**Use this if you are self-hosting Multi-Scrobbler on localhost or accessed like http://IP:PORT**"},"serviceAllow":{"type":"array","items":{"type":"string"}},"serviceDeny":{"type":"array","items":{"type":"string"}}},"required":["identifier"],"title":"TealSourceData"},"TealSourceOptions":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"TealSourceOptions"},"RockskySourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/RockskySourceData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/RockskySourceOptions"},"configureAs":{"type":"string","enum":["source"],"description":"When used in `rocksky.config` this tells multi-scrobbler whether to use this data to configure a source or client.","default":"source","examples":["source"]},"type":{"type":"string","enum":["rocksky"]}},"required":["data","type"],"title":"RockskySourceAIOConfig"},"RockskySourceData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"key":{"type":"string","description":"API Key generated from [API Applications](https://docs.rocksky.app/migrating-from-listenbrainz-to-rocksky-1040189m0) in Rocksky for your account","examples":["6794186bf-1157-4de6-80e5-uvb411f3ea2b"]},"handle":{"type":"string","description":"The **fully-qualified** handle for your ATPRoto/Bluesky account, like:\n\n* alice.bsky.social\n* foxxmd.com\n* mysuer.blacksky.app"}},"required":["handle","key"],"title":"RockskySourceData"},"RockskySourceOptions":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"},"audioScrobblerUrl":{"type":"string","description":"URL for the Rocksky *Listenbrainz* endpoint, if not using the default","examples":["https://audioscrobbler.rocksky.app"],"default":"https://audioscrobbler.rocksky.app"},"apiUrl":{"type":"string","description":"URL for the Rocksky *API* endpoint, if not using the default","examples":["https://api.rocksky.app"],"default":"https://api.rocksky.app"}},"title":"RockskySourceOptions"},"SonosSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/SonosData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/SonosSourceOptions"},"type":{"type":"string","enum":["sonos"]}},"required":["data","type"],"title":"SonosSourceAIOConfig"},"SonosData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"host":{"type":"string","description":"IP address of any connected Sonos speaker or device","examples":["192.168.0.170"]},"devicesAllow":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Only scrobble if device name contains strings from this list (case-insensitive)"},"devicesBlock":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Do not scrobble if device name contains strings from this list (case-insensitive)"},"groupsAllow":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Only scrobble if the name of a group the playing device belongs to contains strings from this list (case-insensitive)"},"groupsBlock":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Do not scrobble if the name of a group the playing device belongs to contains strings from this list (case-insensitive)"}},"required":["host"],"title":"SonosData"},"SonosSourceOptions":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"},"logEmptyPlayer":{"type":"boolean"}},"title":"SonosSourceOptions"}}} \ No newline at end of file diff --git a/src/backend/common/schema/aio.json b/src/backend/common/schema/aio.json index 05258fa9..908cffce 100644 --- a/src/backend/common/schema/aio.json +++ b/src/backend/common/schema/aio.json @@ -1 +1 @@ -{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"sourceDefaults":{"$ref":"#/definitions/SourceDefaults"},"clientDefaults":{"$ref":"#/definitions/ClientDefaults"},"sources":{"type":"array","items":{"$ref":"#/definitions/SourceAIOConfig"}},"clients":{"type":"array","items":{"$ref":"#/definitions/ClientAIOConfig"}},"webhooks":{"type":"array","items":{"$ref":"#/definitions/WebhookConfig"}},"port":{"type":"number","description":"Set the port the multi-scrobbler UI will be served from","default":9078,"examples":[9078]},"baseUrl":{"type":"string","description":"Set the Base URL the application should assume the UI is served from.\n\nThis will affect how default redirect URLs are generated (spotify, lastfm, deezer) and some logging messages.\n\nIt will NOT set the actual interface/IP that the application is listening on.\n\nThis can also be set using the BASE_URL environmental variable.","default":"http://localhost","examples":["http://localhost","http://192.168.0.101","https://ms.myDomain.tld"]},"logging":{"$ref":"#/definitions/LogOptions"},"disableWeb":{"type":"boolean","description":"Disable web server from running/listening on port.\n\nThis will also make any ingress sources (Plex, Jellyfin, Tautulli, etc...) unusable"},"debugMode":{"type":"boolean","description":"Enables ALL relevant logging and debug options for all sources/clients, when none are defined.\n\nThis is a convenience shortcut for enabling all output needed to troubleshoot an issue and does not need to be on for normal operation.\n\nIt can also be enabled with the environmental variable DEBUG_MODE=true","default":false,"examples":[false]},"cache":{"$ref":"#/definitions/CacheConfigOptions"},"transformers":{"type":"array","items":{"$ref":"#/definitions/TransformerCommonConfig"}}},"definitions":{"SourceDefaults":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"SourceDefaults"},"LogLevel":{"type":"string","enum":["silent","fatal","error","warn","info","log","verbose","debug"],"description":"Names of log levels that can be invoked on the logger\n\nFrom lowest to highest:\n\n* `debug`\n* `verbose`\n* `log`\n* `info`\n* `warn`\n* `error`\n* `fatal`\n* `silent` (will never output anything)\n\nWhen used in `LogOptions` specifies the **minimum** level the output should log at.","title":"LogLevel"},"FileLogOptions":{"type":"object","properties":{"timestamp":{"type":"string","enum":["unix","iso","auto"],"description":"For rolling log files\n\nWhen\n* value passed to rolling destination is a string (`path` from LogOptions is a string) and\n* `frequency` is defined\n\nThis determines the format of the datetime inserted into the log file name:\n\n* `unix` - unix epoch timestamp in milliseconds\n* `iso` - Full [ISO8601](https://en.wikipedia.org/wiki/ISO_8601) datetime IE '2024-03-07T20:11:34Z'\n* `auto`\n * When frequency is `daily` only inserts date IE YYYY-MM-DD\n * Otherwise inserts full ISO8601 datetime","default":"auto"},"size":{"type":["number","string"],"description":"The maximum size of a given rolling log file.\n\nCan be combined with frequency. Use k, m and g to express values in KB, MB or GB.\n\nNumerical values will be considered as MB.","default":"10MB"},"frequency":{"anyOf":[{"type":"string","enum":["daily"]},{"type":"string","enum":["hourly"]},{"type":"number"}],"description":"The amount of time a given rolling log file is used. Can be combined with size.\n\nUse `daily` or `hourly` to rotate file every day (or every hour). Existing file within the current day (or hour) will be re-used.\n\nNumerical values will be considered as a number of milliseconds. Using a numerical value will always create a new file upon startup.","default":"daily"},"path":{"anyOf":[{"type":"string"},{"$comment":"() => string"}],"description":"The path and filename to use for log files.\n\nIf using rolling files the filename will be appended with `.N` (a number) BEFORE the extension based on rolling status.\n\nMay also be specified using env LOG_PATH or a function that returns a string.\n\nIf path is relative the absolute path will be derived from `logBaseDir` (in `LoggerAppExtras`) which defaults to CWD","default":"./logs/app.log"},"level":{"anyOf":[{"$ref":"#/definitions/LogLevel"},{"type":"boolean","const":false}],"description":"Specify the minimum log level to output to rotating files. If `false` no log files will be created."}},"title":"FileLogOptions"},"ScrobbleThresholds":{"type":"object","properties":{"duration":{"type":["number","null"],"description":"The number of seconds a track has been listened to before it should be considered scrobbled.\n\nSet to null to disable.","default":240,"examples":[240]},"percent":{"type":["number","null"],"description":"The percentage (as an integer) of a track that should have been seen played before it should be scrobbled. Only used if the Source provides information about how long the track is.\n\nSet to null to disable.\n\nNOTE: This should be used with care when the Source is a \"polling\" type (has an 'interval' property). If the track is short and the interval is too high MS may ignore the track if percentage is high because it had not \"seen\" the track for long enough from first discovery, even if you have been playing the track for longer.","default":50,"examples":[50]}},"title":"ScrobbleThresholds"},"PlayTransformOptions":{"type":"object","properties":{"log":{"anyOf":[{"type":"boolean"},{"type":"string","enum":["all"]}]},"preCompare":{"$ref":"#/definitions/PlayTransformPartsConfig%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%3E"},"compare":{"type":"object","properties":{"candidate":{"$ref":"#/definitions/PlayTransformPartsConfig%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%3E"},"existing":{"$ref":"#/definitions/PlayTransformPartsConfig%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%3E"}}},"postCompare":{"$ref":"#/definitions/PlayTransformPartsConfig%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%3E"}},"title":"PlayTransformOptions"},"PlayTransformPartsConfig<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm)>":{"anyOf":[{"$ref":"#/definitions/PlayTransformPartsArray%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%2CMaybeStageTyped%3E"},{"$ref":"#/definitions/PlayTransformParts%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%2CMaybeStageTyped%3E"}],"description":"Represents the weakly-defined user config. May be an array of parts or one parts object","title":"PlayTransformPartsConfig<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm)>"},"PlayTransformPartsArray<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm),MaybeStageTyped>":{"type":"array","items":{"$ref":"#/definitions/PlayTransformParts%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%2CMaybeStageTyped%3E"},"title":"PlayTransformPartsArray<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm),MaybeStageTyped>"},"PlayTransformParts<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm),MaybeStageTyped>":{"anyOf":[{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"title":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"artists":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"albumArtists":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"album":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"duration":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"meta":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"onSuccess":{"$ref":"#/definitions/FlowControlTerm"},"onFailure":{"$ref":"#/definitions/FlowControlTerm"},"onSkip":{"$ref":"#/definitions/FlowControlTerm"},"failureReturnPartial":{"type":"boolean"},"type":{"$ref":"#/definitions/StageTypeMetadata"},"name":{"type":"string"},"stageHash":{"type":"string"},"score":{"type":"number"}},"required":["type"]},{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"title":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"artists":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"albumArtists":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"album":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"duration":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"meta":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"onSuccess":{"$ref":"#/definitions/FlowControlTerm"},"onFailure":{"$ref":"#/definitions/FlowControlTerm"},"onSkip":{"$ref":"#/definitions/FlowControlTerm"},"failureReturnPartial":{"type":"boolean"},"type":{"$ref":"#/definitions/StageTypeUser"},"name":{"type":"string"},"stageHash":{"type":"string"}},"required":["type"]},{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"title":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"artists":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"albumArtists":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"album":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"duration":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"meta":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"onSuccess":{"$ref":"#/definitions/FlowControlTerm"},"onFailure":{"$ref":"#/definitions/FlowControlTerm"},"onSkip":{"$ref":"#/definitions/FlowControlTerm"},"failureReturnPartial":{"type":"boolean"},"type":{"type":"string","enum":["native"]},"name":{"type":"string"},"stageHash":{"type":"string"}},"required":["type"]},{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"title":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"artists":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"albumArtists":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"album":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"duration":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"meta":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"onSuccess":{"$ref":"#/definitions/FlowControlTerm"},"onFailure":{"$ref":"#/definitions/FlowControlTerm"},"onSkip":{"$ref":"#/definitions/FlowControlTerm"},"failureReturnPartial":{"type":"boolean"},"name":{"type":"string"}}},{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"title":{},"artists":{},"albumArtists":{},"album":{},"duration":{},"meta":{},"onSuccess":{"$ref":"#/definitions/FlowControlTerm"},"onFailure":{"$ref":"#/definitions/FlowControlTerm"},"onSkip":{"$ref":"#/definitions/FlowControlTerm"},"failureReturnPartial":{"type":"boolean"},"type":{"type":"string"},"name":{"type":"string"},"stageHash":{"type":"string"}},"required":["type"]}],"title":"PlayTransformParts<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm),MaybeStageTyped>"},"WhenConditionsConfig":{"$ref":"#/definitions/WhenConditions%3Cstring%3E","title":"WhenConditionsConfig"},"WhenConditions":{"type":"array","items":{"$ref":"#/definitions/WhenParts%3Cstring%3E"},"title":"WhenConditions"},"WhenParts":{"$ref":"#/definitions/PlayTransformPartsAtomic%3Cstring%3E","title":"WhenParts"},"PlayTransformPartsAtomic":{"type":"object","properties":{"title":{"type":"string"},"artists":{"type":"string"},"albumArtists":{"type":"string"},"album":{"type":"string"},"duration":{"type":"string"},"meta":{"type":"string"}},"title":"PlayTransformPartsAtomic"},"Whennable":{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"}},"title":"Whennable"},"FlowControlTerm":{"type":"string","enum":["continue","stop"],"title":"FlowControlTerm"},"StageTypeMetadata":{"type":"string","enum":["spotify","musicbrainz","native"],"title":"StageTypeMetadata"},"SearchAndReplaceTerm":{"anyOf":[{"type":"string"},{"$ref":"#/definitions/ConditionalSearchAndReplaceTerm"}],"title":"SearchAndReplaceTerm"},"ConditionalSearchAndReplaceTerm":{"$ref":"#/definitions/ConditionalSearchAndReplaceRegExp","title":"ConditionalSearchAndReplaceTerm"},"ConditionalSearchAndReplaceRegExp":{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"search":{"anyOf":[{"type":"string"},{"type":"string","format":"regex"}],"description":"The search value to test for\n\nCan be a normal string (converted to a case-sensitive literal) or a valid regular expression as a string, or an actual RegExp object","examples":[["find this string","/some string*/ig"]]},"replace":{"type":"string","description":"The replacement string/value to use when search is found\n\nThis can be a literal string like `'replace with this`, an empty string to remove the search value (`''`), or a special regex value\n\nSee replacement here for more information: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace"},"test":{"$comment":"(obj: SearchAndReplaceRegExp) => boolean","type":"object","properties":{"namedArgs":{"type":"object","properties":{"obj":{"$ref":"#/definitions/SearchAndReplaceRegExp"}},"required":["obj"],"additionalProperties":false}},"description":"An optional function to execute before running this search-and-replace that decides if it should run at all"}},"required":["replace","search"],"title":"ConditionalSearchAndReplaceRegExp"},"SearchAndReplaceRegExp":{"type":"object","properties":{"search":{"anyOf":[{"type":"string"},{"type":"string","format":"regex"}],"description":"The search value to test for\n\nCan be a normal string (converted to a case-sensitive literal) or a valid regular expression as a string, or an actual RegExp object","examples":[["find this string","/some string*/ig"]]},"replace":{"type":"string","description":"The replacement string/value to use when search is found\n\nThis can be a literal string like `'replace with this`, an empty string to remove the search value (`''`), or a special regex value\n\nSee replacement here for more information: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace"},"test":{"$comment":"(obj: SearchAndReplaceRegExp) => boolean","type":"object","properties":{"namedArgs":{"type":"object","properties":{"obj":{"$ref":"#/definitions/SearchAndReplaceRegExp"}},"required":["obj"],"additionalProperties":false}},"description":"An optional function to execute before running this search-and-replace that decides if it should run at all"}},"required":["search","replace"],"title":"SearchAndReplaceRegExp"},"ExternalMetadataTerm":{"anyOf":[{"type":"boolean"},{"not":{}},{"$ref":"#/definitions/Whennable"}],"title":"ExternalMetadataTerm"},"StageTypeUser":{"type":"string","enum":["user"],"title":"StageTypeUser"},"ClientDefaults":{"type":"object","properties":{"refreshEnabled":{"type":"boolean","description":"Try to get fresh scrobble history from client when tracks to be scrobbled are newer than the last scrobble found in client history","default":true,"examples":[true]},"refreshStaleAfter":{"type":"number","description":"Refresh scrobbled plays from upstream service if last refresh was at least X seconds ago\n\n**In most case this setting does NOT need to be changed.** The default value is sufficient for the majority of use-cases. Increasing this setting may increase upstream service load and slow down scrobbles.\n\nThis setting should only be changed in specific scenarios where MS is handling multiple \"relaying\" client-services (IE lfm -> lz -> lfm) and there is the potential for a client to be out of sync after more than a few seconds.","examples":[60],"default":60},"refreshMinInterval":{"type":"number","description":"Minimum time (milliseconds) required to pass before upstream scrobbles can be refreshed.\n\n**In most case this setting does NOT need to be changed.** This will always be equal to or smaller than `refreshStaleAfter`.","default":5000,"examples":[5000]},"refreshInitialCount":{"type":"number","description":"The number of tracks to retrieve on initial refresh (related to scrobbleBacklogCount). If not specified this is the maximum supported by the client in 1 API call."},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"checkExistingScrobbles":{"type":"boolean","description":"Check client for an existing scrobble at the same recorded time as the \"new\" track to be scrobbled. If an existing scrobble is found this track is not track scrobbled.","default":true,"examples":[true]},"verbose":{"type":"object","properties":{"match":{"$ref":"#/definitions/MatchLoggingOptions"}},"description":"Options used for increasing verbosity of logging in MS (used for debugging)"},"deadLetterRetries":{"type":"number","description":"Number of times MS should automatically retry scrobbles in dead letter queue","default":1,"examples":[1]},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"ClientDefaults"},"MatchLoggingOptions":{"type":"object","properties":{"onNoMatch":{"type":"boolean","description":"Log to DEBUG when a new track does NOT match an existing scrobble","default":false,"examples":[false]},"onMatch":{"type":"boolean","description":"Log to DEBUG when a new track DOES match an existing scrobble","default":false,"examples":[false]},"confidenceBreakdown":{"type":"boolean","description":"Include confidence breakdowns in track match logging, if applicable","default":false,"examples":[false]}},"description":"Scrobble matching (between new source track and existing client scrobbles) logging options. Used for debugging.","title":"MatchLoggingOptions"},"SourceAIOConfig":{"anyOf":[{"$ref":"#/definitions/SpotifySourceAIOConfig"},{"$ref":"#/definitions/PlexApiSourceAIOConfig"},{"$ref":"#/definitions/DeezerSourceAIOConfig"},{"$ref":"#/definitions/DeezerInternalAIOConfig"},{"$ref":"#/definitions/ListenbrainzEndpointSourceAIOConfig"},{"$ref":"#/definitions/LastFMEndpointSourceAIOConfig"},{"$ref":"#/definitions/SubsonicSourceAIOConfig"},{"$ref":"#/definitions/JellyApiSourceAIOConfig"},{"$ref":"#/definitions/LastFmSouceAIOConfig"},{"$ref":"#/definitions/LibrefmSouceAIOConfig"},{"$ref":"#/definitions/YTMusicSourceAIOConfig"},{"$ref":"#/definitions/MPRISSourceAIOConfig"},{"$ref":"#/definitions/MopidySourceAIOConfig"},{"$ref":"#/definitions/ListenBrainzSourceAIOConfig"},{"$ref":"#/definitions/JRiverSourceAIOConfig"},{"$ref":"#/definitions/KodiSourceAIOConfig"},{"$ref":"#/definitions/WebScrobblerSourceAIOConfig"},{"$ref":"#/definitions/ChromecastSourceAIOConfig"},{"$ref":"#/definitions/MalojaSourceAIOConfig"},{"$ref":"#/definitions/MusikcubeSourceAIOConfig"},{"$ref":"#/definitions/MusicCastSourceAIOConfig"},{"$ref":"#/definitions/MPDSourceAIOConfig"},{"$ref":"#/definitions/VLCSourceAIOConfig"},{"$ref":"#/definitions/IcecastSourceAIOConfig"},{"$ref":"#/definitions/AzuracastSourceAIOConfig"},{"$ref":"#/definitions/KoitoSourceAIOConfig"},{"$ref":"#/definitions/TealSourceAIOConfig"},{"$ref":"#/definitions/RockskySourceAIOConfig"}],"title":"SourceAIOConfig"},"SpotifySourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/SpotifySourceData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"type":{"type":"string","enum":["spotify"]}},"required":["data","type"],"title":"SpotifySourceAIOConfig"},"SpotifySourceData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)\n\nIt is unlikely you should need to change this unless you scrobble many very short tracks often\n\nReading:\n* https://developer.spotify.com/documentation/web-api/guides/rate-limits/\n* https://medium.com/mendix/limiting-your-amount-of-calls-in-mendix-most-of-the-time-rest-835dde55b10e\n * Rate limit may ~180 req/min\n* https://community.spotify.com/t5/Spotify-for-Developers/Web-API-ratelimit/m-p/5503150/highlight/true#M7930\n * Informally indicated as 20 req/sec? Probably for burstiness","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"clientId":{"type":"string","description":"spotify client id","examples":["787c921a2a2ab42320831aba0c8f2fc2"]},"clientSecret":{"type":"string","description":"spotify client secret","examples":["ec42e09d5ae0ee0f0816ca151008412a"]},"redirectUri":{"type":"string","description":"spotify redirect URI -- required only if not the default shown here. URI must end in \"callback\"","default":"http://localhost:9078/callback","examples":["http://localhost:9078/callback"]}},"required":["clientId","clientSecret"],"title":"SpotifySourceData"},"CommonSourceOptions":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"CommonSourceOptions"},"PlexApiSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/PlexApiData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/PlexApiOptions"},"type":{"type":"string","enum":["plex"]}},"required":["data","type"],"title":"PlexApiSourceAIOConfig"},"PlexApiData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"token":{"type":"string"},"url":{"type":"string","description":"http(s)://HOST:PORT of the Plex server to connect to"},"usersAllow":{"anyOf":[{"type":"string"},{"type":"boolean","enum":[true]},{"type":"array","items":{"type":"string"}}],"description":"Only scrobble for specific users (case-insensitive)\n\nIf `true` MS will scrobble activity from all users"},"usersBlock":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Do not scrobble for these users (case-insensitive)"},"devicesAllow":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Only scrobble if device or application name contains strings from this list (case-insensitive)"},"devicesBlock":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Do not scrobble if device or application name contains strings from this list (case-insensitive)"},"librariesAllow":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Only scrobble if library name contains string from this list (case-insensitive)"},"librariesBlock":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Do not scrobble if library name contains strings from this list (case-insensitive)"}},"required":["url"],"title":"PlexApiData"},"PlexApiOptions":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"},"ignoreInvalidCert":{"type":"boolean","description":"Ignore invalid cert errors when connecting to Plex\n\nUseful for Plex servers using \"Required\" Secure Connections with self-signed certificates\n\nDo not enable unless you know you need this.","default":false}},"title":"PlexApiOptions"},"DeezerSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/DeezerData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"type":{"type":"string","enum":["deezer"]}},"required":["data","type"],"title":"DeezerSourceAIOConfig"},"DeezerData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"clientId":{"type":"string","description":"deezer client id","examples":["a89cba1569901a0671d5a9875fed4be1"]},"clientSecret":{"type":"string","description":"deezer client secret","examples":["ec42e09d5ae0ee0f0816ca151008412a"]},"redirectUri":{"type":"string","description":"deezer redirect URI -- required only if not the default shown here. URI must end in \"callback\"","default":"http://localhost:9078/deezer/callback","examples":["http://localhost:9078/deezer/callback"]}},"required":["clientId","clientSecret"],"title":"DeezerData"},"DeezerInternalAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/DeezerInternalData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/DeezerInternalSourceOptions"},"type":{"type":"string","enum":["deezer"]}},"required":["data","type"],"title":"DeezerInternalAIOConfig"},"DeezerInternalData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"arl":{"type":"string","description":"ARL retrieved from Deezer response header"},"userAgent":{"type":"string","description":"User agent","default":"Mozilla/5.0 (X11; Linux i686; rv:135.0) Gecko/20100101 Firefox/135.0"}},"required":["arl"],"title":"DeezerInternalData"},"DeezerInternalSourceOptions":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"},"fuzzyDiscoveryIgnore":{"anyOf":[{"type":"boolean"},{"type":"string","enum":["aggressive"]}]}},"title":"DeezerInternalSourceOptions"},"ListenbrainzEndpointSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/ListenbrainzEndpointData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"type":{"type":"string","enum":["endpointlz"]}},"required":["type"],"title":"ListenbrainzEndpointSourceAIOConfig"},"ListenbrainzEndpointData":{"type":"object","properties":{"slug":{"type":["string","null"],"description":"The URL ending that should be used to identify scrobbles for this source\n\nIf you are using multiple Listenbrainz endpoint sources (scrobbles for many users) you can use a slug to match Sources with individual users/origins\n\nExample:\n\n* slug: 'usera' => API URL: http://localhost:9078/api/listenbrainz/usera\n* slug: 'originb' => API URL: http://localhost:9078/api/listenbrainz/originb\n\nIf no slug is found from an extension's incoming webhook event the first Listenbrainz source without a slug will be used"},"token":{"type":["string","null"],"description":"If an LZ submission request contains this token in the Authorization Header it will be used to match the submission with this Source\n\nSee: https://listenbrainz.readthedocs.io/en/latest/users/api/index.html#add-the-user-token-to-your-requests"}},"title":"ListenbrainzEndpointData"},"LastFMEndpointSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/LastFMEndpointData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"type":{"type":"string","enum":["endpointlfm"]}},"required":["type"],"title":"LastFMEndpointSourceAIOConfig"},"LastFMEndpointData":{"type":"object","properties":{"slug":{"type":["string","null"],"description":"The URL ending that should be used to identify scrobbles for this source\n\nIf you are using multiple Last.fm endpoint sources (scrobbles for many users) you can use a slug to match Sources with individual users/origins\n\nExample:\n\n* slug: 'usera' => API URL: http://localhost:9078/api/lastfm/usera\n* slug: 'originb' => API URL: http://localhost:9078/api/lastfm/originb\n\nIf no slug is found from an extension's incoming webhook event the first Last.fm source without a slug will be used"}},"title":"LastFMEndpointData"},"SubsonicSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/SubsonicData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"type":{"type":"string","enum":["subsonic"]}},"required":["data","type"],"title":"SubsonicSourceAIOConfig"},"SubsonicData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"url":{"type":"string","description":"URL of the subsonic media server to query","examples":["http://airsonic.local"]},"user":{"type":"string","description":"Username to login to the server with","examples":[["MyUser"]]},"password":{"type":"string","description":"Password for the user to login to the server with","examples":["MyPassword"]},"ignoreTlsErrors":{"type":"boolean","description":"If your subsonic server is using self-signed certs you may need to disable TLS errors in order to get a connection\n\nWARNING: This should be used with caution as your traffic may not be encrypted.","default":false},"legacyAuthentication":{"type":"boolean","description":"Older Subsonic versions, and some badly implemented servers (Nextcloud), use legacy authentication which sends your password in CLEAR TEXT. This is less secure than the newer, recommended hashing authentication method but in some cases it is needed. See \"Authentication\" section here => https://www.subsonic.org/pages/api.jsp\n\nIf this option is not specified it will be turned on if the subsonic server responds with error code 41 \"Token authentication not supported for LDAP users.\" -- See Error Handling section => https://www.subsonic.org/pages/api.jsp","default":false},"usersAllow":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Only scrobble for specific users (case-insensitive)\n\nIf undefined or an empty string/list MS will scrobble activity from all users"}},"required":["url","user","password"],"title":"SubsonicData"},"JellyApiSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/JellyApiData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/JellyApiOptions"},"type":{"type":"string","enum":["jellyfin"]}},"required":["data","options","type"],"title":"JellyApiSourceAIOConfig"},"JellyApiData":{"type":"object","properties":{"url":{"type":"string","description":"HOST:PORT of the Jellyfin server to connect to"},"user":{"type":"string","description":"The username of the user to authenticate for or track scrobbles for"},"password":{"type":"string","description":"Password of the username to authenticate for\n\nRequired if `apiKey` is not provided."},"apiKey":{"type":"string","description":"API Key to authenticate with.\n\nRequired if `password` is not provided."},"usersAllow":{"anyOf":[{"type":"string"},{"type":"boolean","enum":[true]},{"type":"array","items":{"type":"string"}}],"description":"Only scrobble for specific users (case-insensitive)\n\nIf `true` MS will scrobble activity from all users"},"usersBlock":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Do not scrobble for these users (case-insensitive)"},"devicesAllow":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Only scrobble if device or application name contains strings from this list (case-insensitive)"},"devicesBlock":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Do not scrobble if device or application name contains strings from this list (case-insensitive)"},"librariesAllow":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Only scrobble if library name contains string from this list (case-insensitive)"},"librariesBlock":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Do not scrobble if library name contains strings from this list (case-insensitive)"},"additionalAllowedLibraryTypes":{"type":"array","items":{},"description":"Allow MS to scrobble audio media in libraries classified other than 'music'\n\n`librariesAllow` will achieve the same result as this but this is more convenient if you do not want to explicitly list every library name or are only using `librariesBlock`"},"allowUnknown":{"type":"boolean","description":"Force media with a type of \"Unknown\" to be counted as Audio","default":false},"frontendUrlOverride":{"type":"string","description":"HOST:PORT of the Jellyfin server that your browser will be able to access from the frontend (and thus load images and links from)\nIf unspecified it will use the normal server HOST and PORT from the `url`\nNecessary if you are using a reverse proxy or other network configuration that prevents the frontend from accessing the server directly\n\nENV: JELLYFIN_FRONTEND_URL_OVERRIDE"}},"required":["url","user"],"title":"JellyApiData"},"JellyApiOptions":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"JellyApiOptions"},"LastFmSouceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/LastFmSourceData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"configureAs":{"type":"string","enum":["source"],"description":"When used in `lastfm.config` this tells multi-scrobbler whether to use this data to configure a source or client.","default":"source","examples":["source"]},"type":{"type":"string","enum":["lastfm"]}},"required":["data","type"],"title":"LastFmSouceAIOConfig"},"LastFmSourceData":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"apiKey":{"type":"string","description":"API Key generated from Last.fm/Libre.fm account","examples":["787c921a2a2ab42320831aba0c8f2fc2"]},"secret":{"type":"string","description":"Secret generated from Last.fm/Libre.fm account","examples":["ec42e09d5ae0ee0f0816ca151008412a"]},"session":{"type":"string","description":"Optional session id returned from a completed auth flow"},"redirectUri":{"type":"string","description":"Optional URI to use for callback. Specify this if callback should be different than the default. MUST have \"lastfm/callback\" in the URL somewhere.","default":"http://localhost:9078/lastfm/callback","examples":["http://localhost:9078/lastfm/callback"]},"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"}},"required":["apiKey","secret"],"title":"LastFmSourceData"},"LibrefmSouceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/LibrefmData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"configureAs":{"type":"string","enum":["source"],"description":"When used in `librefm.config` this tells multi-scrobbler whether to use this data to configure a source or client.","default":"source","examples":["source"]},"type":{"type":"string","enum":["librefm"]}},"required":["data","type"],"title":"LibrefmSouceAIOConfig"},"LibrefmData":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"apiKey":{"type":"string","description":"Optional Secret for Libre.fm account\n\nThis can be anything, or it will be generated by multi-scrobbler","examples":["anyValue"]},"secret":{"type":"string","description":"Optional Secret for Libre.fm account\n\nThis can be anything, or it will be generated by multi-scrobbler","examples":["anyValue"]},"session":{"type":"string","description":"Optional session id returned from a completed auth flow"},"path":{"type":"string"},"urlBase":{"type":"string","description":"(Optional) The host and path prefix for your Libre.fm instance","default":"https://libre.fm/2.0/"},"redirectUri":{"type":"string","description":"Optional URI to use for callback. Specify this if callback should be different than the default. MUST have \"librefm/callback\" in the URL somewhere.","default":"http://localhost:9078/librefm/callback","examples":["http://localhost:9078/librefm/callback"]}},"title":"LibrefmData"},"YTMusicSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/YTMusicData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"type":"object","properties":{"logAuth":{"type":"boolean","description":"When true MS will log to DEBUG all of the credentials data it receives from YTM"},"logDiff":{"type":"boolean","description":"Always log history diff\n\nBy default MS will log to `WARN` if history diff is inconsistent but does not log if diff is expected (on new tracks found)\nSet this to `true` to ALWAYS log diff on new tracks. Expected diffs will log to `DEBUG` and inconsistent diffs will continue to log to `WARN`","default":false},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}}},"type":{"type":"string","enum":["ytmusic"]}},"required":["type"],"title":"YTMusicSourceAIOConfig"},"YTMusicData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"cookie":{"type":"string","description":"The cookie retrieved from the Request Headers of music.youtube.com after logging in.\n\nSee https://ytmusicapi.readthedocs.io/en/stable/setup/browser.html#copy-authentication-headers for how to retrieve this value.","examples":["VISITOR_INFO1_LIVE=jMp2xA1Xz2_PbVc; __Secure-3PAPISID=3AxsXpy0M/AkISpjek; ..."]},"clientId":{"type":"string","description":"Google Cloud Console project OAuth Client ID\n\nGenerated from a custom OAuth Client, see docs"},"clientSecret":{"type":"string","description":"Google Cloud Console project OAuth Client Secret\n\nGenerated from a custom OAuth Client, see docs"},"redirectUri":{"type":"string","description":"Google Cloud Console project OAuth Client Authorized redirect URI\n\nGenerated from a custom OAuth Client, see docs. multi-scrobbler will generate a default based on BASE_URL.\nOnly specify this if the default does not work for you."},"innertubeOptions":{"$ref":"#/definitions/InnertubeOptions","description":"Additional options for authorization and tailoring YTM client"}},"title":"YTMusicData"},"InnertubeOptions":{"type":"object","properties":{"po_token":{"type":"string","description":"Proof of Origin token\n\nMay be required if YTM starts returning 403"},"visitor_data":{"type":"string","description":"Visitor ID value found in VISITOR_INFO1_LIVE or visitorData cookie\n\nMay be required if YTM starts returning 403"},"account_index":{"type":"number","description":"If account login results in being able to choose multiple account, use a zero-based index to choose which one to monitor","examples":[0,1]},"location":{"type":"string"},"lang":{"type":"string"},"generate_session_locally":{"type":"boolean"},"device_category":{"type":"string"},"client_type":{"type":"string"},"timezone":{"type":"string"}},"title":"InnertubeOptions"},"MPRISSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/MPRISData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"type":{"type":"string","enum":["mpris"]}},"required":["data","type"],"title":"MPRISSourceAIOConfig"},"MPRISData":{"type":"object","properties":{"blacklist":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"DO NOT scrobble from any players that START WITH these values, case-insensitive","examples":[["spotify","vlc"]]},"whitelist":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"ONLY from any players that START WITH these values, case-insensitive\n\nIf whitelist is present then blacklist is ignored","examples":[["spotify","vlc"]]}},"title":"MPRISData"},"MopidySourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/MopidyData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"type":{"type":"string","enum":["mopidy"]}},"required":["data","type"],"title":"MopidySourceAIOConfig"},"MopidyData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"url":{"type":"string","description":"URL of the Mopidy HTTP server to connect to\n\nYou MUST have Mopidy-HTTP extension enabled: https://mopidy.com/ext/http\n\nmulti-scrobbler connects to the WebSocket endpoint that ultimately looks like this => `ws://localhost:6680/mopidy/ws/`\n\nThe URL you provide here will have all parts not explicitly defined filled in for you so if these are not the default you must define them.\n\nParts => [default value]\n\n* Protocol => `ws://`\n* Hostname => `localhost`\n* Port => `6680`\n* Path => `/mopidy/ws/`","examples":["ws://localhost:6680/mopidy/ws/"],"default":"ws://localhost:6680/mopidy/ws/"},"uriBlacklist":{"type":"array","items":{"type":"string"},"description":"Do not scrobble tracks whose URI STARTS WITH any of these strings, case-insensitive\n\nEX: Don't scrobble tracks from soundcloud by adding 'soundcloud' to this list.\n\nList is ignored if uriWhitelist is used."},"uriWhitelist":{"type":"array","items":{"type":"string"},"description":"Only scrobble tracks whose URI STARTS WITH any of these strings, case-insensitive\n\nEX: Only scrobble tracks from soundcloud by adding 'soundcloud' to this list."},"albumBlacklist":{"type":"array","items":{"type":"string"},"description":"Remove album data that matches any case-insensitive string from this list when scrobbling,\n\nFor certain sources (Soundcloud) Mopidy does not have all track info (Album) and will instead use \"Soundcloud\" as the Album name. You can prevent multi-scrobbler from using this bad Album data by adding the fake name to this list. Multi-scrobbler will still scrobble the track, just without the bad data.","examples":[["Soundcloud","Mixcloud"]],"default":["Soundcloud"]}},"title":"MopidyData"},"ListenBrainzSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/ListenBrainzSourceData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"configureAs":{"type":"string","enum":["source"],"description":"When used in `listenbrainz.config` this tells multi-scrobbler whether to use this data to configure a source or client.","default":"source","examples":["source"]},"type":{"type":"string","enum":["listenbrainz"]}},"required":["data","type"],"title":"ListenBrainzSourceAIOConfig"},"ListenBrainzSourceData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"url":{"type":"string","description":"URL for the ListenBrainz server, if not using the default","examples":["https://api.listenbrainz.org/"],"default":"https://api.listenbrainz.org/"},"token":{"type":"string","description":"User token for the user to scrobble for","examples":["6794186bf-1157-4de6-80e5-uvb411f3ea2b"]},"username":{"type":"string","description":"Username of the user to scrobble for"}},"required":["token","username"],"title":"ListenBrainzSourceData"},"JRiverSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/JRiverData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"type":{"type":"string","enum":["jriver"]}},"required":["data","type"],"title":"JRiverSourceAIOConfig"},"JRiverData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"url":{"type":"string","description":"URL of the JRiver HTTP server to connect to\n\nmulti-scrobbler connects to the Web Service Interface endpoint that ultimately looks like this => `http://yourDomain:52199/MCWS/v1/`\n\nThe URL you provide here will have all parts not explicitly defined filled in for you so if these are not the default you must define them.\n\nParts => [default value]\n\n* Protocol => `http://`\n* Hostname => `localhost`\n* Port => `52199`\n* Path => `/MCWS/v1/`","examples":["http://localhost:52199/MCWS/v1/"],"default":"http://localhost:52199/MCWS/v1/"},"username":{"type":"string","description":"If you have enabled authentication, the username you set"},"password":{"type":"string","description":"If you have enabled authentication, the password you set"}},"required":["url"],"title":"JRiverData"},"KodiSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/KodiData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"type":{"type":"string","enum":["kodi"]}},"required":["data","type"],"title":"KodiSourceAIOConfig"},"KodiData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"url":{"type":"string","description":"URL of the Kodi HTTP server to connect to\n\nmulti-scrobbler connects to the Web Service Interface endpoint that ultimately looks like this => `http://yourDomain:8080/jsonrpc`\n\nThe URL you provide here will have all parts not explicitly defined filled in for you so if these are not the default you must define them.\n\nParts => [default value]\n\n* Protocol => `http://`\n* Hostname => `localhost`\n* Port => `8080`\n* Path => `/jsonrpc`","examples":["http://localhost:8080/jsonrpc"],"default":"http://localhost:8080/jsonrpc"},"username":{"type":"string","description":"The username set for Remote Control via Web Sever"},"password":{"type":"string","description":"The password set for Remote Control via Web Sever"}},"required":["url","username","password"],"title":"KodiData"},"WebScrobblerSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/WebScrobblerData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"type":{"type":"string","enum":["webscrobbler"]}},"required":["type"],"title":"WebScrobblerSourceAIOConfig"},"WebScrobblerData":{"type":"object","properties":{"slug":{"type":["string","null"],"description":"The URL ending that should be used to identify scrobbles for this source\n\nIn WebScrobbler's Webhook you must set an 'API URL'. All MS WebScrobbler sources must start like:\n\nhttp://localhost:9078/api/webscrobbler\n\nIf you are using multiple WebScrobbler sources (scrobbles for many users) you must use a slug to match Sources with each users extension.\n\nExample:\n\n* slug: 'usera' => API URL: http://localhost:9078/api/webscrobbler/usera\n* slug: 'userb' => API URL: http://localhost:9078/api/webscrobbler/userb\n\nIf no slug is found from an extension's incoming webhook event the first WebScrobbler source without a slug will be used"},"blacklist":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Block scrobbling from specific WebScrobbler Connectors","examples":[["youtube"]]},"whitelist":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Only allow scrobbling from specific WebScrobbler Connectors","examples":[["mixcloud","soundcloud","bandcamp"]]}},"title":"WebScrobblerData"},"ChromecastSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/ChromecastData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"type":{"type":"string","enum":["chromecast"]}},"required":["data","type"],"title":"ChromecastSourceAIOConfig"},"ChromecastData":{"type":"object","properties":{"blacklistDevices":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"DO NOT scrobble from any cast devices that START WITH these values, case-insensitive\n\nUseful when used with auto discovery","examples":[["home-mini","family-tv"]]},"whitelistDevices":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"ONLY scrobble from any cast device that START WITH these values, case-insensitive\n\nIf whitelist is present then blacklist is ignored\n\nUseful when used with auto discovery","examples":[["home-mini","family-tv"]]},"blacklistApps":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"DO NOT scrobble from any application that START WITH these values, case-insensitive","examples":[["spotify","pandora"]]},"whitelistApps":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"ONLY scrobble from any application that START WITH these values, case-insensitive\n\nIf whitelist is present then blacklist is ignored","examples":[["spotify","pandora"]]},"useAvahi":{"type":"boolean","description":"Try to use Avahi and avahi-browse to resolve mDNS devices instead of native mDNS querying\n\nUseful for docker (alpine) container where mDNS resolution is not yet supported. Avahi socket must be exposed to the container and avahi-tools must be installed.","default":false},"useAutoDiscovery":{"type":"boolean","description":"Use mDNS to discovery Google Cast devices on your next automatically?\n\nIf not explicitly set then it is TRUE if `devices` is not set"},"devices":{"type":"array","items":{"$ref":"#/definitions/ChromecastDeviceInfo"},"description":"A list of Google Cast devices to monitor\n\nIf this is used then `useAutoDiscovery` is set to FALSE, if not explicitly set"},"allowUnknownMedia":{"anyOf":[{"type":"boolean"},{"type":"array","items":{"type":"string"}}],"description":"Chromecast Apps report a \"media type\" in the status info returned for whatever is currently playing\n\n* If set to TRUE then Music AND Generic/Unknown media will be tracked for ALL APPS\n* If set to FALSE then only media explicitly typed as Music will be tracked for ALL APPS\n* If set to a list then only Apps whose name contain one of these values, case-insensitive, will have Music AND Generic/Unknown tracked\n\nSee https://developers.google.com/cast/docs/media/messages#MediaInformation \"metadata\" property","default":false},"forceMediaRecognitionOn":{"type":"array","items":{"type":"string"},"description":"Media provided by any App whose name is listed here will ALWAYS be tracked, regardless of the \"media type\" reported\n\nApps will be recognized if they CONTAIN any of these values, case-insensitive"}},"title":"ChromecastData"},"ChromecastDeviceInfo":{"type":"object","properties":{"name":{"type":"string","description":"A friendly name to identify this device","examples":["MySmartTV"]},"address":{"type":"string","description":"The IP address of the device","examples":["192.168.0.115"]}},"required":["name","address"],"title":"ChromecastDeviceInfo"},"MalojaSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/MalojaSourceData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"configureAs":{"type":"string","enum":["source"],"description":"When used in `maloja.config` this tells multi-scrobbler whether to use this data to configure a source or client.","default":"source","examples":["source"]},"type":{"type":"string","enum":["maloja"]}},"required":["data","type"],"title":"MalojaSourceAIOConfig"},"MalojaSourceData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"url":{"type":"string","description":"URL for maloja server","examples":["http://localhost:42010"]},"apiKey":{"type":"string","description":"API Key for Maloja server","examples":["myApiKey"]}},"required":["apiKey","url"],"title":"MalojaSourceData"},"MusikcubeSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/MusikcubeData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"type":{"type":"string","enum":["musikcube"]}},"required":["data","type"],"title":"MusikcubeSourceAIOConfig"},"MusikcubeData":{"type":"object","properties":{"url":{"type":"string","description":"URL of the Musikcube Websocket (Metadata) server to connect to\n\nYou MUST have enabled 'metadata' server and set a password: https://github.com/clangen/musikcube/wiki/remote-api-documentation\n * musikcube -> settings -> server setup\n\nThe URL you provide here will have all parts not explicitly defined filled in for you so if these are not the default you must define them.\n\nParts => [default value]\n\n* Protocol => `ws://`\n* Hostname => `localhost`\n* Port => `7905`","examples":["ws://localhost:7905"],"default":"ws://localhost:7905"},"password":{"type":"string","description":"Password set in Musikcube https://github.com/clangen/musikcube/wiki/remote-api-documentation\n\n* musikcube -> settings -> server setup -> password"},"device_id":{"type":"string"}},"required":["password"],"title":"MusikcubeData"},"MusicCastSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/MusicCastData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"type":{"type":"string","enum":["musiccast"]}},"required":["data","type"],"title":"MusicCastSourceAIOConfig"},"MusicCastData":{"type":"object","properties":{"url":{"type":"string","description":"The host or URL of the YamahaExtendedControl endpoint to use","examples":[["192.168.0.101","http://192.168.0.101/YamahaExtendedControl"]]}},"required":["url"],"title":"MusicCastData"},"MPDSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/MPDData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/MPDSourceOptions"},"type":{"type":"string","enum":["mpd"]}},"required":["data","options","type"],"title":"MPDSourceAIOConfig"},"MPDData":{"type":"object","properties":{"url":{"type":"string","description":"URL:PORT of the MPD server to connect to\n\nTo use this you must have TCP connections enabled for your MPD server https://mpd.readthedocs.io/en/stable/user.html#client-connections","examples":["localhost:6600"],"default":"localhost:6600"},"path":{"type":"string","description":"If using socket specify the path instead of url.\n\ntrailing `~` is replaced by your home directory"},"password":{"type":"string","description":"Password for the server, if set https://mpd.readthedocs.io/en/stable/user.html#permissions-and-passwords"}},"title":"MPDData"},"MPDSourceOptions":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"MPDSourceOptions"},"VLCSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/VLCData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/VLCSourceOptions"},"type":{"type":"string","enum":["vlc"]}},"required":["data","type"],"title":"VLCSourceAIOConfig"},"VLCData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"url":{"type":"string","description":"URL:PORT of the VLC server to connect to\n\nTo use this you must have the Web (http) interface module enabled and a password set https://foxxmd.github.io/multi-scrobbler/docs/configuration#vlc","examples":["localhost:8080"],"default":"localhost:8080"},"password":{"type":"string","description":"Password for the server"}},"required":["password"],"title":"VLCData"},"VLCSourceOptions":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"},"filenamePatterns":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"A list of regular expressions to use to extract metadata (title, album, artist) from a filename\n\nUsed when VLC reports only the filename for the current audio track"},"logFilenamePatterns":{"type":"boolean","description":"Log to DEBUG when a filename-only track is matched or not matched by filenamePatterns","default":false},"dumpVlcMetadata":{"type":"boolean","description":"Dump all the metadata VLC reports for an audio track to DEBUG.\n\nUse this if reporting an issue with VLC not correctly capturing metadata for a track.","default":false}},"title":"VLCSourceOptions"},"IcecastSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/IcecastData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/IcecastSourceOptions"},"type":{"type":"string","enum":["icecast"]}},"required":["data","type"],"title":"IcecastSourceAIOConfig"},"IcecastData":{"type":"object","properties":{"sources":{"type":"array","items":{"$ref":"#/definitions/IcecastSource"}},"icestatsEndpoint":{"type":"string"},"statsEndpoint":{"type":"string"},"nextsongsEndpoint":{"type":"string"},"sevenhtmlEndpoint":{"type":"string"},"icyMetaInt":{"type":"number"},"url":{"type":"string","description":"The Icecast stream URL"}},"required":["url"],"title":"IcecastData"},"IcecastSource":{"type":"string","enum":["icy","ogg","icestats","stats","sevenhtml","nextsongs"],"title":"IcecastSource"},"IcecastSourceOptions":{"type":"object","properties":{"systemScrobble":{"type":"boolean","description":"For Sources that support manual listening, should MS default to scrobbling when no user interaction has occurred?\n\nIf not specified MS will use a Source's specific behavior, see Source's documentation."},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"IcecastSourceOptions"},"AzuracastSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/AzuracastData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"type":{"type":"string","enum":["azuracast"]}},"required":["data","type"],"title":"AzuracastSourceAIOConfig"},"AzuracastData":{"type":"object","properties":{"url":{"type":"string","description":"Base URL of the Azuracast instance\n\nThis does NOT include the station. If a station is included it will be ignored. Use `station` field to specify station, if necessary","examples":["https://radio.mydomain.tld","http://localhost:80"]},"station":{"type":"string","description":"The specific station to monitor\n\nScrobbling will only occur if any of the monitor conditions are met AND the station is ONLINE.\n\nTo monitor multiple stations create a Source for each station.","examples":["my-station-1"]},"monitorWhenListeners":{"type":["boolean","number"],"description":"Only activate scrobble monitoring if station\n\n* `true` => has any current listeners\n* `number` => has EQUAL TO or MORE THAN X number of listeners"},"monitorWhenLive":{"type":"boolean","description":"Only activate scrobble monitoring if station has a live DJ/Streamer","default":true},"apiKey":{"type":"string","description":"API Key used to access data about private streams\n\nhttps://www.azuracast.com/docs/developers/apis/#api-authentication"}},"required":["url","station"],"title":"AzuracastData"},"KoitoSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/KoitoSourceData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"configureAs":{"type":"string","enum":["source"],"description":"When used in `koito.config` this tells multi-scrobbler whether to use this data to configure a source or client.","default":"source","examples":["source"]},"type":{"type":"string","enum":["koito"]}},"required":["data","type"],"title":"KoitoSourceAIOConfig"},"KoitoSourceData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"url":{"type":"string","description":"URL for the Koito server","examples":["http://192.168.0.100:4110"]},"token":{"type":"string","description":"User token for the user to scrobble for","examples":["pM195xPV98CDpk0QW47FIIOR8AKATAX5DblBF-Jq0t1MbbKL"]},"username":{"type":"string","description":"Username of the user to scrobble for"}},"required":["token","url","username"],"title":"KoitoSourceData"},"TealSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/TealSourceData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/TealSourceOptions"},"configureAs":{"type":"string","enum":["source"],"description":"Should always be `souce` when using Tealfm as a Source","default":"source","examples":["source"]},"type":{"type":"string","enum":["tealfm"]}},"required":["data","type"],"title":"TealSourceAIOConfig"},"TealSourceData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"baseUri":{"type":"string","description":"The base URI of the Multi-Scrobbler to use for ATProto OAuth\n\nOnly include this if you want to use OAuth. The URI must be a non-IP/non-local domain using https: protocol."},"identifier":{"type":"string","description":"Identify the account to login as\n\n* For **App Password** Auth - your email\n* For **Oauth** - your handle minus the @"},"appPassword":{"type":"string","description":"The [App Password](https://atproto.com/specs/xrpc#app-passwords) you created for your account\n\nThis is created under https://bsky.app/settings/app-passwords\n\n**Use this if you are self-hosting Multi-Scrobbler on localhost or accessed like http://IP:PORT**"},"serviceAllow":{"type":"array","items":{"type":"string"}},"serviceDeny":{"type":"array","items":{"type":"string"}}},"required":["identifier"],"title":"TealSourceData"},"TealSourceOptions":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"TealSourceOptions"},"RockskySourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/RockskySourceData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/RockskySourceOptions"},"configureAs":{"type":"string","enum":["source"],"description":"When used in `rocksky.config` this tells multi-scrobbler whether to use this data to configure a source or client.","default":"source","examples":["source"]},"type":{"type":"string","enum":["rocksky"]}},"required":["data","type"],"title":"RockskySourceAIOConfig"},"RockskySourceData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"key":{"type":"string","description":"API Key generated from [API Applications](https://docs.rocksky.app/migrating-from-listenbrainz-to-rocksky-1040189m0) in Rocksky for your account","examples":["6794186bf-1157-4de6-80e5-uvb411f3ea2b"]},"handle":{"type":"string","description":"The **fully-qualified** handle for your ATPRoto/Bluesky account, like:\n\n* alice.bsky.social\n* foxxmd.com\n* mysuer.blacksky.app"}},"required":["handle","key"],"title":"RockskySourceData"},"RockskySourceOptions":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"},"audioScrobblerUrl":{"type":"string","description":"URL for the Rocksky *Listenbrainz* endpoint, if not using the default","examples":["https://audioscrobbler.rocksky.app"],"default":"https://audioscrobbler.rocksky.app"},"apiUrl":{"type":"string","description":"URL for the Rocksky *API* endpoint, if not using the default","examples":["https://api.rocksky.app"],"default":"https://api.rocksky.app"}},"title":"RockskySourceOptions"},"ClientAIOConfig":{"anyOf":[{"$ref":"#/definitions/MalojaClientAIOConfig"},{"$ref":"#/definitions/LastfmClientAIOConfig"},{"$ref":"#/definitions/LibrefmClientAIOConfig"},{"$ref":"#/definitions/ListenBrainzClientAIOConfig"},{"$ref":"#/definitions/KoitoClientAIOConfig"},{"$ref":"#/definitions/TealClientAIOConfig"},{"$ref":"#/definitions/RockSkyClientAIOConfig"}],"title":"ClientAIOConfig"},"MalojaClientAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this client. Used with sources to restrict where scrobbles are sent.","examples":["MyConfig"]},"data":{"$ref":"#/definitions/MalojaClientData","description":"Specific data required to configure this client"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"options":{"$ref":"#/definitions/CommonClientOptions"},"configureAs":{"type":"string","enum":["client","source"],"description":"Should always be `client` when using Maloja as a client","default":"client","examples":["client"]},"type":{"type":"string","enum":["maloja"]}},"required":["data","name","type"],"title":"MalojaClientAIOConfig"},"MalojaClientData":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"url":{"type":"string","description":"URL for maloja server","examples":["http://localhost:42010"]},"apiKey":{"type":"string","description":"API Key for Maloja server","examples":["myApiKey"]}},"required":["apiKey","url"],"title":"MalojaClientData"},"CommonClientOptions":{"type":"object","properties":{"refreshEnabled":{"type":"boolean","description":"Try to get fresh scrobble history from client when tracks to be scrobbled are newer than the last scrobble found in client history","default":true,"examples":[true]},"refreshStaleAfter":{"type":"number","description":"Refresh scrobbled plays from upstream service if last refresh was at least X seconds ago\n\n**In most case this setting does NOT need to be changed.** The default value is sufficient for the majority of use-cases. Increasing this setting may increase upstream service load and slow down scrobbles.\n\nThis setting should only be changed in specific scenarios where MS is handling multiple \"relaying\" client-services (IE lfm -> lz -> lfm) and there is the potential for a client to be out of sync after more than a few seconds.","examples":[60],"default":60},"refreshMinInterval":{"type":"number","description":"Minimum time (milliseconds) required to pass before upstream scrobbles can be refreshed.\n\n**In most case this setting does NOT need to be changed.** This will always be equal to or smaller than `refreshStaleAfter`.","default":5000,"examples":[5000]},"refreshInitialCount":{"type":"number","description":"The number of tracks to retrieve on initial refresh (related to scrobbleBacklogCount). If not specified this is the maximum supported by the client in 1 API call."},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"checkExistingScrobbles":{"type":"boolean","description":"Check client for an existing scrobble at the same recorded time as the \"new\" track to be scrobbled. If an existing scrobble is found this track is not track scrobbled.","default":true,"examples":[true]},"verbose":{"type":"object","properties":{"match":{"$ref":"#/definitions/MatchLoggingOptions"}},"description":"Options used for increasing verbosity of logging in MS (used for debugging)"},"deadLetterRetries":{"type":"number","description":"Number of times MS should automatically retry scrobbles in dead letter queue","default":1,"examples":[1]},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"CommonClientOptions"},"LastfmClientAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this client. Used with sources to restrict where scrobbles are sent.","examples":["MyConfig"]},"data":{"$ref":"#/definitions/LastfmData","description":"Specific data required to configure this client"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"options":{"$ref":"#/definitions/LastfmClientOptions"},"configureAs":{"type":"string","enum":["client","source"],"description":"Should always be `client` when using LastFM as a client","default":"client","examples":["client"]},"type":{"type":"string","enum":["lastfm"]}},"required":["data","name","type"],"title":"LastfmClientAIOConfig"},"LastfmData":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"apiKey":{"type":"string","description":"API Key generated from Last.fm/Libre.fm account","examples":["787c921a2a2ab42320831aba0c8f2fc2"]},"secret":{"type":"string","description":"Secret generated from Last.fm/Libre.fm account","examples":["ec42e09d5ae0ee0f0816ca151008412a"]},"session":{"type":"string","description":"Optional session id returned from a completed auth flow"},"redirectUri":{"type":"string","description":"Optional URI to use for callback. Specify this if callback should be different than the default. MUST have \"lastfm/callback\" in the URL somewhere.","default":"http://localhost:9078/lastfm/callback","examples":["http://localhost:9078/lastfm/callback"]}},"required":["apiKey","secret"],"title":"LastfmData"},"LastfmClientOptions":{"type":"object","properties":{"nowPlaying":{"anyOf":[{"type":"boolean"},{"type":"array","items":{"type":"string"}}],"description":"Configure if this Client should report Now Playing from Sources that can scrobble to it\n\n* `true` (default) => Report Now Playing from any eligible Source. \n * If multiple Sources are Playing then reported Play is based on alphabetical order of Source names\n* `false` => Do not report Now Playing\n* `string` list => list of Source `names` that should be allowed to report Now Playing. Order of list determine priority of Play to Report.","default":true},"refreshEnabled":{"type":"boolean","description":"Try to get fresh scrobble history from client when tracks to be scrobbled are newer than the last scrobble found in client history","default":true,"examples":[true]},"refreshStaleAfter":{"type":"number","description":"Refresh scrobbled plays from upstream service if last refresh was at least X seconds ago\n\n**In most case this setting does NOT need to be changed.** The default value is sufficient for the majority of use-cases. Increasing this setting may increase upstream service load and slow down scrobbles.\n\nThis setting should only be changed in specific scenarios where MS is handling multiple \"relaying\" client-services (IE lfm -> lz -> lfm) and there is the potential for a client to be out of sync after more than a few seconds.","examples":[60],"default":60},"refreshMinInterval":{"type":"number","description":"Minimum time (milliseconds) required to pass before upstream scrobbles can be refreshed.\n\n**In most case this setting does NOT need to be changed.** This will always be equal to or smaller than `refreshStaleAfter`.","default":5000,"examples":[5000]},"refreshInitialCount":{"type":"number","description":"The number of tracks to retrieve on initial refresh (related to scrobbleBacklogCount). If not specified this is the maximum supported by the client in 1 API call."},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"checkExistingScrobbles":{"type":"boolean","description":"Check client for an existing scrobble at the same recorded time as the \"new\" track to be scrobbled. If an existing scrobble is found this track is not track scrobbled.","default":true,"examples":[true]},"verbose":{"type":"object","properties":{"match":{"$ref":"#/definitions/MatchLoggingOptions"}},"description":"Options used for increasing verbosity of logging in MS (used for debugging)"},"deadLetterRetries":{"type":"number","description":"Number of times MS should automatically retry scrobbles in dead letter queue","default":1,"examples":[1]},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"LastfmClientOptions"},"LibrefmClientAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this client. Used with sources to restrict where scrobbles are sent.","examples":["MyConfig"]},"data":{"$ref":"#/definitions/LibrefmData","description":"Specific data required to configure this client"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"options":{"$ref":"#/definitions/LibrefmClientOptions"},"configureAs":{"type":"string","enum":["client","source"],"description":"Should always be `client` when using Librefm as a client","default":"client","examples":["client"]},"type":{"type":"string","enum":["librefm"]}},"required":["data","name","type"],"title":"LibrefmClientAIOConfig"},"LibrefmClientOptions":{"type":"object","properties":{"nowPlaying":{"anyOf":[{"type":"boolean"},{"type":"array","items":{"type":"string"}}],"description":"Configure if this Client should report Now Playing from Sources that can scrobble to it\n\n* `true` (default) => Report Now Playing from any eligible Source. \n * If multiple Sources are Playing then reported Play is based on alphabetical order of Source names\n* `false` => Do not report Now Playing\n* `string` list => list of Source `names` that should be allowed to report Now Playing. Order of list determine priority of Play to Report.","default":true},"refreshEnabled":{"type":"boolean","description":"Try to get fresh scrobble history from client when tracks to be scrobbled are newer than the last scrobble found in client history","default":true,"examples":[true]},"refreshStaleAfter":{"type":"number","description":"Refresh scrobbled plays from upstream service if last refresh was at least X seconds ago\n\n**In most case this setting does NOT need to be changed.** The default value is sufficient for the majority of use-cases. Increasing this setting may increase upstream service load and slow down scrobbles.\n\nThis setting should only be changed in specific scenarios where MS is handling multiple \"relaying\" client-services (IE lfm -> lz -> lfm) and there is the potential for a client to be out of sync after more than a few seconds.","examples":[60],"default":60},"refreshMinInterval":{"type":"number","description":"Minimum time (milliseconds) required to pass before upstream scrobbles can be refreshed.\n\n**In most case this setting does NOT need to be changed.** This will always be equal to or smaller than `refreshStaleAfter`.","default":5000,"examples":[5000]},"refreshInitialCount":{"type":"number","description":"The number of tracks to retrieve on initial refresh (related to scrobbleBacklogCount). If not specified this is the maximum supported by the client in 1 API call."},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"checkExistingScrobbles":{"type":"boolean","description":"Check client for an existing scrobble at the same recorded time as the \"new\" track to be scrobbled. If an existing scrobble is found this track is not track scrobbled.","default":true,"examples":[true]},"verbose":{"type":"object","properties":{"match":{"$ref":"#/definitions/MatchLoggingOptions"}},"description":"Options used for increasing verbosity of logging in MS (used for debugging)"},"deadLetterRetries":{"type":"number","description":"Number of times MS should automatically retry scrobbles in dead letter queue","default":1,"examples":[1]},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"LibrefmClientOptions"},"ListenBrainzClientAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this client. Used with sources to restrict where scrobbles are sent.","examples":["MyConfig"]},"data":{"$ref":"#/definitions/ListenBrainzClientData","description":"Specific data required to configure this client"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"options":{"$ref":"#/definitions/CommonClientOptions"},"configureAs":{"type":"string","enum":["client","source"],"description":"Should always be `client` when using Listenbrainz as a client","default":"client","examples":["client"]},"type":{"type":"string","enum":["listenbrainz"]}},"required":["data","name","type"],"title":"ListenBrainzClientAIOConfig"},"ListenBrainzClientData":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"url":{"type":"string","description":"URL for the ListenBrainz server, if not using the default","examples":["https://api.listenbrainz.org/"],"default":"https://api.listenbrainz.org/"},"token":{"type":"string","description":"User token for the user to scrobble for","examples":["6794186bf-1157-4de6-80e5-uvb411f3ea2b"]},"username":{"type":"string","description":"Username of the user to scrobble for"}},"required":["token","username"],"title":"ListenBrainzClientData"},"KoitoClientAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this client. Used with sources to restrict where scrobbles are sent.","examples":["MyConfig"]},"data":{"$ref":"#/definitions/KoitoClientData","description":"Specific data required to configure this client"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"options":{"$ref":"#/definitions/CommonClientOptions"},"configureAs":{"type":"string","enum":["client","source"],"description":"Should always be `client` when using Koito as a client","default":"client","examples":["client"]},"type":{"type":"string","enum":["koito"]}},"required":["data","name","type"],"title":"KoitoClientAIOConfig"},"KoitoClientData":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"url":{"type":"string","description":"URL for the Koito server","examples":["http://192.168.0.100:4110"]},"token":{"type":"string","description":"User token for the user to scrobble for","examples":["pM195xPV98CDpk0QW47FIIOR8AKATAX5DblBF-Jq0t1MbbKL"]},"username":{"type":"string","description":"Username of the user to scrobble for"}},"required":["token","url","username"],"title":"KoitoClientData"},"TealClientAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this client. Used with sources to restrict where scrobbles are sent.","examples":["MyConfig"]},"data":{"$ref":"#/definitions/TealClientData","description":"Specific data required to configure this client"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"options":{"$ref":"#/definitions/TealClientOptions"},"configureAs":{"type":"string","enum":["client","source"],"description":"Should always be `client` when using Tealfm as a client","default":"client","examples":["client"]},"type":{"type":"string","enum":["tealfm"]}},"required":["data","name","type"],"title":"TealClientAIOConfig"},"TealClientData":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"baseUri":{"type":"string","description":"The base URI of the Multi-Scrobbler to use for ATProto OAuth\n\nOnly include this if you want to use OAuth. The URI must be a non-IP/non-local domain using https: protocol."},"identifier":{"type":"string","description":"Identify the account to login as\n\n* For **App Password** Auth - your email\n* For **Oauth** - your handle minus the @"},"appPassword":{"type":"string","description":"The [App Password](https://atproto.com/specs/xrpc#app-passwords) you created for your account\n\nThis is created under https://bsky.app/settings/app-passwords\n\n**Use this if you are self-hosting Multi-Scrobbler on localhost or accessed like http://IP:PORT**"}},"required":["identifier"],"title":"TealClientData"},"TealClientOptions":{"type":"object","properties":{"refreshEnabled":{"type":"boolean","description":"Try to get fresh scrobble history from client when tracks to be scrobbled are newer than the last scrobble found in client history","default":true,"examples":[true]},"refreshStaleAfter":{"type":"number","description":"Refresh scrobbled plays from upstream service if last refresh was at least X seconds ago\n\n**In most case this setting does NOT need to be changed.** The default value is sufficient for the majority of use-cases. Increasing this setting may increase upstream service load and slow down scrobbles.\n\nThis setting should only be changed in specific scenarios where MS is handling multiple \"relaying\" client-services (IE lfm -> lz -> lfm) and there is the potential for a client to be out of sync after more than a few seconds.","examples":[60],"default":60},"refreshMinInterval":{"type":"number","description":"Minimum time (milliseconds) required to pass before upstream scrobbles can be refreshed.\n\n**In most case this setting does NOT need to be changed.** This will always be equal to or smaller than `refreshStaleAfter`.","default":5000,"examples":[5000]},"refreshInitialCount":{"type":"number","description":"The number of tracks to retrieve on initial refresh (related to scrobbleBacklogCount). If not specified this is the maximum supported by the client in 1 API call."},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"checkExistingScrobbles":{"type":"boolean","description":"Check client for an existing scrobble at the same recorded time as the \"new\" track to be scrobbled. If an existing scrobble is found this track is not track scrobbled.","default":true,"examples":[true]},"verbose":{"type":"object","properties":{"match":{"$ref":"#/definitions/MatchLoggingOptions"}},"description":"Options used for increasing verbosity of logging in MS (used for debugging)"},"deadLetterRetries":{"type":"number","description":"Number of times MS should automatically retry scrobbles in dead letter queue","default":1,"examples":[1]},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"TealClientOptions"},"RockSkyClientAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this client. Used with sources to restrict where scrobbles are sent.","examples":["MyConfig"]},"data":{"$ref":"#/definitions/RockSkyClientData","description":"Specific data required to configure this client"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"options":{"$ref":"#/definitions/RockSkyClientOptions"},"configureAs":{"type":"string","enum":["client","source"],"description":"Should always be `client` when using RockSky as a client","default":"client","examples":["client"]},"type":{"type":"string","enum":["rocksky"]}},"required":["data","name","type"],"title":"RockSkyClientAIOConfig"},"RockSkyClientData":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"key":{"type":"string","description":"API Key generated from [API Applications](https://docs.rocksky.app/migrating-from-listenbrainz-to-rocksky-1040189m0) in Rocksky for your account","examples":["6794186bf-1157-4de6-80e5-uvb411f3ea2b"]},"handle":{"type":"string","description":"The **fully-qualified** handle for your ATPRoto/Bluesky account, like:\n\n* alice.bsky.social\n* foxxmd.com\n* mysuer.blacksky.app"}},"required":["handle","key"],"title":"RockSkyClientData"},"RockSkyClientOptions":{"type":"object","properties":{"nowPlaying":{"anyOf":[{"type":"boolean"},{"type":"array","items":{"type":"string"}}],"description":"Configure if this Client should report Now Playing from Sources that can scrobble to it\n\n* `true` (default) => Report Now Playing from any eligible Source. \n * If multiple Sources are Playing then reported Play is based on alphabetical order of Source names\n* `false` => Do not report Now Playing\n* `string` list => list of Source `names` that should be allowed to report Now Playing. Order of list determine priority of Play to Report.","default":true},"refreshEnabled":{"type":"boolean","description":"Try to get fresh scrobble history from client when tracks to be scrobbled are newer than the last scrobble found in client history","default":true,"examples":[true]},"refreshStaleAfter":{"type":"number","description":"Refresh scrobbled plays from upstream service if last refresh was at least X seconds ago\n\n**In most case this setting does NOT need to be changed.** The default value is sufficient for the majority of use-cases. Increasing this setting may increase upstream service load and slow down scrobbles.\n\nThis setting should only be changed in specific scenarios where MS is handling multiple \"relaying\" client-services (IE lfm -> lz -> lfm) and there is the potential for a client to be out of sync after more than a few seconds.","examples":[60],"default":60},"refreshMinInterval":{"type":"number","description":"Minimum time (milliseconds) required to pass before upstream scrobbles can be refreshed.\n\n**In most case this setting does NOT need to be changed.** This will always be equal to or smaller than `refreshStaleAfter`.","default":5000,"examples":[5000]},"refreshInitialCount":{"type":"number","description":"The number of tracks to retrieve on initial refresh (related to scrobbleBacklogCount). If not specified this is the maximum supported by the client in 1 API call."},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"checkExistingScrobbles":{"type":"boolean","description":"Check client for an existing scrobble at the same recorded time as the \"new\" track to be scrobbled. If an existing scrobble is found this track is not track scrobbled.","default":true,"examples":[true]},"verbose":{"type":"object","properties":{"match":{"$ref":"#/definitions/MatchLoggingOptions"}},"description":"Options used for increasing verbosity of logging in MS (used for debugging)"},"deadLetterRetries":{"type":"number","description":"Number of times MS should automatically retry scrobbles in dead letter queue","default":1,"examples":[1]},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"},"audioScrobblerUrl":{"type":"string","description":"URL for the Rocksky *Listenbrainz* endpoint, if not using the default","examples":["https://audioscrobbler.rocksky.app"],"default":"https://audioscrobbler.rocksky.app"},"apiUrl":{"type":"string","description":"URL for the Rocksky *API* endpoint, if not using the default","examples":["https://api.rocksky.app"],"default":"https://api.rocksky.app"}},"title":"RockSkyClientOptions"},"WebhookConfig":{"anyOf":[{"$ref":"#/definitions/GotifyConfig"},{"$ref":"#/definitions/NtfyConfig"},{"$ref":"#/definitions/AppriseConfig"}],"title":"WebhookConfig"},"GotifyConfig":{"type":"object","properties":{"type":{"type":"string","enum":["gotify","ntfy","apprise"],"description":"Webhook type. Valid values are:\n\n* gotify\n* ntfy","examples":["gotify"]},"name":{"type":"string","description":"A friendly name used to identify webhook config in logs"},"url":{"type":"string","description":"The URL of the Gotify server. Same URL that would be used to reach the Gotify UI","examples":["http://192.168.0.100:8078"]},"token":{"type":"string","description":"The token created for this Application in Gotify","examples":["AQZI58fA.rfSZbm"]},"priorities":{"$ref":"#/definitions/PrioritiesConfig","description":"Priority of messages\n\n* Info -> 5\n* Warn -> 7\n* Error -> 10"}},"required":["token","type","url"],"title":"GotifyConfig"},"PrioritiesConfig":{"type":"object","properties":{"info":{"type":"number","examples":[5]},"warn":{"type":"number","examples":[7]},"error":{"type":"number","examples":[10]}},"required":["info","warn","error"],"title":"PrioritiesConfig"},"NtfyConfig":{"type":"object","properties":{"type":{"type":"string","enum":["gotify","ntfy","apprise"],"description":"Webhook type. Valid values are:\n\n* gotify\n* ntfy","examples":["gotify"]},"name":{"type":"string","description":"A friendly name used to identify webhook config in logs"},"url":{"type":"string","description":"The URL of the Ntfy server","examples":["http://192.168.0.100:8078"]},"topic":{"type":"string","description":"The topic mutli-scrobbler should POST to"},"username":{"type":"string","description":"Required if topic is protected"},"password":{"type":"string","description":"Required if topic is protected"},"token":{"type":"string","description":"Use instead of username/password, required if topic is protected"},"priorities":{"$ref":"#/definitions/PrioritiesConfig","description":"Priority of messages\n\n* Info -> 3\n* Warn -> 4\n* Error -> 5"}},"required":["topic","type","url"],"title":"NtfyConfig"},"AppriseConfig":{"type":"object","properties":{"type":{"type":"string","enum":["gotify","ntfy","apprise"],"description":"Webhook type. Valid values are:\n\n* gotify\n* ntfy","examples":["gotify"]},"name":{"type":"string","description":"A friendly name used to identify webhook config in logs"},"host":{"type":"string","description":"The URL of the apprise-api server","examples":["http://192.168.0.100:8078"]},"urls":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"If using [Stateless Endpoints](https://github.com/caronc/apprise-api?tab=readme-ov-file#stateless-solution) the Apprise config URL(s) to send"},"keys":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"If using [Persistent Store Endpoints](https://github.com/caronc/apprise-api?tab=readme-ov-file#persistent-storage-solution) the Configuration ID(s) to send to\n\nNote: If multiple keys are defined then MS will attempt to POST to each one individually"},"tags":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Optional [tag(s)](https://github.com/caronc/apprise-api?tab=readme-ov-file#tagging) to send in the notification payload"}},"required":["host","type"],"title":"AppriseConfig"},"LogOptions":{"type":"object","properties":{"level":{"$ref":"#/definitions/LogLevel","description":"Specify the minimum log level for all log outputs without their own level specified.\n\nDefaults to env `LOG_LEVEL` or `info` if not specified.","default":"info"},"file":{"anyOf":[{"$ref":"#/definitions/LogLevel"},{"type":"boolean","const":false},{"$ref":"#/definitions/FileLogOptions"}],"description":"Specify the minimum log level to output to rotating files or file output options. If `false` no log files will be created."},"console":{"$ref":"#/definitions/LogLevel","description":"Specify the minimum log level streamed to the console (or docker container)"}},"description":"Configure log levels and file options for an AppLogger.\n\n```ts\nconst infoLogger = loggerApp({\n level: 'info' // console and file will log any levels `info` and above\n});\n\nconst logger = loggerApp({\n console: 'debug', // console will log `debug` and higher\n file: 'warn' // file will log `warn` and higher\n});\n\nconst fileLogger = loggerRollingApp({\n console: 'debug', // console will log `debug` and higher\n file: {\n level: 'warn', // file will log `warn` and higher\n path: '/my/cool/path/output.log', // optionally, output to log file at this path\n frequency: 'hourly', // optionally, rotate hourly\n }\n});\n```","title":"LogOptions"},"CacheConfigOptions":{"type":"object","properties":{"metadata":{"$ref":"#/definitions/CacheMetadataConfig"},"scrobble":{"$ref":"#/definitions/CacheScrobbleConfig"},"auth":{"$ref":"#/definitions/CacheAuthConfig"},"regex":{"type":"number","description":"Number of regex functions to cache (LRU)","default":200}},"title":"CacheConfigOptions"},"CacheMetadataConfig":{"$ref":"#/definitions/CacheConfig%3CCacheMetadataProvider%3E","title":"CacheMetadataConfig"},"CacheConfig":{"type":"object","properties":{"provider":{"$ref":"#/definitions/CacheMetadataProvider"},"connection":{"type":"string"}},"required":["provider"],"title":"CacheConfig"},"CacheMetadataProvider":{"$ref":"#/definitions/CacheProvider","title":"CacheMetadataProvider"},"CacheProvider":{"type":["string","boolean"],"enum":["memory","valkey","file",false],"title":"CacheProvider"},"CacheScrobbleConfig":{"$ref":"#/definitions/CacheConfig%3CCacheScrobbleProvider%3E","title":"CacheScrobbleConfig"},"CacheConfig":{"type":"object","properties":{"provider":{"$ref":"#/definitions/CacheScrobbleProvider"},"connection":{"type":"string"}},"required":["provider"],"title":"CacheConfig"},"CacheScrobbleProvider":{"$ref":"#/definitions/CacheProvider","title":"CacheScrobbleProvider"},"CacheAuthConfig":{"$ref":"#/definitions/CacheConfig%3CCacheAuthProvider%3E","title":"CacheAuthConfig"},"CacheConfig":{"type":"object","properties":{"provider":{"$ref":"#/definitions/CacheAuthProvider"},"connection":{"type":"string"}},"required":["provider"],"title":"CacheConfig"},"CacheAuthProvider":{"$ref":"#/definitions/CacheProvider","title":"CacheAuthProvider"},"TransformerCommonConfig":{"type":"object","properties":{"defaults":{"type":"object"},"data":{"type":"object"},"type":{"type":"string"},"name":{"type":"string"},"options":{"$ref":"#/definitions/TransformOptions"}},"required":["type"],"title":"TransformerCommonConfig"},"TransformOptions":{"type":"object","properties":{"failOnFetch":{"type":"boolean"},"throwOnFailure":{"anyOf":[{"type":"boolean"},{"type":"array","items":{"type":"string","enum":["artists","title","albumArtists","album","duration","meta"]}}]},"ttl":{"type":"string"}},"title":"TransformOptions"}}} \ No newline at end of file +{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"sourceDefaults":{"$ref":"#/definitions/SourceDefaults"},"clientDefaults":{"$ref":"#/definitions/ClientDefaults"},"sources":{"type":"array","items":{"$ref":"#/definitions/SourceAIOConfig"}},"clients":{"type":"array","items":{"$ref":"#/definitions/ClientAIOConfig"}},"webhooks":{"type":"array","items":{"$ref":"#/definitions/WebhookConfig"}},"port":{"type":"number","description":"Set the port the multi-scrobbler UI will be served from","default":9078,"examples":[9078]},"baseUrl":{"type":"string","description":"Set the Base URL the application should assume the UI is served from.\n\nThis will affect how default redirect URLs are generated (spotify, lastfm, deezer) and some logging messages.\n\nIt will NOT set the actual interface/IP that the application is listening on.\n\nThis can also be set using the BASE_URL environmental variable.","default":"http://localhost","examples":["http://localhost","http://192.168.0.101","https://ms.myDomain.tld"]},"logging":{"$ref":"#/definitions/LogOptions"},"disableWeb":{"type":"boolean","description":"Disable web server from running/listening on port.\n\nThis will also make any ingress sources (Plex, Jellyfin, Tautulli, etc...) unusable"},"debugMode":{"type":"boolean","description":"Enables ALL relevant logging and debug options for all sources/clients, when none are defined.\n\nThis is a convenience shortcut for enabling all output needed to troubleshoot an issue and does not need to be on for normal operation.\n\nIt can also be enabled with the environmental variable DEBUG_MODE=true","default":false,"examples":[false]},"cache":{"$ref":"#/definitions/CacheConfigOptions"},"transformers":{"type":"array","items":{"$ref":"#/definitions/TransformerCommonConfig"}}},"definitions":{"SourceDefaults":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"SourceDefaults"},"LogLevel":{"type":"string","enum":["silent","fatal","error","warn","info","log","verbose","debug","trace"],"description":"Names of log levels that can be invoked on the logger\n\nFrom lowest to highest:\n\n* `trace`\n* `debug`\n* `verbose`\n* `log`\n* `info`\n* `warn`\n* `error`\n* `fatal`\n* `silent` (will never output anything)\n\nWhen used in `LogOptions` specifies the **minimum** level the output should log at.","title":"LogLevel"},"FileLogOptions":{"type":"object","properties":{"timestamp":{"type":"string","enum":["unix","iso","auto"],"description":"For rolling log files\n\nWhen\n* value passed to rolling destination is a string (`path` from LogOptions is a string) and\n* `frequency` is defined\n\nThis determines the format of the datetime inserted into the log file name:\n\n* `unix` - unix epoch timestamp in milliseconds\n* `iso` - Full [ISO8601](https://en.wikipedia.org/wiki/ISO_8601) datetime IE '2024-03-07T20:11:34Z'\n* `auto`\n * When frequency is `daily` only inserts date IE YYYY-MM-DD\n * Otherwise inserts full ISO8601 datetime","default":"auto"},"size":{"type":["number","string"],"description":"The maximum size of a given rolling log file.\n\nCan be combined with frequency. Use k, m and g to express values in KB, MB or GB.\n\nNumerical values will be considered as MB.","default":"10MB"},"frequency":{"anyOf":[{"type":"string","enum":["daily"]},{"type":"string","enum":["hourly"]},{"type":"number"}],"description":"The amount of time a given rolling log file is used. Can be combined with size.\n\nUse `daily` or `hourly` to rotate file every day (or every hour). Existing file within the current day (or hour) will be re-used.\n\nNumerical values will be considered as a number of milliseconds. Using a numerical value will always create a new file upon startup.","default":"daily"},"path":{"anyOf":[{"type":"string"},{"$comment":"() => string"}],"description":"The path and filename to use for log files.\n\nIf using rolling files the filename will be appended with `.N` (a number) BEFORE the extension based on rolling status.\n\nMay also be specified using env LOG_PATH or a function that returns a string.\n\nIf path is relative the absolute path will be derived from `logBaseDir` (in `LoggerAppExtras`) which defaults to CWD","default":"./logs/app.log"},"level":{"anyOf":[{"$ref":"#/definitions/LogLevel"},{"type":"boolean","const":false}],"description":"Specify the minimum log level to output to rotating files. If `false` no log files will be created."}},"title":"FileLogOptions"},"ScrobbleThresholds":{"type":"object","properties":{"duration":{"type":["number","null"],"description":"The number of seconds a track has been listened to before it should be considered scrobbled.\n\nSet to null to disable.","default":240,"examples":[240]},"percent":{"type":["number","null"],"description":"The percentage (as an integer) of a track that should have been seen played before it should be scrobbled. Only used if the Source provides information about how long the track is.\n\nSet to null to disable.\n\nNOTE: This should be used with care when the Source is a \"polling\" type (has an 'interval' property). If the track is short and the interval is too high MS may ignore the track if percentage is high because it had not \"seen\" the track for long enough from first discovery, even if you have been playing the track for longer.","default":50,"examples":[50]}},"title":"ScrobbleThresholds"},"PlayTransformOptions":{"type":"object","properties":{"log":{"anyOf":[{"type":"boolean"},{"type":"string","enum":["all"]}]},"preCompare":{"$ref":"#/definitions/PlayTransformPartsConfig%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%3E"},"compare":{"type":"object","properties":{"candidate":{"$ref":"#/definitions/PlayTransformPartsConfig%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%3E"},"existing":{"$ref":"#/definitions/PlayTransformPartsConfig%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%3E"}}},"postCompare":{"$ref":"#/definitions/PlayTransformPartsConfig%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%3E"}},"title":"PlayTransformOptions"},"PlayTransformPartsConfig<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm)>":{"anyOf":[{"$ref":"#/definitions/PlayTransformPartsArray%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%2CMaybeStageTyped%3E"},{"$ref":"#/definitions/PlayTransformParts%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%2CMaybeStageTyped%3E"}],"description":"Represents the weakly-defined user config. May be an array of parts or one parts object","title":"PlayTransformPartsConfig<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm)>"},"PlayTransformPartsArray<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm),MaybeStageTyped>":{"type":"array","items":{"$ref":"#/definitions/PlayTransformParts%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%2CMaybeStageTyped%3E"},"title":"PlayTransformPartsArray<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm),MaybeStageTyped>"},"PlayTransformParts<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm),MaybeStageTyped>":{"anyOf":[{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"title":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"artists":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"albumArtists":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"album":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"duration":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"meta":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"onSuccess":{"$ref":"#/definitions/FlowControlTerm"},"onFailure":{"$ref":"#/definitions/FlowControlTerm"},"onSkip":{"$ref":"#/definitions/FlowControlTerm"},"failureReturnPartial":{"type":"boolean"},"type":{"$ref":"#/definitions/StageTypeMetadata"},"name":{"type":"string"},"stageHash":{"type":"string"},"score":{"type":"number"}},"required":["type"]},{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"title":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"artists":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"albumArtists":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"album":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"duration":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"meta":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"onSuccess":{"$ref":"#/definitions/FlowControlTerm"},"onFailure":{"$ref":"#/definitions/FlowControlTerm"},"onSkip":{"$ref":"#/definitions/FlowControlTerm"},"failureReturnPartial":{"type":"boolean"},"type":{"$ref":"#/definitions/StageTypeUser"},"name":{"type":"string"},"stageHash":{"type":"string"}},"required":["type"]},{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"title":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"artists":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"albumArtists":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"album":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"duration":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"meta":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"onSuccess":{"$ref":"#/definitions/FlowControlTerm"},"onFailure":{"$ref":"#/definitions/FlowControlTerm"},"onSkip":{"$ref":"#/definitions/FlowControlTerm"},"failureReturnPartial":{"type":"boolean"},"type":{"type":"string","enum":["native"]},"name":{"type":"string"},"stageHash":{"type":"string"}},"required":["type"]},{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"title":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"artists":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"albumArtists":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"album":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"duration":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"meta":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"onSuccess":{"$ref":"#/definitions/FlowControlTerm"},"onFailure":{"$ref":"#/definitions/FlowControlTerm"},"onSkip":{"$ref":"#/definitions/FlowControlTerm"},"failureReturnPartial":{"type":"boolean"},"name":{"type":"string"}}},{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"title":{},"artists":{},"albumArtists":{},"album":{},"duration":{},"meta":{},"onSuccess":{"$ref":"#/definitions/FlowControlTerm"},"onFailure":{"$ref":"#/definitions/FlowControlTerm"},"onSkip":{"$ref":"#/definitions/FlowControlTerm"},"failureReturnPartial":{"type":"boolean"},"type":{"type":"string"},"name":{"type":"string"},"stageHash":{"type":"string"}},"required":["type"]}],"title":"PlayTransformParts<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm),MaybeStageTyped>"},"WhenConditionsConfig":{"$ref":"#/definitions/WhenConditions%3Cstring%3E","title":"WhenConditionsConfig"},"WhenConditions":{"type":"array","items":{"$ref":"#/definitions/WhenParts%3Cstring%3E"},"title":"WhenConditions"},"WhenParts":{"$ref":"#/definitions/PlayTransformPartsAtomic%3Cstring%3E","title":"WhenParts"},"PlayTransformPartsAtomic":{"type":"object","properties":{"title":{"type":"string"},"artists":{"type":"string"},"albumArtists":{"type":"string"},"album":{"type":"string"},"duration":{"type":"string"},"meta":{"type":"string"}},"title":"PlayTransformPartsAtomic"},"Whennable":{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"}},"title":"Whennable"},"FlowControlTerm":{"type":"string","enum":["continue","stop"],"title":"FlowControlTerm"},"StageTypeMetadata":{"type":"string","enum":["spotify","musicbrainz","native"],"title":"StageTypeMetadata"},"SearchAndReplaceTerm":{"anyOf":[{"type":"string"},{"$ref":"#/definitions/ConditionalSearchAndReplaceTerm"}],"title":"SearchAndReplaceTerm"},"ConditionalSearchAndReplaceTerm":{"$ref":"#/definitions/ConditionalSearchAndReplaceRegExp","title":"ConditionalSearchAndReplaceTerm"},"ConditionalSearchAndReplaceRegExp":{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"search":{"anyOf":[{"type":"string"},{"type":"string","format":"regex"}],"description":"The search value to test for\n\nCan be a normal string (converted to a case-sensitive literal) or a valid regular expression as a string, or an actual RegExp object","examples":[["find this string","/some string*/ig"]]},"replace":{"type":"string","description":"The replacement string/value to use when search is found\n\nThis can be a literal string like `'replace with this`, an empty string to remove the search value (`''`), or a special regex value\n\nSee replacement here for more information: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace"},"test":{"$comment":"(obj: SearchAndReplaceRegExp) => boolean","type":"object","properties":{"namedArgs":{"type":"object","properties":{"obj":{"$ref":"#/definitions/SearchAndReplaceRegExp"}},"required":["obj"],"additionalProperties":false}},"description":"An optional function to execute before running this search-and-replace that decides if it should run at all"}},"required":["replace","search"],"title":"ConditionalSearchAndReplaceRegExp"},"SearchAndReplaceRegExp":{"type":"object","properties":{"search":{"anyOf":[{"type":"string"},{"type":"string","format":"regex"}],"description":"The search value to test for\n\nCan be a normal string (converted to a case-sensitive literal) or a valid regular expression as a string, or an actual RegExp object","examples":[["find this string","/some string*/ig"]]},"replace":{"type":"string","description":"The replacement string/value to use when search is found\n\nThis can be a literal string like `'replace with this`, an empty string to remove the search value (`''`), or a special regex value\n\nSee replacement here for more information: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace"},"test":{"$comment":"(obj: SearchAndReplaceRegExp) => boolean","type":"object","properties":{"namedArgs":{"type":"object","properties":{"obj":{"$ref":"#/definitions/SearchAndReplaceRegExp"}},"required":["obj"],"additionalProperties":false}},"description":"An optional function to execute before running this search-and-replace that decides if it should run at all"}},"required":["search","replace"],"title":"SearchAndReplaceRegExp"},"ExternalMetadataTerm":{"anyOf":[{"type":"boolean"},{"not":{}},{"$ref":"#/definitions/Whennable"}],"title":"ExternalMetadataTerm"},"StageTypeUser":{"type":"string","enum":["user"],"title":"StageTypeUser"},"ClientDefaults":{"type":"object","properties":{"refreshEnabled":{"type":"boolean","description":"Try to get fresh scrobble history from client when tracks to be scrobbled are newer than the last scrobble found in client history","default":true,"examples":[true]},"refreshStaleAfter":{"type":"number","description":"Refresh scrobbled plays from upstream service if last refresh was at least X seconds ago\n\n**In most case this setting does NOT need to be changed.** The default value is sufficient for the majority of use-cases. Increasing this setting may increase upstream service load and slow down scrobbles.\n\nThis setting should only be changed in specific scenarios where MS is handling multiple \"relaying\" client-services (IE lfm -> lz -> lfm) and there is the potential for a client to be out of sync after more than a few seconds.","examples":[60],"default":60},"refreshMinInterval":{"type":"number","description":"Minimum time (milliseconds) required to pass before upstream scrobbles can be refreshed.\n\n**In most case this setting does NOT need to be changed.** This will always be equal to or smaller than `refreshStaleAfter`.","default":5000,"examples":[5000]},"refreshInitialCount":{"type":"number","description":"The number of tracks to retrieve on initial refresh (related to scrobbleBacklogCount). If not specified this is the maximum supported by the client in 1 API call."},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"checkExistingScrobbles":{"type":"boolean","description":"Check client for an existing scrobble at the same recorded time as the \"new\" track to be scrobbled. If an existing scrobble is found this track is not track scrobbled.","default":true,"examples":[true]},"verbose":{"type":"object","properties":{"match":{"$ref":"#/definitions/MatchLoggingOptions"}},"description":"Options used for increasing verbosity of logging in MS (used for debugging)"},"deadLetterRetries":{"type":"number","description":"Number of times MS should automatically retry scrobbles in dead letter queue","default":1,"examples":[1]},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"ClientDefaults"},"MatchLoggingOptions":{"type":"object","properties":{"onNoMatch":{"type":"boolean","description":"Log to DEBUG when a new track does NOT match an existing scrobble","default":false,"examples":[false]},"onMatch":{"type":"boolean","description":"Log to DEBUG when a new track DOES match an existing scrobble","default":false,"examples":[false]},"confidenceBreakdown":{"type":"boolean","description":"Include confidence breakdowns in track match logging, if applicable","default":false,"examples":[false]}},"description":"Scrobble matching (between new source track and existing client scrobbles) logging options. Used for debugging.","title":"MatchLoggingOptions"},"SourceAIOConfig":{"anyOf":[{"$ref":"#/definitions/SpotifySourceAIOConfig"},{"$ref":"#/definitions/PlexApiSourceAIOConfig"},{"$ref":"#/definitions/DeezerSourceAIOConfig"},{"$ref":"#/definitions/DeezerInternalAIOConfig"},{"$ref":"#/definitions/ListenbrainzEndpointSourceAIOConfig"},{"$ref":"#/definitions/LastFMEndpointSourceAIOConfig"},{"$ref":"#/definitions/SubsonicSourceAIOConfig"},{"$ref":"#/definitions/JellyApiSourceAIOConfig"},{"$ref":"#/definitions/LastFmSouceAIOConfig"},{"$ref":"#/definitions/LibrefmSouceAIOConfig"},{"$ref":"#/definitions/YTMusicSourceAIOConfig"},{"$ref":"#/definitions/MPRISSourceAIOConfig"},{"$ref":"#/definitions/MopidySourceAIOConfig"},{"$ref":"#/definitions/ListenBrainzSourceAIOConfig"},{"$ref":"#/definitions/JRiverSourceAIOConfig"},{"$ref":"#/definitions/KodiSourceAIOConfig"},{"$ref":"#/definitions/WebScrobblerSourceAIOConfig"},{"$ref":"#/definitions/ChromecastSourceAIOConfig"},{"$ref":"#/definitions/MalojaSourceAIOConfig"},{"$ref":"#/definitions/MusikcubeSourceAIOConfig"},{"$ref":"#/definitions/MusicCastSourceAIOConfig"},{"$ref":"#/definitions/MPDSourceAIOConfig"},{"$ref":"#/definitions/VLCSourceAIOConfig"},{"$ref":"#/definitions/IcecastSourceAIOConfig"},{"$ref":"#/definitions/AzuracastSourceAIOConfig"},{"$ref":"#/definitions/KoitoSourceAIOConfig"},{"$ref":"#/definitions/TealSourceAIOConfig"},{"$ref":"#/definitions/RockskySourceAIOConfig"},{"$ref":"#/definitions/SonosSourceAIOConfig"}],"title":"SourceAIOConfig"},"SpotifySourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/SpotifySourceData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"type":{"type":"string","enum":["spotify"]}},"required":["data","type"],"title":"SpotifySourceAIOConfig"},"SpotifySourceData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)\n\nIt is unlikely you should need to change this unless you scrobble many very short tracks often\n\nReading:\n* https://developer.spotify.com/documentation/web-api/guides/rate-limits/\n* https://medium.com/mendix/limiting-your-amount-of-calls-in-mendix-most-of-the-time-rest-835dde55b10e\n * Rate limit may ~180 req/min\n* https://community.spotify.com/t5/Spotify-for-Developers/Web-API-ratelimit/m-p/5503150/highlight/true#M7930\n * Informally indicated as 20 req/sec? Probably for burstiness","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"clientId":{"type":"string","description":"spotify client id","examples":["787c921a2a2ab42320831aba0c8f2fc2"]},"clientSecret":{"type":"string","description":"spotify client secret","examples":["ec42e09d5ae0ee0f0816ca151008412a"]},"redirectUri":{"type":"string","description":"spotify redirect URI -- required only if not the default shown here. URI must end in \"callback\"","default":"http://localhost:9078/callback","examples":["http://localhost:9078/callback"]}},"required":["clientId","clientSecret"],"title":"SpotifySourceData"},"CommonSourceOptions":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"CommonSourceOptions"},"PlexApiSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/PlexApiData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/PlexApiOptions"},"type":{"type":"string","enum":["plex"]}},"required":["data","type"],"title":"PlexApiSourceAIOConfig"},"PlexApiData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"token":{"type":"string"},"url":{"type":"string","description":"http(s)://HOST:PORT of the Plex server to connect to"},"usersAllow":{"anyOf":[{"type":"string"},{"type":"boolean","enum":[true]},{"type":"array","items":{"type":"string"}}],"description":"Only scrobble for specific users (case-insensitive)\n\nIf `true` MS will scrobble activity from all users"},"usersBlock":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Do not scrobble for these users (case-insensitive)"},"devicesAllow":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Only scrobble if device or application name contains strings from this list (case-insensitive)"},"devicesBlock":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Do not scrobble if device or application name contains strings from this list (case-insensitive)"},"librariesAllow":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Only scrobble if library name contains string from this list (case-insensitive)"},"librariesBlock":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Do not scrobble if library name contains strings from this list (case-insensitive)"}},"required":["url"],"title":"PlexApiData"},"PlexApiOptions":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"},"ignoreInvalidCert":{"type":"boolean","description":"Ignore invalid cert errors when connecting to Plex\n\nUseful for Plex servers using \"Required\" Secure Connections with self-signed certificates\n\nDo not enable unless you know you need this.","default":false}},"title":"PlexApiOptions"},"DeezerSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/DeezerData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"type":{"type":"string","enum":["deezer"]}},"required":["data","type"],"title":"DeezerSourceAIOConfig"},"DeezerData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"clientId":{"type":"string","description":"deezer client id","examples":["a89cba1569901a0671d5a9875fed4be1"]},"clientSecret":{"type":"string","description":"deezer client secret","examples":["ec42e09d5ae0ee0f0816ca151008412a"]},"redirectUri":{"type":"string","description":"deezer redirect URI -- required only if not the default shown here. URI must end in \"callback\"","default":"http://localhost:9078/deezer/callback","examples":["http://localhost:9078/deezer/callback"]}},"required":["clientId","clientSecret"],"title":"DeezerData"},"DeezerInternalAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/DeezerInternalData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/DeezerInternalSourceOptions"},"type":{"type":"string","enum":["deezer"]}},"required":["data","type"],"title":"DeezerInternalAIOConfig"},"DeezerInternalData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"arl":{"type":"string","description":"ARL retrieved from Deezer response header"},"userAgent":{"type":"string","description":"User agent","default":"Mozilla/5.0 (X11; Linux i686; rv:135.0) Gecko/20100101 Firefox/135.0"},"accountId":{"type":"string","description":"The ID (USER_ID) of the linked account to monitor. If not set, monitors the main ARL account"}},"required":["arl"],"title":"DeezerInternalData"},"DeezerInternalSourceOptions":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"},"fuzzyDiscoveryIgnore":{"anyOf":[{"type":"boolean"},{"type":"string","enum":["aggressive"]}]}},"title":"DeezerInternalSourceOptions"},"ListenbrainzEndpointSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/ListenbrainzEndpointData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"type":{"type":"string","enum":["endpointlz"]}},"required":["type"],"title":"ListenbrainzEndpointSourceAIOConfig"},"ListenbrainzEndpointData":{"type":"object","properties":{"slug":{"type":["string","null"],"description":"The URL ending that should be used to identify scrobbles for this source\n\nIf you are using multiple Listenbrainz endpoint sources (scrobbles for many users) you can use a slug to match Sources with individual users/origins\n\nExample:\n\n* slug: 'usera' => API URL: http://localhost:9078/api/listenbrainz/usera\n* slug: 'originb' => API URL: http://localhost:9078/api/listenbrainz/originb\n\nIf no slug is found from an extension's incoming webhook event the first Listenbrainz source without a slug will be used"},"token":{"type":["string","null"],"description":"If an LZ submission request contains this token in the Authorization Header it will be used to match the submission with this Source\n\nSee: https://listenbrainz.readthedocs.io/en/latest/users/api/index.html#add-the-user-token-to-your-requests"}},"title":"ListenbrainzEndpointData"},"LastFMEndpointSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/LastFMEndpointData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"type":{"type":"string","enum":["endpointlfm"]}},"required":["type"],"title":"LastFMEndpointSourceAIOConfig"},"LastFMEndpointData":{"type":"object","properties":{"slug":{"type":["string","null"],"description":"The URL ending that should be used to identify scrobbles for this source\n\nIf you are using multiple Last.fm endpoint sources (scrobbles for many users) you can use a slug to match Sources with individual users/origins\n\nExample:\n\n* slug: 'usera' => API URL: http://localhost:9078/api/lastfm/usera\n* slug: 'originb' => API URL: http://localhost:9078/api/lastfm/originb\n\nIf no slug is found from an extension's incoming webhook event the first Last.fm source without a slug will be used"}},"title":"LastFMEndpointData"},"SubsonicSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/SubsonicData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"type":{"type":"string","enum":["subsonic"]}},"required":["data","type"],"title":"SubsonicSourceAIOConfig"},"SubsonicData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"url":{"type":"string","description":"URL of the subsonic media server to query","examples":["http://airsonic.local"]},"user":{"type":"string","description":"Username to login to the server with","examples":[["MyUser"]]},"password":{"type":"string","description":"Password for the user to login to the server with","examples":["MyPassword"]},"ignoreTlsErrors":{"type":"boolean","description":"If your subsonic server is using self-signed certs you may need to disable TLS errors in order to get a connection\n\nWARNING: This should be used with caution as your traffic may not be encrypted.","default":false},"legacyAuthentication":{"type":"boolean","description":"Older Subsonic versions, and some badly implemented servers (Nextcloud), use legacy authentication which sends your password in CLEAR TEXT. This is less secure than the newer, recommended hashing authentication method but in some cases it is needed. See \"Authentication\" section here => https://www.subsonic.org/pages/api.jsp\n\nIf this option is not specified it will be turned on if the subsonic server responds with error code 41 \"Token authentication not supported for LDAP users.\" -- See Error Handling section => https://www.subsonic.org/pages/api.jsp","default":false},"usersAllow":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Only scrobble for specific users (case-insensitive)\n\nIf undefined or an empty string/list MS will scrobble activity from all users"}},"required":["url","user","password"],"title":"SubsonicData"},"JellyApiSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/JellyApiData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/JellyApiOptions"},"type":{"type":"string","enum":["jellyfin"]}},"required":["data","type"],"title":"JellyApiSourceAIOConfig"},"JellyApiData":{"type":"object","properties":{"url":{"type":"string","description":"HOST:PORT of the Jellyfin server to connect to"},"user":{"type":"string","description":"The username of the user to authenticate for or track scrobbles for"},"password":{"type":"string","description":"Password of the username to authenticate for\n\nRequired if `apiKey` is not provided."},"apiKey":{"type":"string","description":"API Key to authenticate with.\n\nRequired if `password` is not provided."},"usersAllow":{"anyOf":[{"type":"string"},{"type":"boolean","enum":[true]},{"type":"array","items":{"type":"string"}}],"description":"Only scrobble for specific users (case-insensitive)\n\nIf `true` MS will scrobble activity from all users"},"usersBlock":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Do not scrobble for these users (case-insensitive)"},"devicesAllow":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Only scrobble if device or application name contains strings from this list (case-insensitive)"},"devicesBlock":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Do not scrobble if device or application name contains strings from this list (case-insensitive)"},"librariesAllow":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Only scrobble if library name contains string from this list (case-insensitive)"},"librariesBlock":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Do not scrobble if library name contains strings from this list (case-insensitive)"},"additionalAllowedLibraryTypes":{"type":"array","items":{},"description":"Allow MS to scrobble audio media in libraries classified other than 'music'\n\n`librariesAllow` will achieve the same result as this but this is more convenient if you do not want to explicitly list every library name or are only using `librariesBlock`"},"allowUnknown":{"type":"boolean","description":"Force media with a type of \"Unknown\" to be counted as Audio","default":false,"deprecated":"use allowMediaTypes instead"},"allowMediaTypes":{"anyOf":[{"type":"array","items":{}},{"type":"string"}],"description":"Allow these media types to be scrobbled.\n\nIf not defined or empty, uses 'Audio' as default. If non-empty then *only* uses these types (make sure you include Audio!)\n\nValues are case-insensitive.\n\nSee https://github.com/jellyfin/jellyfin-sdk-typescript/blob/master/src/generated-client/models/media-type.ts#L22 for possible types"},"frontendUrlOverride":{"type":"string","description":"HOST:PORT of the Jellyfin server that your browser will be able to access from the frontend (and thus load images and links from)\nIf unspecified it will use the normal server HOST and PORT from the `url`\nNecessary if you are using a reverse proxy or other network configuration that prevents the frontend from accessing the server directly\n\nENV: JELLYFIN_FRONTEND_URL_OVERRIDE"}},"required":["url","user"],"title":"JellyApiData"},"JellyApiOptions":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"JellyApiOptions"},"LastFmSouceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/LastFmSourceData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"configureAs":{"type":"string","enum":["source"],"description":"When used in `lastfm.config` this tells multi-scrobbler whether to use this data to configure a source or client.","default":"source","examples":["source"]},"type":{"type":"string","enum":["lastfm"]}},"required":["data","type"],"title":"LastFmSouceAIOConfig"},"LastFmSourceData":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"apiKey":{"type":"string","description":"API Key generated from Last.fm/Libre.fm account","examples":["787c921a2a2ab42320831aba0c8f2fc2"]},"secret":{"type":"string","description":"Secret generated from Last.fm/Libre.fm account","examples":["ec42e09d5ae0ee0f0816ca151008412a"]},"session":{"type":"string","description":"Optional session id returned from a completed auth flow"},"redirectUri":{"type":"string","description":"Optional URI to use for callback. Specify this if callback should be different than the default. MUST have \"lastfm/callback\" in the URL somewhere.","default":"http://localhost:9078/lastfm/callback","examples":["http://localhost:9078/lastfm/callback"]},"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"}},"required":["apiKey","secret"],"title":"LastFmSourceData"},"LibrefmSouceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/LibrefmData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"configureAs":{"type":"string","enum":["source"],"description":"When used in `librefm.config` this tells multi-scrobbler whether to use this data to configure a source or client.","default":"source","examples":["source"]},"type":{"type":"string","enum":["librefm"]}},"required":["data","type"],"title":"LibrefmSouceAIOConfig"},"LibrefmData":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"apiKey":{"type":"string","description":"Optional Secret for Libre.fm account\n\nThis can be anything, or it will be generated by multi-scrobbler","examples":["anyValue"]},"secret":{"type":"string","description":"Optional Secret for Libre.fm account\n\nThis can be anything, or it will be generated by multi-scrobbler","examples":["anyValue"]},"session":{"type":"string","description":"Optional session id returned from a completed auth flow"},"path":{"type":"string"},"urlBase":{"type":"string","description":"(Optional) The host and path prefix for your Libre.fm instance","default":"https://libre.fm/2.0/"},"redirectUri":{"type":"string","description":"Optional URI to use for callback. Specify this if callback should be different than the default. MUST have \"librefm/callback\" in the URL somewhere.","default":"http://localhost:9078/librefm/callback","examples":["http://localhost:9078/librefm/callback"]}},"title":"LibrefmData"},"YTMusicSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/YTMusicData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"type":"object","properties":{"logAuth":{"type":"boolean","description":"When true MS will log to DEBUG all of the credentials data it receives from YTM"},"logDiff":{"type":"boolean","description":"Always log history diff\n\nBy default MS will log to `WARN` if history diff is inconsistent but does not log if diff is expected (on new tracks found)\nSet this to `true` to ALWAYS log diff on new tracks. Expected diffs will log to `DEBUG` and inconsistent diffs will continue to log to `WARN`","default":false},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}}},"type":{"type":"string","enum":["ytmusic"]}},"required":["type"],"title":"YTMusicSourceAIOConfig"},"YTMusicData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"cookie":{"type":"string","description":"The cookie retrieved from the Request Headers of music.youtube.com after logging in.\n\nSee https://ytmusicapi.readthedocs.io/en/stable/setup/browser.html#copy-authentication-headers for how to retrieve this value.","examples":["VISITOR_INFO1_LIVE=jMp2xA1Xz2_PbVc; __Secure-3PAPISID=3AxsXpy0M/AkISpjek; ..."]},"clientId":{"type":"string","description":"Google Cloud Console project OAuth Client ID\n\nGenerated from a custom OAuth Client, see docs"},"clientSecret":{"type":"string","description":"Google Cloud Console project OAuth Client Secret\n\nGenerated from a custom OAuth Client, see docs"},"redirectUri":{"type":"string","description":"Google Cloud Console project OAuth Client Authorized redirect URI\n\nGenerated from a custom OAuth Client, see docs. multi-scrobbler will generate a default based on BASE_URL.\nOnly specify this if the default does not work for you."},"innertubeOptions":{"$ref":"#/definitions/InnertubeOptions","description":"Additional options for authorization and tailoring YTM client"}},"title":"YTMusicData"},"InnertubeOptions":{"type":"object","properties":{"po_token":{"type":"string","description":"Proof of Origin token\n\nMay be required if YTM starts returning 403"},"visitor_data":{"type":"string","description":"Visitor ID value found in VISITOR_INFO1_LIVE or visitorData cookie\n\nMay be required if YTM starts returning 403"},"account_index":{"type":"number","description":"If account login results in being able to choose multiple account, use a zero-based index to choose which one to monitor","examples":[0,1]},"location":{"type":"string"},"lang":{"type":"string"},"generate_session_locally":{"type":"boolean"},"device_category":{"type":"string"},"client_type":{"type":"string"},"timezone":{"type":"string"}},"title":"InnertubeOptions"},"MPRISSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/MPRISData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"type":{"type":"string","enum":["mpris"]}},"required":["data","type"],"title":"MPRISSourceAIOConfig"},"MPRISData":{"type":"object","properties":{"blacklist":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"DO NOT scrobble from any players that START WITH these values, case-insensitive","examples":[["spotify","vlc"]]},"whitelist":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"ONLY from any players that START WITH these values, case-insensitive\n\nIf whitelist is present then blacklist is ignored","examples":[["spotify","vlc"]]}},"title":"MPRISData"},"MopidySourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/MopidyData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"type":{"type":"string","enum":["mopidy"]}},"required":["data","type"],"title":"MopidySourceAIOConfig"},"MopidyData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"url":{"type":"string","description":"URL of the Mopidy HTTP server to connect to\n\nYou MUST have Mopidy-HTTP extension enabled: https://mopidy.com/ext/http\n\nmulti-scrobbler connects to the WebSocket endpoint that ultimately looks like this => `ws://localhost:6680/mopidy/ws/`\n\nThe URL you provide here will have all parts not explicitly defined filled in for you so if these are not the default you must define them.\n\nParts => [default value]\n\n* Protocol => `ws://`\n* Hostname => `localhost`\n* Port => `6680`\n* Path => `/mopidy/ws/`","examples":["ws://localhost:6680/mopidy/ws/"],"default":"ws://localhost:6680/mopidy/ws/"},"uriBlacklist":{"type":"array","items":{"type":"string"},"description":"Do not scrobble tracks whose URI STARTS WITH any of these strings, case-insensitive\n\nEX: Don't scrobble tracks from soundcloud by adding 'soundcloud' to this list.\n\nList is ignored if uriWhitelist is used."},"uriWhitelist":{"type":"array","items":{"type":"string"},"description":"Only scrobble tracks whose URI STARTS WITH any of these strings, case-insensitive\n\nEX: Only scrobble tracks from soundcloud by adding 'soundcloud' to this list."},"albumBlacklist":{"type":"array","items":{"type":"string"},"description":"Remove album data that matches any case-insensitive string from this list when scrobbling,\n\nFor certain sources (Soundcloud) Mopidy does not have all track info (Album) and will instead use \"Soundcloud\" as the Album name. You can prevent multi-scrobbler from using this bad Album data by adding the fake name to this list. Multi-scrobbler will still scrobble the track, just without the bad data.","examples":[["Soundcloud","Mixcloud"]],"default":["Soundcloud"]}},"title":"MopidyData"},"ListenBrainzSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/ListenBrainzSourceData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"configureAs":{"type":"string","enum":["source"],"description":"When used in `listenbrainz.config` this tells multi-scrobbler whether to use this data to configure a source or client.","default":"source","examples":["source"]},"type":{"type":"string","enum":["listenbrainz"]}},"required":["data","type"],"title":"ListenBrainzSourceAIOConfig"},"ListenBrainzSourceData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"url":{"type":"string","description":"URL for the ListenBrainz server, if not using the default","examples":["https://api.listenbrainz.org/"],"default":"https://api.listenbrainz.org/"},"token":{"type":"string","description":"User token for the user to scrobble for","examples":["6794186bf-1157-4de6-80e5-uvb411f3ea2b"]},"username":{"type":"string","description":"Username of the user to scrobble for"}},"required":["token","username"],"title":"ListenBrainzSourceData"},"JRiverSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/JRiverData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"type":{"type":"string","enum":["jriver"]}},"required":["data","type"],"title":"JRiverSourceAIOConfig"},"JRiverData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"url":{"type":"string","description":"URL of the JRiver HTTP server to connect to\n\nmulti-scrobbler connects to the Web Service Interface endpoint that ultimately looks like this => `http://yourDomain:52199/MCWS/v1/`\n\nThe URL you provide here will have all parts not explicitly defined filled in for you so if these are not the default you must define them.\n\nParts => [default value]\n\n* Protocol => `http://`\n* Hostname => `localhost`\n* Port => `52199`\n* Path => `/MCWS/v1/`","examples":["http://localhost:52199/MCWS/v1/"],"default":"http://localhost:52199/MCWS/v1/"},"username":{"type":"string","description":"If you have enabled authentication, the username you set"},"password":{"type":"string","description":"If you have enabled authentication, the password you set"}},"required":["url"],"title":"JRiverData"},"KodiSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/KodiData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"type":{"type":"string","enum":["kodi"]}},"required":["data","type"],"title":"KodiSourceAIOConfig"},"KodiData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"url":{"type":"string","description":"URL of the Kodi HTTP server to connect to\n\nmulti-scrobbler connects to the Web Service Interface endpoint that ultimately looks like this => `http://yourDomain:8080/jsonrpc`\n\nThe URL you provide here will have all parts not explicitly defined filled in for you so if these are not the default you must define them.\n\nParts => [default value]\n\n* Protocol => `http://`\n* Hostname => `localhost`\n* Port => `8080`\n* Path => `/jsonrpc`","examples":["http://localhost:8080/jsonrpc"],"default":"http://localhost:8080/jsonrpc"},"username":{"type":"string","description":"The username set for Remote Control via Web Sever"},"password":{"type":"string","description":"The password set for Remote Control via Web Sever"}},"required":["url","username","password"],"title":"KodiData"},"WebScrobblerSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/WebScrobblerData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"type":{"type":"string","enum":["webscrobbler"]}},"required":["type"],"title":"WebScrobblerSourceAIOConfig"},"WebScrobblerData":{"type":"object","properties":{"slug":{"type":["string","null"],"description":"The URL ending that should be used to identify scrobbles for this source\n\nIn WebScrobbler's Webhook you must set an 'API URL'. All MS WebScrobbler sources must start like:\n\nhttp://localhost:9078/api/webscrobbler\n\nIf you are using multiple WebScrobbler sources (scrobbles for many users) you must use a slug to match Sources with each users extension.\n\nExample:\n\n* slug: 'usera' => API URL: http://localhost:9078/api/webscrobbler/usera\n* slug: 'userb' => API URL: http://localhost:9078/api/webscrobbler/userb\n\nIf no slug is found from an extension's incoming webhook event the first WebScrobbler source without a slug will be used"},"blacklist":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Block scrobbling from specific WebScrobbler Connectors","examples":[["youtube"]]},"whitelist":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Only allow scrobbling from specific WebScrobbler Connectors","examples":[["mixcloud","soundcloud","bandcamp"]]}},"title":"WebScrobblerData"},"ChromecastSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/ChromecastData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"type":{"type":"string","enum":["chromecast"]}},"required":["data","type"],"title":"ChromecastSourceAIOConfig"},"ChromecastData":{"type":"object","properties":{"blacklistDevices":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"DO NOT scrobble from any cast devices that START WITH these values, case-insensitive\n\nUseful when used with auto discovery","examples":[["home-mini","family-tv"]]},"whitelistDevices":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"ONLY scrobble from any cast device that START WITH these values, case-insensitive\n\nIf whitelist is present then blacklist is ignored\n\nUseful when used with auto discovery","examples":[["home-mini","family-tv"]]},"blacklistApps":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"DO NOT scrobble from any application that START WITH these values, case-insensitive","examples":[["spotify","pandora"]]},"whitelistApps":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"ONLY scrobble from any application that START WITH these values, case-insensitive\n\nIf whitelist is present then blacklist is ignored","examples":[["spotify","pandora"]]},"useAvahi":{"type":"boolean","description":"Try to use Avahi and avahi-browse to resolve mDNS devices instead of native mDNS querying\n\nUseful for docker (alpine) container where mDNS resolution is not yet supported. Avahi socket must be exposed to the container and avahi-tools must be installed.","default":false},"useAutoDiscovery":{"type":"boolean","description":"Use mDNS to discovery Google Cast devices on your next automatically?\n\nIf not explicitly set then it is TRUE if `devices` is not set"},"devices":{"type":"array","items":{"$ref":"#/definitions/ChromecastDeviceInfo"},"description":"A list of Google Cast devices to monitor\n\nIf this is used then `useAutoDiscovery` is set to FALSE, if not explicitly set"},"allowUnknownMedia":{"anyOf":[{"type":"boolean"},{"type":"array","items":{"type":"string"}}],"description":"Chromecast Apps report a \"media type\" in the status info returned for whatever is currently playing\n\n* If set to TRUE then Music AND Generic/Unknown media will be tracked for ALL APPS\n* If set to FALSE then only media explicitly typed as Music will be tracked for ALL APPS\n* If set to a list then only Apps whose name contain one of these values, case-insensitive, will have Music AND Generic/Unknown tracked\n\nSee https://developers.google.com/cast/docs/media/messages#MediaInformation \"metadata\" property","default":false},"forceMediaRecognitionOn":{"type":"array","items":{"type":"string"},"description":"Media provided by any App whose name is listed here will ALWAYS be tracked, regardless of the \"media type\" reported\n\nApps will be recognized if they CONTAIN any of these values, case-insensitive"}},"title":"ChromecastData"},"ChromecastDeviceInfo":{"type":"object","properties":{"name":{"type":"string","description":"A friendly name to identify this device","examples":["MySmartTV"]},"address":{"type":"string","description":"The IP address of the device","examples":["192.168.0.115"]}},"required":["name","address"],"title":"ChromecastDeviceInfo"},"MalojaSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/MalojaSourceData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"configureAs":{"type":"string","enum":["source"],"description":"When used in `maloja.config` this tells multi-scrobbler whether to use this data to configure a source or client.","default":"source","examples":["source"]},"type":{"type":"string","enum":["maloja"]}},"required":["data","type"],"title":"MalojaSourceAIOConfig"},"MalojaSourceData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"url":{"type":"string","description":"URL for maloja server","examples":["http://localhost:42010"]},"apiKey":{"type":"string","description":"API Key for Maloja server","examples":["myApiKey"]}},"required":["apiKey","url"],"title":"MalojaSourceData"},"MusikcubeSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/MusikcubeData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"type":{"type":"string","enum":["musikcube"]}},"required":["data","type"],"title":"MusikcubeSourceAIOConfig"},"MusikcubeData":{"type":"object","properties":{"url":{"type":"string","description":"URL of the Musikcube Websocket (Metadata) server to connect to\n\nYou MUST have enabled 'metadata' server and set a password: https://github.com/clangen/musikcube/wiki/remote-api-documentation\n * musikcube -> settings -> server setup\n\nThe URL you provide here will have all parts not explicitly defined filled in for you so if these are not the default you must define them.\n\nParts => [default value]\n\n* Protocol => `ws://`\n* Hostname => `localhost`\n* Port => `7905`","examples":["ws://localhost:7905"],"default":"ws://localhost:7905"},"password":{"type":"string","description":"Password set in Musikcube https://github.com/clangen/musikcube/wiki/remote-api-documentation\n\n* musikcube -> settings -> server setup -> password"},"device_id":{"type":"string"}},"required":["password"],"title":"MusikcubeData"},"MusicCastSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/MusicCastData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"type":{"type":"string","enum":["musiccast"]}},"required":["data","type"],"title":"MusicCastSourceAIOConfig"},"MusicCastData":{"type":"object","properties":{"url":{"type":"string","description":"The host or URL of the YamahaExtendedControl endpoint to use","examples":[["192.168.0.101","http://192.168.0.101/YamahaExtendedControl"]]}},"required":["url"],"title":"MusicCastData"},"MPDSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/MPDData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/MPDSourceOptions"},"type":{"type":"string","enum":["mpd"]}},"required":["data","options","type"],"title":"MPDSourceAIOConfig"},"MPDData":{"type":"object","properties":{"url":{"type":"string","description":"URL:PORT of the MPD server to connect to\n\nTo use this you must have TCP connections enabled for your MPD server https://mpd.readthedocs.io/en/stable/user.html#client-connections","examples":["localhost:6600"],"default":"localhost:6600"},"path":{"type":"string","description":"If using socket specify the path instead of url.\n\ntrailing `~` is replaced by your home directory"},"password":{"type":"string","description":"Password for the server, if set https://mpd.readthedocs.io/en/stable/user.html#permissions-and-passwords"}},"title":"MPDData"},"MPDSourceOptions":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"MPDSourceOptions"},"VLCSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/VLCData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/VLCSourceOptions"},"type":{"type":"string","enum":["vlc"]}},"required":["data","type"],"title":"VLCSourceAIOConfig"},"VLCData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"url":{"type":"string","description":"URL:PORT of the VLC server to connect to\n\nTo use this you must have the Web (http) interface module enabled and a password set https://foxxmd.github.io/multi-scrobbler/docs/configuration#vlc","examples":["localhost:8080"],"default":"localhost:8080"},"password":{"type":"string","description":"Password for the server"}},"required":["password"],"title":"VLCData"},"VLCSourceOptions":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"},"filenamePatterns":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"A list of regular expressions to use to extract metadata (title, album, artist) from a filename\n\nUsed when VLC reports only the filename for the current audio track"},"logFilenamePatterns":{"type":"boolean","description":"Log to DEBUG when a filename-only track is matched or not matched by filenamePatterns","default":false},"dumpVlcMetadata":{"type":"boolean","description":"Dump all the metadata VLC reports for an audio track to DEBUG.\n\nUse this if reporting an issue with VLC not correctly capturing metadata for a track.","default":false}},"title":"VLCSourceOptions"},"IcecastSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/IcecastData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/IcecastSourceOptions"},"type":{"type":"string","enum":["icecast"]}},"required":["data","type"],"title":"IcecastSourceAIOConfig"},"IcecastData":{"type":"object","properties":{"sources":{"type":"array","items":{"$ref":"#/definitions/IcecastSource"}},"icestatsEndpoint":{"type":"string"},"statsEndpoint":{"type":"string"},"nextsongsEndpoint":{"type":"string"},"sevenhtmlEndpoint":{"type":"string"},"icyMetaInt":{"type":"number"},"url":{"type":"string","description":"The Icecast stream URL"}},"required":["url"],"title":"IcecastData"},"IcecastSource":{"type":"string","enum":["icy","ogg","icestats","stats","sevenhtml","nextsongs"],"title":"IcecastSource"},"IcecastSourceOptions":{"type":"object","properties":{"systemScrobble":{"type":"boolean","description":"For Sources that support manual listening, should MS default to scrobbling when no user interaction has occurred?\n\nIf not specified MS will use a Source's specific behavior, see Source's documentation."},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"IcecastSourceOptions"},"AzuracastSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/AzuracastData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"type":{"type":"string","enum":["azuracast"]}},"required":["data","type"],"title":"AzuracastSourceAIOConfig"},"AzuracastData":{"type":"object","properties":{"url":{"type":"string","description":"Base URL of the Azuracast instance\n\nThis does NOT include the station. If a station is included it will be ignored. Use `station` field to specify station, if necessary","examples":["https://radio.mydomain.tld","http://localhost:80"]},"station":{"type":"string","description":"The specific station to monitor\n\nScrobbling will only occur if any of the monitor conditions are met AND the station is ONLINE.\n\nTo monitor multiple stations create a Source for each station.","examples":["my-station-1"]},"monitorWhenListeners":{"type":["boolean","number"],"description":"Only activate scrobble monitoring if station\n\n* `true` => has any current listeners\n* `number` => has EQUAL TO or MORE THAN X number of listeners"},"monitorWhenLive":{"type":"boolean","description":"Only activate scrobble monitoring if station has a live DJ/Streamer","default":true},"apiKey":{"type":"string","description":"API Key used to access data about private streams\n\nhttps://www.azuracast.com/docs/developers/apis/#api-authentication"}},"required":["url","station"],"title":"AzuracastData"},"KoitoSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/KoitoSourceData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"configureAs":{"type":"string","enum":["source"],"description":"When used in `koito.config` this tells multi-scrobbler whether to use this data to configure a source or client.","default":"source","examples":["source"]},"type":{"type":"string","enum":["koito"]}},"required":["data","type"],"title":"KoitoSourceAIOConfig"},"KoitoSourceData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"url":{"type":"string","description":"URL for the Koito server","examples":["http://192.168.0.100:4110"]},"token":{"type":"string","description":"User token for the user to scrobble for","examples":["pM195xPV98CDpk0QW47FIIOR8AKATAX5DblBF-Jq0t1MbbKL"]},"username":{"type":"string","description":"Username of the user to scrobble for"}},"required":["token","url","username"],"title":"KoitoSourceData"},"TealSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/TealSourceData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/TealSourceOptions"},"configureAs":{"type":"string","enum":["source"],"description":"Should always be `souce` when using Tealfm as a Source","default":"source","examples":["source"]},"type":{"type":"string","enum":["tealfm"]}},"required":["data","type"],"title":"TealSourceAIOConfig"},"TealSourceData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"baseUri":{"type":"string","description":"The base URI of the Multi-Scrobbler to use for ATProto OAuth\n\nOnly include this if you want to use OAuth. The URI must be a non-IP/non-local domain using https: protocol."},"identifier":{"type":"string","description":"Identify the account to login as\n\n* For **App Password** Auth - your email\n* For **Oauth** - your handle minus the @"},"appPassword":{"type":"string","description":"The [App Password](https://atproto.com/specs/xrpc#app-passwords) you created for your account\n\nThis is created under https://bsky.app/settings/app-passwords\n\n**Use this if you are self-hosting Multi-Scrobbler on localhost or accessed like http://IP:PORT**"},"serviceAllow":{"type":"array","items":{"type":"string"}},"serviceDeny":{"type":"array","items":{"type":"string"}}},"required":["identifier"],"title":"TealSourceData"},"TealSourceOptions":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"TealSourceOptions"},"RockskySourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/RockskySourceData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/RockskySourceOptions"},"configureAs":{"type":"string","enum":["source"],"description":"When used in `rocksky.config` this tells multi-scrobbler whether to use this data to configure a source or client.","default":"source","examples":["source"]},"type":{"type":"string","enum":["rocksky"]}},"required":["data","type"],"title":"RockskySourceAIOConfig"},"RockskySourceData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"key":{"type":"string","description":"API Key generated from [API Applications](https://docs.rocksky.app/migrating-from-listenbrainz-to-rocksky-1040189m0) in Rocksky for your account","examples":["6794186bf-1157-4de6-80e5-uvb411f3ea2b"]},"handle":{"type":"string","description":"The **fully-qualified** handle for your ATPRoto/Bluesky account, like:\n\n* alice.bsky.social\n* foxxmd.com\n* mysuer.blacksky.app"}},"required":["handle","key"],"title":"RockskySourceData"},"RockskySourceOptions":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"},"audioScrobblerUrl":{"type":"string","description":"URL for the Rocksky *Listenbrainz* endpoint, if not using the default","examples":["https://audioscrobbler.rocksky.app"],"default":"https://audioscrobbler.rocksky.app"},"apiUrl":{"type":"string","description":"URL for the Rocksky *API* endpoint, if not using the default","examples":["https://api.rocksky.app"],"default":"https://api.rocksky.app"}},"title":"RockskySourceOptions"},"SonosSourceAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/SonosData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/SonosSourceOptions"},"type":{"type":"string","enum":["sonos"]}},"required":["data","type"],"title":"SonosSourceAIOConfig"},"SonosData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"host":{"type":"string","description":"IP address of any connected Sonos speaker or device","examples":["192.168.0.170"]},"devicesAllow":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Only scrobble if device name contains strings from this list (case-insensitive)"},"devicesBlock":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Do not scrobble if device name contains strings from this list (case-insensitive)"},"groupsAllow":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Only scrobble if the name of a group the playing device belongs to contains strings from this list (case-insensitive)"},"groupsBlock":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Do not scrobble if the name of a group the playing device belongs to contains strings from this list (case-insensitive)"}},"required":["host"],"title":"SonosData"},"SonosSourceOptions":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"},"logEmptyPlayer":{"type":"boolean"}},"title":"SonosSourceOptions"},"ClientAIOConfig":{"anyOf":[{"$ref":"#/definitions/MalojaClientAIOConfig"},{"$ref":"#/definitions/LastfmClientAIOConfig"},{"$ref":"#/definitions/LibrefmClientAIOConfig"},{"$ref":"#/definitions/ListenBrainzClientAIOConfig"},{"$ref":"#/definitions/KoitoClientAIOConfig"},{"$ref":"#/definitions/TealClientAIOConfig"},{"$ref":"#/definitions/RockSkyClientAIOConfig"},{"$ref":"#/definitions/DiscordClientAIOConfig"}],"title":"ClientAIOConfig"},"MalojaClientAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this client. Used with sources to restrict where scrobbles are sent.","examples":["MyConfig"]},"data":{"$ref":"#/definitions/MalojaClientData","description":"Specific data required to configure this client"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"options":{"$ref":"#/definitions/CommonClientOptions"},"configureAs":{"type":"string","enum":["client","source"],"description":"Should always be `client` when using Maloja as a client","default":"client","examples":["client"]},"type":{"type":"string","enum":["maloja"]}},"required":["data","name","type"],"title":"MalojaClientAIOConfig"},"MalojaClientData":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"url":{"type":"string","description":"URL for maloja server","examples":["http://localhost:42010"]},"apiKey":{"type":"string","description":"API Key for Maloja server","examples":["myApiKey"]}},"required":["apiKey","url"],"title":"MalojaClientData"},"CommonClientOptions":{"type":"object","properties":{"refreshEnabled":{"type":"boolean","description":"Try to get fresh scrobble history from client when tracks to be scrobbled are newer than the last scrobble found in client history","default":true,"examples":[true]},"refreshStaleAfter":{"type":"number","description":"Refresh scrobbled plays from upstream service if last refresh was at least X seconds ago\n\n**In most case this setting does NOT need to be changed.** The default value is sufficient for the majority of use-cases. Increasing this setting may increase upstream service load and slow down scrobbles.\n\nThis setting should only be changed in specific scenarios where MS is handling multiple \"relaying\" client-services (IE lfm -> lz -> lfm) and there is the potential for a client to be out of sync after more than a few seconds.","examples":[60],"default":60},"refreshMinInterval":{"type":"number","description":"Minimum time (milliseconds) required to pass before upstream scrobbles can be refreshed.\n\n**In most case this setting does NOT need to be changed.** This will always be equal to or smaller than `refreshStaleAfter`.","default":5000,"examples":[5000]},"refreshInitialCount":{"type":"number","description":"The number of tracks to retrieve on initial refresh (related to scrobbleBacklogCount). If not specified this is the maximum supported by the client in 1 API call."},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"checkExistingScrobbles":{"type":"boolean","description":"Check client for an existing scrobble at the same recorded time as the \"new\" track to be scrobbled. If an existing scrobble is found this track is not track scrobbled.","default":true,"examples":[true]},"verbose":{"type":"object","properties":{"match":{"$ref":"#/definitions/MatchLoggingOptions"}},"description":"Options used for increasing verbosity of logging in MS (used for debugging)"},"deadLetterRetries":{"type":"number","description":"Number of times MS should automatically retry scrobbles in dead letter queue","default":1,"examples":[1]},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"CommonClientOptions"},"LastfmClientAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this client. Used with sources to restrict where scrobbles are sent.","examples":["MyConfig"]},"data":{"$ref":"#/definitions/LastfmData","description":"Specific data required to configure this client"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"options":{"$ref":"#/definitions/LastfmClientOptions"},"configureAs":{"type":"string","enum":["client","source"],"description":"Should always be `client` when using LastFM as a client","default":"client","examples":["client"]},"type":{"type":"string","enum":["lastfm"]}},"required":["data","name","type"],"title":"LastfmClientAIOConfig"},"LastfmData":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"apiKey":{"type":"string","description":"API Key generated from Last.fm/Libre.fm account","examples":["787c921a2a2ab42320831aba0c8f2fc2"]},"secret":{"type":"string","description":"Secret generated from Last.fm/Libre.fm account","examples":["ec42e09d5ae0ee0f0816ca151008412a"]},"session":{"type":"string","description":"Optional session id returned from a completed auth flow"},"redirectUri":{"type":"string","description":"Optional URI to use for callback. Specify this if callback should be different than the default. MUST have \"lastfm/callback\" in the URL somewhere.","default":"http://localhost:9078/lastfm/callback","examples":["http://localhost:9078/lastfm/callback"]}},"required":["apiKey","secret"],"title":"LastfmData"},"LastfmClientOptions":{"type":"object","properties":{"nowPlaying":{"anyOf":[{"type":"boolean"},{"type":"array","items":{"type":"string"}}],"description":"Configure if this Client should report Now Playing from Sources that can scrobble to it\n\n* `true` (default) => Report Now Playing from any eligible Source. \n * If multiple Sources are Playing then reported Play is based on alphabetical order of Source names\n* `false` => Do not report Now Playing\n* `string` list => list of Source `names` that should be allowed to report Now Playing. Order of list determine priority of Play to Report.","default":true},"refreshEnabled":{"type":"boolean","description":"Try to get fresh scrobble history from client when tracks to be scrobbled are newer than the last scrobble found in client history","default":true,"examples":[true]},"refreshStaleAfter":{"type":"number","description":"Refresh scrobbled plays from upstream service if last refresh was at least X seconds ago\n\n**In most case this setting does NOT need to be changed.** The default value is sufficient for the majority of use-cases. Increasing this setting may increase upstream service load and slow down scrobbles.\n\nThis setting should only be changed in specific scenarios where MS is handling multiple \"relaying\" client-services (IE lfm -> lz -> lfm) and there is the potential for a client to be out of sync after more than a few seconds.","examples":[60],"default":60},"refreshMinInterval":{"type":"number","description":"Minimum time (milliseconds) required to pass before upstream scrobbles can be refreshed.\n\n**In most case this setting does NOT need to be changed.** This will always be equal to or smaller than `refreshStaleAfter`.","default":5000,"examples":[5000]},"refreshInitialCount":{"type":"number","description":"The number of tracks to retrieve on initial refresh (related to scrobbleBacklogCount). If not specified this is the maximum supported by the client in 1 API call."},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"checkExistingScrobbles":{"type":"boolean","description":"Check client for an existing scrobble at the same recorded time as the \"new\" track to be scrobbled. If an existing scrobble is found this track is not track scrobbled.","default":true,"examples":[true]},"verbose":{"type":"object","properties":{"match":{"$ref":"#/definitions/MatchLoggingOptions"}},"description":"Options used for increasing verbosity of logging in MS (used for debugging)"},"deadLetterRetries":{"type":"number","description":"Number of times MS should automatically retry scrobbles in dead letter queue","default":1,"examples":[1]},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"LastfmClientOptions"},"LibrefmClientAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this client. Used with sources to restrict where scrobbles are sent.","examples":["MyConfig"]},"data":{"$ref":"#/definitions/LibrefmData","description":"Specific data required to configure this client"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"options":{"$ref":"#/definitions/LibrefmClientOptions"},"configureAs":{"type":"string","enum":["client","source"],"description":"Should always be `client` when using Librefm as a client","default":"client","examples":["client"]},"type":{"type":"string","enum":["librefm"]}},"required":["data","name","type"],"title":"LibrefmClientAIOConfig"},"LibrefmClientOptions":{"type":"object","properties":{"nowPlaying":{"anyOf":[{"type":"boolean"},{"type":"array","items":{"type":"string"}}],"description":"Configure if this Client should report Now Playing from Sources that can scrobble to it\n\n* `true` (default) => Report Now Playing from any eligible Source. \n * If multiple Sources are Playing then reported Play is based on alphabetical order of Source names\n* `false` => Do not report Now Playing\n* `string` list => list of Source `names` that should be allowed to report Now Playing. Order of list determine priority of Play to Report.","default":true},"refreshEnabled":{"type":"boolean","description":"Try to get fresh scrobble history from client when tracks to be scrobbled are newer than the last scrobble found in client history","default":true,"examples":[true]},"refreshStaleAfter":{"type":"number","description":"Refresh scrobbled plays from upstream service if last refresh was at least X seconds ago\n\n**In most case this setting does NOT need to be changed.** The default value is sufficient for the majority of use-cases. Increasing this setting may increase upstream service load and slow down scrobbles.\n\nThis setting should only be changed in specific scenarios where MS is handling multiple \"relaying\" client-services (IE lfm -> lz -> lfm) and there is the potential for a client to be out of sync after more than a few seconds.","examples":[60],"default":60},"refreshMinInterval":{"type":"number","description":"Minimum time (milliseconds) required to pass before upstream scrobbles can be refreshed.\n\n**In most case this setting does NOT need to be changed.** This will always be equal to or smaller than `refreshStaleAfter`.","default":5000,"examples":[5000]},"refreshInitialCount":{"type":"number","description":"The number of tracks to retrieve on initial refresh (related to scrobbleBacklogCount). If not specified this is the maximum supported by the client in 1 API call."},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"checkExistingScrobbles":{"type":"boolean","description":"Check client for an existing scrobble at the same recorded time as the \"new\" track to be scrobbled. If an existing scrobble is found this track is not track scrobbled.","default":true,"examples":[true]},"verbose":{"type":"object","properties":{"match":{"$ref":"#/definitions/MatchLoggingOptions"}},"description":"Options used for increasing verbosity of logging in MS (used for debugging)"},"deadLetterRetries":{"type":"number","description":"Number of times MS should automatically retry scrobbles in dead letter queue","default":1,"examples":[1]},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"LibrefmClientOptions"},"ListenBrainzClientAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this client. Used with sources to restrict where scrobbles are sent.","examples":["MyConfig"]},"data":{"$ref":"#/definitions/ListenBrainzClientData","description":"Specific data required to configure this client"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"options":{"$ref":"#/definitions/CommonClientOptions"},"configureAs":{"type":"string","enum":["client","source"],"description":"Should always be `client` when using Listenbrainz as a client","default":"client","examples":["client"]},"type":{"type":"string","enum":["listenbrainz"]}},"required":["data","name","type"],"title":"ListenBrainzClientAIOConfig"},"ListenBrainzClientData":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"url":{"type":"string","description":"URL for the ListenBrainz server, if not using the default","examples":["https://api.listenbrainz.org/"],"default":"https://api.listenbrainz.org/"},"token":{"type":"string","description":"User token for the user to scrobble for","examples":["6794186bf-1157-4de6-80e5-uvb411f3ea2b"]},"username":{"type":"string","description":"Username of the user to scrobble for"}},"required":["token","username"],"title":"ListenBrainzClientData"},"KoitoClientAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this client. Used with sources to restrict where scrobbles are sent.","examples":["MyConfig"]},"data":{"$ref":"#/definitions/KoitoClientData","description":"Specific data required to configure this client"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"options":{"$ref":"#/definitions/CommonClientOptions"},"configureAs":{"type":"string","enum":["client","source"],"description":"Should always be `client` when using Koito as a client","default":"client","examples":["client"]},"type":{"type":"string","enum":["koito"]}},"required":["data","name","type"],"title":"KoitoClientAIOConfig"},"KoitoClientData":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"url":{"type":"string","description":"URL for the Koito server","examples":["http://192.168.0.100:4110"]},"token":{"type":"string","description":"User token for the user to scrobble for","examples":["pM195xPV98CDpk0QW47FIIOR8AKATAX5DblBF-Jq0t1MbbKL"]},"username":{"type":"string","description":"Username of the user to scrobble for"}},"required":["token","url","username"],"title":"KoitoClientData"},"TealClientAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this client. Used with sources to restrict where scrobbles are sent.","examples":["MyConfig"]},"data":{"$ref":"#/definitions/TealClientData","description":"Specific data required to configure this client"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"options":{"$ref":"#/definitions/TealClientOptions"},"configureAs":{"type":"string","enum":["client","source"],"description":"Should always be `client` when using Tealfm as a client","default":"client","examples":["client"]},"type":{"type":"string","enum":["tealfm"]}},"required":["data","name","type"],"title":"TealClientAIOConfig"},"TealClientData":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"baseUri":{"type":"string","description":"The base URI of the Multi-Scrobbler to use for ATProto OAuth\n\nOnly include this if you want to use OAuth. The URI must be a non-IP/non-local domain using https: protocol."},"identifier":{"type":"string","description":"Identify the account to login as\n\n* For **App Password** Auth - your email\n* For **Oauth** - your handle minus the @"},"appPassword":{"type":"string","description":"The [App Password](https://atproto.com/specs/xrpc#app-passwords) you created for your account\n\nThis is created under https://bsky.app/settings/app-passwords\n\n**Use this if you are self-hosting Multi-Scrobbler on localhost or accessed like http://IP:PORT**"}},"required":["identifier"],"title":"TealClientData"},"TealClientOptions":{"type":"object","properties":{"refreshEnabled":{"type":"boolean","description":"Try to get fresh scrobble history from client when tracks to be scrobbled are newer than the last scrobble found in client history","default":true,"examples":[true]},"refreshStaleAfter":{"type":"number","description":"Refresh scrobbled plays from upstream service if last refresh was at least X seconds ago\n\n**In most case this setting does NOT need to be changed.** The default value is sufficient for the majority of use-cases. Increasing this setting may increase upstream service load and slow down scrobbles.\n\nThis setting should only be changed in specific scenarios where MS is handling multiple \"relaying\" client-services (IE lfm -> lz -> lfm) and there is the potential for a client to be out of sync after more than a few seconds.","examples":[60],"default":60},"refreshMinInterval":{"type":"number","description":"Minimum time (milliseconds) required to pass before upstream scrobbles can be refreshed.\n\n**In most case this setting does NOT need to be changed.** This will always be equal to or smaller than `refreshStaleAfter`.","default":5000,"examples":[5000]},"refreshInitialCount":{"type":"number","description":"The number of tracks to retrieve on initial refresh (related to scrobbleBacklogCount). If not specified this is the maximum supported by the client in 1 API call."},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"checkExistingScrobbles":{"type":"boolean","description":"Check client for an existing scrobble at the same recorded time as the \"new\" track to be scrobbled. If an existing scrobble is found this track is not track scrobbled.","default":true,"examples":[true]},"verbose":{"type":"object","properties":{"match":{"$ref":"#/definitions/MatchLoggingOptions"}},"description":"Options used for increasing verbosity of logging in MS (used for debugging)"},"deadLetterRetries":{"type":"number","description":"Number of times MS should automatically retry scrobbles in dead letter queue","default":1,"examples":[1]},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"TealClientOptions"},"RockSkyClientAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this client. Used with sources to restrict where scrobbles are sent.","examples":["MyConfig"]},"data":{"$ref":"#/definitions/RockSkyClientData","description":"Specific data required to configure this client"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"options":{"$ref":"#/definitions/RockSkyClientOptions"},"configureAs":{"type":"string","enum":["client","source"],"description":"Should always be `client` when using RockSky as a client","default":"client","examples":["client"]},"type":{"type":"string","enum":["rocksky"]}},"required":["data","name","type"],"title":"RockSkyClientAIOConfig"},"RockSkyClientData":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"key":{"type":"string","description":"API Key generated from [API Applications](https://docs.rocksky.app/migrating-from-listenbrainz-to-rocksky-1040189m0) in Rocksky for your account","examples":["6794186bf-1157-4de6-80e5-uvb411f3ea2b"]},"handle":{"type":"string","description":"The **fully-qualified** handle for your ATPRoto/Bluesky account, like:\n\n* alice.bsky.social\n* foxxmd.com\n* mysuer.blacksky.app"}},"required":["handle","key"],"title":"RockSkyClientData"},"RockSkyClientOptions":{"type":"object","properties":{"nowPlaying":{"anyOf":[{"type":"boolean"},{"type":"array","items":{"type":"string"}}],"description":"Configure if this Client should report Now Playing from Sources that can scrobble to it\n\n* `true` (default) => Report Now Playing from any eligible Source. \n * If multiple Sources are Playing then reported Play is based on alphabetical order of Source names\n* `false` => Do not report Now Playing\n* `string` list => list of Source `names` that should be allowed to report Now Playing. Order of list determine priority of Play to Report.","default":true},"refreshEnabled":{"type":"boolean","description":"Try to get fresh scrobble history from client when tracks to be scrobbled are newer than the last scrobble found in client history","default":true,"examples":[true]},"refreshStaleAfter":{"type":"number","description":"Refresh scrobbled plays from upstream service if last refresh was at least X seconds ago\n\n**In most case this setting does NOT need to be changed.** The default value is sufficient for the majority of use-cases. Increasing this setting may increase upstream service load and slow down scrobbles.\n\nThis setting should only be changed in specific scenarios where MS is handling multiple \"relaying\" client-services (IE lfm -> lz -> lfm) and there is the potential for a client to be out of sync after more than a few seconds.","examples":[60],"default":60},"refreshMinInterval":{"type":"number","description":"Minimum time (milliseconds) required to pass before upstream scrobbles can be refreshed.\n\n**In most case this setting does NOT need to be changed.** This will always be equal to or smaller than `refreshStaleAfter`.","default":5000,"examples":[5000]},"refreshInitialCount":{"type":"number","description":"The number of tracks to retrieve on initial refresh (related to scrobbleBacklogCount). If not specified this is the maximum supported by the client in 1 API call."},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"checkExistingScrobbles":{"type":"boolean","description":"Check client for an existing scrobble at the same recorded time as the \"new\" track to be scrobbled. If an existing scrobble is found this track is not track scrobbled.","default":true,"examples":[true]},"verbose":{"type":"object","properties":{"match":{"$ref":"#/definitions/MatchLoggingOptions"}},"description":"Options used for increasing verbosity of logging in MS (used for debugging)"},"deadLetterRetries":{"type":"number","description":"Number of times MS should automatically retry scrobbles in dead letter queue","default":1,"examples":[1]},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"},"audioScrobblerUrl":{"type":"string","description":"URL for the Rocksky *Listenbrainz* endpoint, if not using the default","examples":["https://audioscrobbler.rocksky.app"],"default":"https://audioscrobbler.rocksky.app"},"apiUrl":{"type":"string","description":"URL for the Rocksky *API* endpoint, if not using the default","examples":["https://api.rocksky.app"],"default":"https://api.rocksky.app"}},"title":"RockSkyClientOptions"},"DiscordClientAIOConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this client. Used with sources to restrict where scrobbles are sent.","examples":["MyConfig"]},"data":{"$ref":"#/definitions/DiscordClientData","description":"Specific data required to configure this client"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"options":{"$ref":"#/definitions/CommonClientOptions"},"configureAs":{"type":"string","enum":["client","source"],"description":"Should always be `client` when using Koito as a client","default":"client","examples":["client"]},"type":{"type":"string","enum":["discord"]}},"required":["data","name","type"],"title":"DiscordClientAIOConfig"},"DiscordClientData":{"type":"object","properties":{"token":{"type":"string"},"applicationId":{"type":"string"},"artwork":{"anyOf":[{"type":"boolean"},{"type":"string"},{"type":"array","items":{"type":"string"}}]},"artworkDefaultUrl":{"type":"string"},"statusOverrideAllow":{"anyOf":[{"type":"string"},{"type":"array","items":{"$ref":"#/definitions/StatusType"}}]},"listeningActivityAllow":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}]},"ipcLocations":{"anyOf":[{"type":"string"},{"type":"array","items":{"anyOf":[{"type":"string"},{"type":"array","minItems":2,"items":[{"type":"number"},{"type":"string"}],"maxItems":2}]}}]}},"title":"DiscordClientData"},"StatusType":{"type":"string","enum":["online","idle","dnd","invisible"],"title":"StatusType"},"WebhookConfig":{"anyOf":[{"$ref":"#/definitions/GotifyConfig"},{"$ref":"#/definitions/NtfyConfig"},{"$ref":"#/definitions/AppriseConfig"}],"title":"WebhookConfig"},"GotifyConfig":{"type":"object","properties":{"type":{"type":"string","enum":["gotify","ntfy","apprise"],"description":"Webhook type. Valid values are:\n\n* gotify\n* ntfy","examples":["gotify"]},"name":{"type":"string","description":"A friendly name used to identify webhook config in logs"},"url":{"type":"string","description":"The URL of the Gotify server. Same URL that would be used to reach the Gotify UI","examples":["http://192.168.0.100:8078"]},"token":{"type":"string","description":"The token created for this Application in Gotify","examples":["AQZI58fA.rfSZbm"]},"priorities":{"$ref":"#/definitions/PrioritiesConfig","description":"Priority of messages\n\n* Info -> 5\n* Warn -> 7\n* Error -> 10"}},"required":["token","type","url"],"title":"GotifyConfig"},"PrioritiesConfig":{"type":"object","properties":{"info":{"type":"number","examples":[5]},"warn":{"type":"number","examples":[7]},"error":{"type":"number","examples":[10]}},"required":["info","warn","error"],"title":"PrioritiesConfig"},"NtfyConfig":{"type":"object","properties":{"type":{"type":"string","enum":["gotify","ntfy","apprise"],"description":"Webhook type. Valid values are:\n\n* gotify\n* ntfy","examples":["gotify"]},"name":{"type":"string","description":"A friendly name used to identify webhook config in logs"},"url":{"type":"string","description":"The URL of the Ntfy server","examples":["http://192.168.0.100:8078"]},"topic":{"type":"string","description":"The topic mutli-scrobbler should POST to"},"username":{"type":"string","description":"Required if topic is protected"},"password":{"type":"string","description":"Required if topic is protected"},"token":{"type":"string","description":"Use instead of username/password, required if topic is protected"},"priorities":{"$ref":"#/definitions/PrioritiesConfig","description":"Priority of messages\n\n* Info -> 3\n* Warn -> 4\n* Error -> 5"}},"required":["topic","type","url"],"title":"NtfyConfig"},"AppriseConfig":{"type":"object","properties":{"type":{"type":"string","enum":["gotify","ntfy","apprise"],"description":"Webhook type. Valid values are:\n\n* gotify\n* ntfy","examples":["gotify"]},"name":{"type":"string","description":"A friendly name used to identify webhook config in logs"},"host":{"type":"string","description":"The URL of the apprise-api server","examples":["http://192.168.0.100:8078"]},"urls":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"If using [Stateless Endpoints](https://github.com/caronc/apprise-api?tab=readme-ov-file#stateless-solution) the Apprise config URL(s) to send"},"keys":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"If using [Persistent Store Endpoints](https://github.com/caronc/apprise-api?tab=readme-ov-file#persistent-storage-solution) the Configuration ID(s) to send to\n\nNote: If multiple keys are defined then MS will attempt to POST to each one individually"},"tags":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Optional [tag(s)](https://github.com/caronc/apprise-api?tab=readme-ov-file#tagging) to send in the notification payload"}},"required":["host","type"],"title":"AppriseConfig"},"LogOptions":{"type":"object","properties":{"level":{"$ref":"#/definitions/LogLevel","description":"Specify the minimum log level for all log outputs without their own level specified.\n\nDefaults to env `LOG_LEVEL` or `info` if not specified.","default":"info"},"file":{"anyOf":[{"$ref":"#/definitions/LogLevel"},{"type":"boolean","const":false},{"$ref":"#/definitions/FileLogOptions"}],"description":"Specify the minimum log level to output to rotating files or file output options. If `false` no log files will be created."},"console":{"$ref":"#/definitions/LogLevel","description":"Specify the minimum log level streamed to the console (or docker container)"}},"description":"Configure log levels and file options for an AppLogger.\n\n```ts\nconst infoLogger = loggerApp({\n level: 'info' // console and file will log any levels `info` and above\n});\n\nconst logger = loggerApp({\n console: 'debug', // console will log `debug` and higher\n file: 'warn' // file will log `warn` and higher\n});\n\nconst fileLogger = loggerRollingApp({\n console: 'debug', // console will log `debug` and higher\n file: {\n level: 'warn', // file will log `warn` and higher\n path: '/my/cool/path/output.log', // optionally, output to log file at this path\n frequency: 'hourly', // optionally, rotate hourly\n }\n});\n```","title":"LogOptions"},"CacheConfigOptions":{"type":"object","properties":{"metadata":{"$ref":"#/definitions/CacheMetadataConfig"},"scrobble":{"$ref":"#/definitions/CacheScrobbleConfig"},"auth":{"$ref":"#/definitions/CacheAuthConfig"},"regex":{"type":"number","description":"Number of regex functions to cache (LRU)","default":200}},"title":"CacheConfigOptions"},"CacheMetadataConfig":{"$ref":"#/definitions/CacheConfig%3CCacheMetadataProvider%3E","title":"CacheMetadataConfig"},"CacheConfig":{"type":"object","properties":{"provider":{"$ref":"#/definitions/CacheMetadataProvider"},"connection":{"type":"string"}},"required":["provider"],"title":"CacheConfig"},"CacheMetadataProvider":{"$ref":"#/definitions/CacheProvider","title":"CacheMetadataProvider"},"CacheProvider":{"type":["string","boolean"],"enum":["memory","valkey","file",false],"title":"CacheProvider"},"CacheScrobbleConfig":{"$ref":"#/definitions/CacheConfig%3CCacheScrobbleProvider%3E","title":"CacheScrobbleConfig"},"CacheConfig":{"type":"object","properties":{"provider":{"$ref":"#/definitions/CacheScrobbleProvider"},"connection":{"type":"string"}},"required":["provider"],"title":"CacheConfig"},"CacheScrobbleProvider":{"$ref":"#/definitions/CacheProvider","title":"CacheScrobbleProvider"},"CacheAuthConfig":{"$ref":"#/definitions/CacheConfig%3CCacheAuthProvider%3E","title":"CacheAuthConfig"},"CacheConfig":{"type":"object","properties":{"provider":{"$ref":"#/definitions/CacheAuthProvider"},"connection":{"type":"string"}},"required":["provider"],"title":"CacheConfig"},"CacheAuthProvider":{"$ref":"#/definitions/CacheProvider","title":"CacheAuthProvider"},"TransformerCommonConfig":{"type":"object","properties":{"defaults":{"type":"object"},"data":{"type":"object"},"type":{"type":"string"},"name":{"type":"string"},"options":{"$ref":"#/definitions/TransformOptions"}},"required":["type"],"title":"TransformerCommonConfig"},"TransformOptions":{"type":"object","properties":{"failOnFetch":{"type":"boolean"},"throwOnFailure":{"anyOf":[{"type":"boolean"},{"type":"array","items":{"type":"string","enum":["artists","title","albumArtists","album","duration","meta","art"]}}]},"ttl":{"type":"string"}},"title":"TransformOptions"}}} \ No newline at end of file diff --git a/src/backend/common/schema/client.json b/src/backend/common/schema/client.json index a3e19d98..c0af33ce 100644 --- a/src/backend/common/schema/client.json +++ b/src/backend/common/schema/client.json @@ -1 +1 @@ -{"$schema":"http://json-schema.org/draft-07/schema#","anyOf":[{"$ref":"#/definitions/MalojaClientConfig"},{"$ref":"#/definitions/LastfmClientConfig"},{"$ref":"#/definitions/LibrefmClientConfig"},{"$ref":"#/definitions/ListenBrainzClientConfig"},{"$ref":"#/definitions/KoitoClientConfig"},{"$ref":"#/definitions/TealClientConfig"},{"$ref":"#/definitions/RockSkyClientConfig"}],"definitions":{"MalojaClientConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this client. Used with sources to restrict where scrobbles are sent.","examples":["MyConfig"]},"data":{"$ref":"#/definitions/MalojaClientData","description":"Specific data required to configure this client"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"options":{"$ref":"#/definitions/CommonClientOptions"},"configureAs":{"type":"string","enum":["client","source"],"description":"Should always be `client` when using Maloja as a client","default":"client","examples":["client"]}},"required":["data","name"],"title":"MalojaClientConfig"},"MalojaClientData":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"url":{"type":"string","description":"URL for maloja server","examples":["http://localhost:42010"]},"apiKey":{"type":"string","description":"API Key for Maloja server","examples":["myApiKey"]}},"required":["apiKey","url"],"title":"MalojaClientData"},"CommonClientOptions":{"type":"object","properties":{"refreshEnabled":{"type":"boolean","description":"Try to get fresh scrobble history from client when tracks to be scrobbled are newer than the last scrobble found in client history","default":true,"examples":[true]},"refreshStaleAfter":{"type":"number","description":"Refresh scrobbled plays from upstream service if last refresh was at least X seconds ago\n\n**In most case this setting does NOT need to be changed.** The default value is sufficient for the majority of use-cases. Increasing this setting may increase upstream service load and slow down scrobbles.\n\nThis setting should only be changed in specific scenarios where MS is handling multiple \"relaying\" client-services (IE lfm -> lz -> lfm) and there is the potential for a client to be out of sync after more than a few seconds.","examples":[60],"default":60},"refreshMinInterval":{"type":"number","description":"Minimum time (milliseconds) required to pass before upstream scrobbles can be refreshed.\n\n**In most case this setting does NOT need to be changed.** This will always be equal to or smaller than `refreshStaleAfter`.","default":5000,"examples":[5000]},"refreshInitialCount":{"type":"number","description":"The number of tracks to retrieve on initial refresh (related to scrobbleBacklogCount). If not specified this is the maximum supported by the client in 1 API call."},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"checkExistingScrobbles":{"type":"boolean","description":"Check client for an existing scrobble at the same recorded time as the \"new\" track to be scrobbled. If an existing scrobble is found this track is not track scrobbled.","default":true,"examples":[true]},"verbose":{"type":"object","properties":{"match":{"$ref":"#/definitions/MatchLoggingOptions"}},"description":"Options used for increasing verbosity of logging in MS (used for debugging)"},"deadLetterRetries":{"type":"number","description":"Number of times MS should automatically retry scrobbles in dead letter queue","default":1,"examples":[1]},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"CommonClientOptions"},"MatchLoggingOptions":{"type":"object","properties":{"onNoMatch":{"type":"boolean","description":"Log to DEBUG when a new track does NOT match an existing scrobble","default":false,"examples":[false]},"onMatch":{"type":"boolean","description":"Log to DEBUG when a new track DOES match an existing scrobble","default":false,"examples":[false]},"confidenceBreakdown":{"type":"boolean","description":"Include confidence breakdowns in track match logging, if applicable","default":false,"examples":[false]}},"description":"Scrobble matching (between new source track and existing client scrobbles) logging options. Used for debugging.","title":"MatchLoggingOptions"},"PlayTransformOptions":{"type":"object","properties":{"log":{"anyOf":[{"type":"boolean"},{"type":"string","enum":["all"]}]},"preCompare":{"$ref":"#/definitions/PlayTransformPartsConfig%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%3E"},"compare":{"type":"object","properties":{"candidate":{"$ref":"#/definitions/PlayTransformPartsConfig%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%3E"},"existing":{"$ref":"#/definitions/PlayTransformPartsConfig%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%3E"}}},"postCompare":{"$ref":"#/definitions/PlayTransformPartsConfig%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%3E"}},"title":"PlayTransformOptions"},"PlayTransformPartsConfig<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm)>":{"anyOf":[{"$ref":"#/definitions/PlayTransformPartsArray%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%2CMaybeStageTyped%3E"},{"$ref":"#/definitions/PlayTransformParts%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%2CMaybeStageTyped%3E"}],"description":"Represents the weakly-defined user config. May be an array of parts or one parts object","title":"PlayTransformPartsConfig<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm)>"},"PlayTransformPartsArray<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm),MaybeStageTyped>":{"type":"array","items":{"$ref":"#/definitions/PlayTransformParts%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%2CMaybeStageTyped%3E"},"title":"PlayTransformPartsArray<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm),MaybeStageTyped>"},"PlayTransformParts<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm),MaybeStageTyped>":{"anyOf":[{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"title":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"artists":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"albumArtists":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"album":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"duration":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"meta":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"onSuccess":{"$ref":"#/definitions/FlowControlTerm"},"onFailure":{"$ref":"#/definitions/FlowControlTerm"},"onSkip":{"$ref":"#/definitions/FlowControlTerm"},"failureReturnPartial":{"type":"boolean"},"type":{"$ref":"#/definitions/StageTypeMetadata"},"name":{"type":"string"},"stageHash":{"type":"string"},"score":{"type":"number"}},"required":["type"]},{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"title":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"artists":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"albumArtists":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"album":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"duration":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"meta":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"onSuccess":{"$ref":"#/definitions/FlowControlTerm"},"onFailure":{"$ref":"#/definitions/FlowControlTerm"},"onSkip":{"$ref":"#/definitions/FlowControlTerm"},"failureReturnPartial":{"type":"boolean"},"type":{"$ref":"#/definitions/StageTypeUser"},"name":{"type":"string"},"stageHash":{"type":"string"}},"required":["type"]},{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"title":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"artists":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"albumArtists":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"album":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"duration":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"meta":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"onSuccess":{"$ref":"#/definitions/FlowControlTerm"},"onFailure":{"$ref":"#/definitions/FlowControlTerm"},"onSkip":{"$ref":"#/definitions/FlowControlTerm"},"failureReturnPartial":{"type":"boolean"},"type":{"type":"string","enum":["native"]},"name":{"type":"string"},"stageHash":{"type":"string"}},"required":["type"]},{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"title":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"artists":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"albumArtists":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"album":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"duration":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"meta":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"onSuccess":{"$ref":"#/definitions/FlowControlTerm"},"onFailure":{"$ref":"#/definitions/FlowControlTerm"},"onSkip":{"$ref":"#/definitions/FlowControlTerm"},"failureReturnPartial":{"type":"boolean"},"name":{"type":"string"}}},{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"title":{},"artists":{},"albumArtists":{},"album":{},"duration":{},"meta":{},"onSuccess":{"$ref":"#/definitions/FlowControlTerm"},"onFailure":{"$ref":"#/definitions/FlowControlTerm"},"onSkip":{"$ref":"#/definitions/FlowControlTerm"},"failureReturnPartial":{"type":"boolean"},"type":{"type":"string"},"name":{"type":"string"},"stageHash":{"type":"string"}},"required":["type"]}],"title":"PlayTransformParts<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm),MaybeStageTyped>"},"WhenConditionsConfig":{"$ref":"#/definitions/WhenConditions%3Cstring%3E","title":"WhenConditionsConfig"},"WhenConditions":{"type":"array","items":{"$ref":"#/definitions/WhenParts%3Cstring%3E"},"title":"WhenConditions"},"WhenParts":{"$ref":"#/definitions/PlayTransformPartsAtomic%3Cstring%3E","title":"WhenParts"},"PlayTransformPartsAtomic":{"type":"object","properties":{"title":{"type":"string"},"artists":{"type":"string"},"albumArtists":{"type":"string"},"album":{"type":"string"},"duration":{"type":"string"},"meta":{"type":"string"}},"title":"PlayTransformPartsAtomic"},"Whennable":{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"}},"title":"Whennable"},"FlowControlTerm":{"type":"string","enum":["continue","stop"],"title":"FlowControlTerm"},"StageTypeMetadata":{"type":"string","enum":["spotify","musicbrainz","native"],"title":"StageTypeMetadata"},"SearchAndReplaceTerm":{"anyOf":[{"type":"string"},{"$ref":"#/definitions/ConditionalSearchAndReplaceTerm"}],"title":"SearchAndReplaceTerm"},"ConditionalSearchAndReplaceTerm":{"$ref":"#/definitions/ConditionalSearchAndReplaceRegExp","title":"ConditionalSearchAndReplaceTerm"},"ConditionalSearchAndReplaceRegExp":{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"search":{"anyOf":[{"type":"string"},{"type":"string","format":"regex"}],"description":"The search value to test for\n\nCan be a normal string (converted to a case-sensitive literal) or a valid regular expression as a string, or an actual RegExp object","examples":[["find this string","/some string*/ig"]]},"replace":{"type":"string","description":"The replacement string/value to use when search is found\n\nThis can be a literal string like `'replace with this`, an empty string to remove the search value (`''`), or a special regex value\n\nSee replacement here for more information: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace"},"test":{"$comment":"(obj: SearchAndReplaceRegExp) => boolean","type":"object","properties":{"namedArgs":{"type":"object","properties":{"obj":{"$ref":"#/definitions/SearchAndReplaceRegExp"}},"required":["obj"],"additionalProperties":false}},"description":"An optional function to execute before running this search-and-replace that decides if it should run at all"}},"required":["replace","search"],"title":"ConditionalSearchAndReplaceRegExp"},"SearchAndReplaceRegExp":{"type":"object","properties":{"search":{"anyOf":[{"type":"string"},{"type":"string","format":"regex"}],"description":"The search value to test for\n\nCan be a normal string (converted to a case-sensitive literal) or a valid regular expression as a string, or an actual RegExp object","examples":[["find this string","/some string*/ig"]]},"replace":{"type":"string","description":"The replacement string/value to use when search is found\n\nThis can be a literal string like `'replace with this`, an empty string to remove the search value (`''`), or a special regex value\n\nSee replacement here for more information: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace"},"test":{"$comment":"(obj: SearchAndReplaceRegExp) => boolean","type":"object","properties":{"namedArgs":{"type":"object","properties":{"obj":{"$ref":"#/definitions/SearchAndReplaceRegExp"}},"required":["obj"],"additionalProperties":false}},"description":"An optional function to execute before running this search-and-replace that decides if it should run at all"}},"required":["search","replace"],"title":"SearchAndReplaceRegExp"},"ExternalMetadataTerm":{"anyOf":[{"type":"boolean"},{"not":{}},{"$ref":"#/definitions/Whennable"}],"title":"ExternalMetadataTerm"},"StageTypeUser":{"type":"string","enum":["user"],"title":"StageTypeUser"},"LastfmClientConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this client. Used with sources to restrict where scrobbles are sent.","examples":["MyConfig"]},"data":{"$ref":"#/definitions/LastfmData","description":"Specific data required to configure this client"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"options":{"$ref":"#/definitions/LastfmClientOptions"},"configureAs":{"type":"string","enum":["client","source"],"description":"Should always be `client` when using LastFM as a client","default":"client","examples":["client"]}},"required":["data","name"],"title":"LastfmClientConfig"},"LastfmData":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"apiKey":{"type":"string","description":"API Key generated from Last.fm/Libre.fm account","examples":["787c921a2a2ab42320831aba0c8f2fc2"]},"secret":{"type":"string","description":"Secret generated from Last.fm/Libre.fm account","examples":["ec42e09d5ae0ee0f0816ca151008412a"]},"session":{"type":"string","description":"Optional session id returned from a completed auth flow"},"redirectUri":{"type":"string","description":"Optional URI to use for callback. Specify this if callback should be different than the default. MUST have \"lastfm/callback\" in the URL somewhere.","default":"http://localhost:9078/lastfm/callback","examples":["http://localhost:9078/lastfm/callback"]}},"required":["apiKey","secret"],"title":"LastfmData"},"LastfmClientOptions":{"type":"object","properties":{"nowPlaying":{"anyOf":[{"type":"boolean"},{"type":"array","items":{"type":"string"}}],"description":"Configure if this Client should report Now Playing from Sources that can scrobble to it\n\n* `true` (default) => Report Now Playing from any eligible Source. \n * If multiple Sources are Playing then reported Play is based on alphabetical order of Source names\n* `false` => Do not report Now Playing\n* `string` list => list of Source `names` that should be allowed to report Now Playing. Order of list determine priority of Play to Report.","default":true},"refreshEnabled":{"type":"boolean","description":"Try to get fresh scrobble history from client when tracks to be scrobbled are newer than the last scrobble found in client history","default":true,"examples":[true]},"refreshStaleAfter":{"type":"number","description":"Refresh scrobbled plays from upstream service if last refresh was at least X seconds ago\n\n**In most case this setting does NOT need to be changed.** The default value is sufficient for the majority of use-cases. Increasing this setting may increase upstream service load and slow down scrobbles.\n\nThis setting should only be changed in specific scenarios where MS is handling multiple \"relaying\" client-services (IE lfm -> lz -> lfm) and there is the potential for a client to be out of sync after more than a few seconds.","examples":[60],"default":60},"refreshMinInterval":{"type":"number","description":"Minimum time (milliseconds) required to pass before upstream scrobbles can be refreshed.\n\n**In most case this setting does NOT need to be changed.** This will always be equal to or smaller than `refreshStaleAfter`.","default":5000,"examples":[5000]},"refreshInitialCount":{"type":"number","description":"The number of tracks to retrieve on initial refresh (related to scrobbleBacklogCount). If not specified this is the maximum supported by the client in 1 API call."},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"checkExistingScrobbles":{"type":"boolean","description":"Check client for an existing scrobble at the same recorded time as the \"new\" track to be scrobbled. If an existing scrobble is found this track is not track scrobbled.","default":true,"examples":[true]},"verbose":{"type":"object","properties":{"match":{"$ref":"#/definitions/MatchLoggingOptions"}},"description":"Options used for increasing verbosity of logging in MS (used for debugging)"},"deadLetterRetries":{"type":"number","description":"Number of times MS should automatically retry scrobbles in dead letter queue","default":1,"examples":[1]},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"LastfmClientOptions"},"LibrefmClientConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this client. Used with sources to restrict where scrobbles are sent.","examples":["MyConfig"]},"data":{"$ref":"#/definitions/LibrefmData","description":"Specific data required to configure this client"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"options":{"$ref":"#/definitions/LibrefmClientOptions"},"configureAs":{"type":"string","enum":["client","source"],"description":"Should always be `client` when using Librefm as a client","default":"client","examples":["client"]}},"required":["data","name"],"title":"LibrefmClientConfig"},"LibrefmData":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"apiKey":{"type":"string","description":"Optional Secret for Libre.fm account\n\nThis can be anything, or it will be generated by multi-scrobbler","examples":["anyValue"]},"secret":{"type":"string","description":"Optional Secret for Libre.fm account\n\nThis can be anything, or it will be generated by multi-scrobbler","examples":["anyValue"]},"session":{"type":"string","description":"Optional session id returned from a completed auth flow"},"path":{"type":"string"},"urlBase":{"type":"string","description":"(Optional) The host and path prefix for your Libre.fm instance","default":"https://libre.fm/2.0/"},"redirectUri":{"type":"string","description":"Optional URI to use for callback. Specify this if callback should be different than the default. MUST have \"librefm/callback\" in the URL somewhere.","default":"http://localhost:9078/librefm/callback","examples":["http://localhost:9078/librefm/callback"]}},"title":"LibrefmData"},"LibrefmClientOptions":{"type":"object","properties":{"nowPlaying":{"anyOf":[{"type":"boolean"},{"type":"array","items":{"type":"string"}}],"description":"Configure if this Client should report Now Playing from Sources that can scrobble to it\n\n* `true` (default) => Report Now Playing from any eligible Source. \n * If multiple Sources are Playing then reported Play is based on alphabetical order of Source names\n* `false` => Do not report Now Playing\n* `string` list => list of Source `names` that should be allowed to report Now Playing. Order of list determine priority of Play to Report.","default":true},"refreshEnabled":{"type":"boolean","description":"Try to get fresh scrobble history from client when tracks to be scrobbled are newer than the last scrobble found in client history","default":true,"examples":[true]},"refreshStaleAfter":{"type":"number","description":"Refresh scrobbled plays from upstream service if last refresh was at least X seconds ago\n\n**In most case this setting does NOT need to be changed.** The default value is sufficient for the majority of use-cases. Increasing this setting may increase upstream service load and slow down scrobbles.\n\nThis setting should only be changed in specific scenarios where MS is handling multiple \"relaying\" client-services (IE lfm -> lz -> lfm) and there is the potential for a client to be out of sync after more than a few seconds.","examples":[60],"default":60},"refreshMinInterval":{"type":"number","description":"Minimum time (milliseconds) required to pass before upstream scrobbles can be refreshed.\n\n**In most case this setting does NOT need to be changed.** This will always be equal to or smaller than `refreshStaleAfter`.","default":5000,"examples":[5000]},"refreshInitialCount":{"type":"number","description":"The number of tracks to retrieve on initial refresh (related to scrobbleBacklogCount). If not specified this is the maximum supported by the client in 1 API call."},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"checkExistingScrobbles":{"type":"boolean","description":"Check client for an existing scrobble at the same recorded time as the \"new\" track to be scrobbled. If an existing scrobble is found this track is not track scrobbled.","default":true,"examples":[true]},"verbose":{"type":"object","properties":{"match":{"$ref":"#/definitions/MatchLoggingOptions"}},"description":"Options used for increasing verbosity of logging in MS (used for debugging)"},"deadLetterRetries":{"type":"number","description":"Number of times MS should automatically retry scrobbles in dead letter queue","default":1,"examples":[1]},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"LibrefmClientOptions"},"ListenBrainzClientConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this client. Used with sources to restrict where scrobbles are sent.","examples":["MyConfig"]},"data":{"$ref":"#/definitions/ListenBrainzClientData","description":"Specific data required to configure this client"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"options":{"$ref":"#/definitions/CommonClientOptions"},"configureAs":{"type":"string","enum":["client","source"],"description":"Should always be `client` when using Listenbrainz as a client","default":"client","examples":["client"]}},"required":["data","name"],"title":"ListenBrainzClientConfig"},"ListenBrainzClientData":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"url":{"type":"string","description":"URL for the ListenBrainz server, if not using the default","examples":["https://api.listenbrainz.org/"],"default":"https://api.listenbrainz.org/"},"token":{"type":"string","description":"User token for the user to scrobble for","examples":["6794186bf-1157-4de6-80e5-uvb411f3ea2b"]},"username":{"type":"string","description":"Username of the user to scrobble for"}},"required":["token","username"],"title":"ListenBrainzClientData"},"KoitoClientConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this client. Used with sources to restrict where scrobbles are sent.","examples":["MyConfig"]},"data":{"$ref":"#/definitions/KoitoClientData","description":"Specific data required to configure this client"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"options":{"$ref":"#/definitions/CommonClientOptions"},"configureAs":{"type":"string","enum":["client","source"],"description":"Should always be `client` when using Koito as a client","default":"client","examples":["client"]}},"required":["data","name"],"title":"KoitoClientConfig"},"KoitoClientData":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"url":{"type":"string","description":"URL for the Koito server","examples":["http://192.168.0.100:4110"]},"token":{"type":"string","description":"User token for the user to scrobble for","examples":["pM195xPV98CDpk0QW47FIIOR8AKATAX5DblBF-Jq0t1MbbKL"]},"username":{"type":"string","description":"Username of the user to scrobble for"}},"required":["token","url","username"],"title":"KoitoClientData"},"TealClientConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this client. Used with sources to restrict where scrobbles are sent.","examples":["MyConfig"]},"data":{"$ref":"#/definitions/TealClientData","description":"Specific data required to configure this client"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"options":{"$ref":"#/definitions/TealClientOptions"},"configureAs":{"type":"string","enum":["client","source"],"description":"Should always be `client` when using Tealfm as a client","default":"client","examples":["client"]}},"required":["data","name"],"title":"TealClientConfig"},"TealClientData":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"baseUri":{"type":"string","description":"The base URI of the Multi-Scrobbler to use for ATProto OAuth\n\nOnly include this if you want to use OAuth. The URI must be a non-IP/non-local domain using https: protocol."},"identifier":{"type":"string","description":"Identify the account to login as\n\n* For **App Password** Auth - your email\n* For **Oauth** - your handle minus the @"},"appPassword":{"type":"string","description":"The [App Password](https://atproto.com/specs/xrpc#app-passwords) you created for your account\n\nThis is created under https://bsky.app/settings/app-passwords\n\n**Use this if you are self-hosting Multi-Scrobbler on localhost or accessed like http://IP:PORT**"}},"required":["identifier"],"title":"TealClientData"},"TealClientOptions":{"type":"object","properties":{"refreshEnabled":{"type":"boolean","description":"Try to get fresh scrobble history from client when tracks to be scrobbled are newer than the last scrobble found in client history","default":true,"examples":[true]},"refreshStaleAfter":{"type":"number","description":"Refresh scrobbled plays from upstream service if last refresh was at least X seconds ago\n\n**In most case this setting does NOT need to be changed.** The default value is sufficient for the majority of use-cases. Increasing this setting may increase upstream service load and slow down scrobbles.\n\nThis setting should only be changed in specific scenarios where MS is handling multiple \"relaying\" client-services (IE lfm -> lz -> lfm) and there is the potential for a client to be out of sync after more than a few seconds.","examples":[60],"default":60},"refreshMinInterval":{"type":"number","description":"Minimum time (milliseconds) required to pass before upstream scrobbles can be refreshed.\n\n**In most case this setting does NOT need to be changed.** This will always be equal to or smaller than `refreshStaleAfter`.","default":5000,"examples":[5000]},"refreshInitialCount":{"type":"number","description":"The number of tracks to retrieve on initial refresh (related to scrobbleBacklogCount). If not specified this is the maximum supported by the client in 1 API call."},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"checkExistingScrobbles":{"type":"boolean","description":"Check client for an existing scrobble at the same recorded time as the \"new\" track to be scrobbled. If an existing scrobble is found this track is not track scrobbled.","default":true,"examples":[true]},"verbose":{"type":"object","properties":{"match":{"$ref":"#/definitions/MatchLoggingOptions"}},"description":"Options used for increasing verbosity of logging in MS (used for debugging)"},"deadLetterRetries":{"type":"number","description":"Number of times MS should automatically retry scrobbles in dead letter queue","default":1,"examples":[1]},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"TealClientOptions"},"RockSkyClientConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this client. Used with sources to restrict where scrobbles are sent.","examples":["MyConfig"]},"data":{"$ref":"#/definitions/RockSkyClientData","description":"Specific data required to configure this client"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"options":{"$ref":"#/definitions/RockSkyClientOptions"},"configureAs":{"type":"string","enum":["client","source"],"description":"Should always be `client` when using RockSky as a client","default":"client","examples":["client"]}},"required":["data","name"],"title":"RockSkyClientConfig"},"RockSkyClientData":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"key":{"type":"string","description":"API Key generated from [API Applications](https://docs.rocksky.app/migrating-from-listenbrainz-to-rocksky-1040189m0) in Rocksky for your account","examples":["6794186bf-1157-4de6-80e5-uvb411f3ea2b"]},"handle":{"type":"string","description":"The **fully-qualified** handle for your ATPRoto/Bluesky account, like:\n\n* alice.bsky.social\n* foxxmd.com\n* mysuer.blacksky.app"}},"required":["handle","key"],"title":"RockSkyClientData"},"RockSkyClientOptions":{"type":"object","properties":{"nowPlaying":{"anyOf":[{"type":"boolean"},{"type":"array","items":{"type":"string"}}],"description":"Configure if this Client should report Now Playing from Sources that can scrobble to it\n\n* `true` (default) => Report Now Playing from any eligible Source. \n * If multiple Sources are Playing then reported Play is based on alphabetical order of Source names\n* `false` => Do not report Now Playing\n* `string` list => list of Source `names` that should be allowed to report Now Playing. Order of list determine priority of Play to Report.","default":true},"refreshEnabled":{"type":"boolean","description":"Try to get fresh scrobble history from client when tracks to be scrobbled are newer than the last scrobble found in client history","default":true,"examples":[true]},"refreshStaleAfter":{"type":"number","description":"Refresh scrobbled plays from upstream service if last refresh was at least X seconds ago\n\n**In most case this setting does NOT need to be changed.** The default value is sufficient for the majority of use-cases. Increasing this setting may increase upstream service load and slow down scrobbles.\n\nThis setting should only be changed in specific scenarios where MS is handling multiple \"relaying\" client-services (IE lfm -> lz -> lfm) and there is the potential for a client to be out of sync after more than a few seconds.","examples":[60],"default":60},"refreshMinInterval":{"type":"number","description":"Minimum time (milliseconds) required to pass before upstream scrobbles can be refreshed.\n\n**In most case this setting does NOT need to be changed.** This will always be equal to or smaller than `refreshStaleAfter`.","default":5000,"examples":[5000]},"refreshInitialCount":{"type":"number","description":"The number of tracks to retrieve on initial refresh (related to scrobbleBacklogCount). If not specified this is the maximum supported by the client in 1 API call."},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"checkExistingScrobbles":{"type":"boolean","description":"Check client for an existing scrobble at the same recorded time as the \"new\" track to be scrobbled. If an existing scrobble is found this track is not track scrobbled.","default":true,"examples":[true]},"verbose":{"type":"object","properties":{"match":{"$ref":"#/definitions/MatchLoggingOptions"}},"description":"Options used for increasing verbosity of logging in MS (used for debugging)"},"deadLetterRetries":{"type":"number","description":"Number of times MS should automatically retry scrobbles in dead letter queue","default":1,"examples":[1]},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"},"audioScrobblerUrl":{"type":"string","description":"URL for the Rocksky *Listenbrainz* endpoint, if not using the default","examples":["https://audioscrobbler.rocksky.app"],"default":"https://audioscrobbler.rocksky.app"},"apiUrl":{"type":"string","description":"URL for the Rocksky *API* endpoint, if not using the default","examples":["https://api.rocksky.app"],"default":"https://api.rocksky.app"}},"title":"RockSkyClientOptions"}}} \ No newline at end of file +{"$schema":"http://json-schema.org/draft-07/schema#","anyOf":[{"$ref":"#/definitions/MalojaClientConfig"},{"$ref":"#/definitions/LastfmClientConfig"},{"$ref":"#/definitions/LibrefmClientConfig"},{"$ref":"#/definitions/ListenBrainzClientConfig"},{"$ref":"#/definitions/KoitoClientConfig"},{"$ref":"#/definitions/TealClientConfig"},{"$ref":"#/definitions/RockSkyClientConfig"},{"$ref":"#/definitions/DiscordClientConfig"}],"definitions":{"MalojaClientConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this client. Used with sources to restrict where scrobbles are sent.","examples":["MyConfig"]},"data":{"$ref":"#/definitions/MalojaClientData","description":"Specific data required to configure this client"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"options":{"$ref":"#/definitions/CommonClientOptions"},"configureAs":{"type":"string","enum":["client","source"],"description":"Should always be `client` when using Maloja as a client","default":"client","examples":["client"]}},"required":["data","name"],"title":"MalojaClientConfig"},"MalojaClientData":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"url":{"type":"string","description":"URL for maloja server","examples":["http://localhost:42010"]},"apiKey":{"type":"string","description":"API Key for Maloja server","examples":["myApiKey"]}},"required":["apiKey","url"],"title":"MalojaClientData"},"CommonClientOptions":{"type":"object","properties":{"refreshEnabled":{"type":"boolean","description":"Try to get fresh scrobble history from client when tracks to be scrobbled are newer than the last scrobble found in client history","default":true,"examples":[true]},"refreshStaleAfter":{"type":"number","description":"Refresh scrobbled plays from upstream service if last refresh was at least X seconds ago\n\n**In most case this setting does NOT need to be changed.** The default value is sufficient for the majority of use-cases. Increasing this setting may increase upstream service load and slow down scrobbles.\n\nThis setting should only be changed in specific scenarios where MS is handling multiple \"relaying\" client-services (IE lfm -> lz -> lfm) and there is the potential for a client to be out of sync after more than a few seconds.","examples":[60],"default":60},"refreshMinInterval":{"type":"number","description":"Minimum time (milliseconds) required to pass before upstream scrobbles can be refreshed.\n\n**In most case this setting does NOT need to be changed.** This will always be equal to or smaller than `refreshStaleAfter`.","default":5000,"examples":[5000]},"refreshInitialCount":{"type":"number","description":"The number of tracks to retrieve on initial refresh (related to scrobbleBacklogCount). If not specified this is the maximum supported by the client in 1 API call."},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"checkExistingScrobbles":{"type":"boolean","description":"Check client for an existing scrobble at the same recorded time as the \"new\" track to be scrobbled. If an existing scrobble is found this track is not track scrobbled.","default":true,"examples":[true]},"verbose":{"type":"object","properties":{"match":{"$ref":"#/definitions/MatchLoggingOptions"}},"description":"Options used for increasing verbosity of logging in MS (used for debugging)"},"deadLetterRetries":{"type":"number","description":"Number of times MS should automatically retry scrobbles in dead letter queue","default":1,"examples":[1]},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"CommonClientOptions"},"MatchLoggingOptions":{"type":"object","properties":{"onNoMatch":{"type":"boolean","description":"Log to DEBUG when a new track does NOT match an existing scrobble","default":false,"examples":[false]},"onMatch":{"type":"boolean","description":"Log to DEBUG when a new track DOES match an existing scrobble","default":false,"examples":[false]},"confidenceBreakdown":{"type":"boolean","description":"Include confidence breakdowns in track match logging, if applicable","default":false,"examples":[false]}},"description":"Scrobble matching (between new source track and existing client scrobbles) logging options. Used for debugging.","title":"MatchLoggingOptions"},"PlayTransformOptions":{"type":"object","properties":{"log":{"anyOf":[{"type":"boolean"},{"type":"string","enum":["all"]}]},"preCompare":{"$ref":"#/definitions/PlayTransformPartsConfig%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%3E"},"compare":{"type":"object","properties":{"candidate":{"$ref":"#/definitions/PlayTransformPartsConfig%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%3E"},"existing":{"$ref":"#/definitions/PlayTransformPartsConfig%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%3E"}}},"postCompare":{"$ref":"#/definitions/PlayTransformPartsConfig%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%3E"}},"title":"PlayTransformOptions"},"PlayTransformPartsConfig<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm)>":{"anyOf":[{"$ref":"#/definitions/PlayTransformPartsArray%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%2CMaybeStageTyped%3E"},{"$ref":"#/definitions/PlayTransformParts%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%2CMaybeStageTyped%3E"}],"description":"Represents the weakly-defined user config. May be an array of parts or one parts object","title":"PlayTransformPartsConfig<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm)>"},"PlayTransformPartsArray<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm),MaybeStageTyped>":{"type":"array","items":{"$ref":"#/definitions/PlayTransformParts%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%2CMaybeStageTyped%3E"},"title":"PlayTransformPartsArray<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm),MaybeStageTyped>"},"PlayTransformParts<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm),MaybeStageTyped>":{"anyOf":[{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"title":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"artists":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"albumArtists":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"album":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"duration":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"meta":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"onSuccess":{"$ref":"#/definitions/FlowControlTerm"},"onFailure":{"$ref":"#/definitions/FlowControlTerm"},"onSkip":{"$ref":"#/definitions/FlowControlTerm"},"failureReturnPartial":{"type":"boolean"},"type":{"$ref":"#/definitions/StageTypeMetadata"},"name":{"type":"string"},"stageHash":{"type":"string"},"score":{"type":"number"}},"required":["type"]},{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"title":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"artists":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"albumArtists":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"album":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"duration":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"meta":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"onSuccess":{"$ref":"#/definitions/FlowControlTerm"},"onFailure":{"$ref":"#/definitions/FlowControlTerm"},"onSkip":{"$ref":"#/definitions/FlowControlTerm"},"failureReturnPartial":{"type":"boolean"},"type":{"$ref":"#/definitions/StageTypeUser"},"name":{"type":"string"},"stageHash":{"type":"string"}},"required":["type"]},{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"title":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"artists":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"albumArtists":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"album":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"duration":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"meta":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"onSuccess":{"$ref":"#/definitions/FlowControlTerm"},"onFailure":{"$ref":"#/definitions/FlowControlTerm"},"onSkip":{"$ref":"#/definitions/FlowControlTerm"},"failureReturnPartial":{"type":"boolean"},"type":{"type":"string","enum":["native"]},"name":{"type":"string"},"stageHash":{"type":"string"}},"required":["type"]},{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"title":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"artists":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"albumArtists":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"album":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"duration":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"meta":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"onSuccess":{"$ref":"#/definitions/FlowControlTerm"},"onFailure":{"$ref":"#/definitions/FlowControlTerm"},"onSkip":{"$ref":"#/definitions/FlowControlTerm"},"failureReturnPartial":{"type":"boolean"},"name":{"type":"string"}}},{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"title":{},"artists":{},"albumArtists":{},"album":{},"duration":{},"meta":{},"onSuccess":{"$ref":"#/definitions/FlowControlTerm"},"onFailure":{"$ref":"#/definitions/FlowControlTerm"},"onSkip":{"$ref":"#/definitions/FlowControlTerm"},"failureReturnPartial":{"type":"boolean"},"type":{"type":"string"},"name":{"type":"string"},"stageHash":{"type":"string"}},"required":["type"]}],"title":"PlayTransformParts<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm),MaybeStageTyped>"},"WhenConditionsConfig":{"$ref":"#/definitions/WhenConditions%3Cstring%3E","title":"WhenConditionsConfig"},"WhenConditions":{"type":"array","items":{"$ref":"#/definitions/WhenParts%3Cstring%3E"},"title":"WhenConditions"},"WhenParts":{"$ref":"#/definitions/PlayTransformPartsAtomic%3Cstring%3E","title":"WhenParts"},"PlayTransformPartsAtomic":{"type":"object","properties":{"title":{"type":"string"},"artists":{"type":"string"},"albumArtists":{"type":"string"},"album":{"type":"string"},"duration":{"type":"string"},"meta":{"type":"string"}},"title":"PlayTransformPartsAtomic"},"Whennable":{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"}},"title":"Whennable"},"FlowControlTerm":{"type":"string","enum":["continue","stop"],"title":"FlowControlTerm"},"StageTypeMetadata":{"type":"string","enum":["spotify","musicbrainz","native"],"title":"StageTypeMetadata"},"SearchAndReplaceTerm":{"anyOf":[{"type":"string"},{"$ref":"#/definitions/ConditionalSearchAndReplaceTerm"}],"title":"SearchAndReplaceTerm"},"ConditionalSearchAndReplaceTerm":{"$ref":"#/definitions/ConditionalSearchAndReplaceRegExp","title":"ConditionalSearchAndReplaceTerm"},"ConditionalSearchAndReplaceRegExp":{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"search":{"anyOf":[{"type":"string"},{"type":"string","format":"regex"}],"description":"The search value to test for\n\nCan be a normal string (converted to a case-sensitive literal) or a valid regular expression as a string, or an actual RegExp object","examples":[["find this string","/some string*/ig"]]},"replace":{"type":"string","description":"The replacement string/value to use when search is found\n\nThis can be a literal string like `'replace with this`, an empty string to remove the search value (`''`), or a special regex value\n\nSee replacement here for more information: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace"},"test":{"$comment":"(obj: SearchAndReplaceRegExp) => boolean","type":"object","properties":{"namedArgs":{"type":"object","properties":{"obj":{"$ref":"#/definitions/SearchAndReplaceRegExp"}},"required":["obj"],"additionalProperties":false}},"description":"An optional function to execute before running this search-and-replace that decides if it should run at all"}},"required":["replace","search"],"title":"ConditionalSearchAndReplaceRegExp"},"SearchAndReplaceRegExp":{"type":"object","properties":{"search":{"anyOf":[{"type":"string"},{"type":"string","format":"regex"}],"description":"The search value to test for\n\nCan be a normal string (converted to a case-sensitive literal) or a valid regular expression as a string, or an actual RegExp object","examples":[["find this string","/some string*/ig"]]},"replace":{"type":"string","description":"The replacement string/value to use when search is found\n\nThis can be a literal string like `'replace with this`, an empty string to remove the search value (`''`), or a special regex value\n\nSee replacement here for more information: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace"},"test":{"$comment":"(obj: SearchAndReplaceRegExp) => boolean","type":"object","properties":{"namedArgs":{"type":"object","properties":{"obj":{"$ref":"#/definitions/SearchAndReplaceRegExp"}},"required":["obj"],"additionalProperties":false}},"description":"An optional function to execute before running this search-and-replace that decides if it should run at all"}},"required":["search","replace"],"title":"SearchAndReplaceRegExp"},"ExternalMetadataTerm":{"anyOf":[{"type":"boolean"},{"not":{}},{"$ref":"#/definitions/Whennable"}],"title":"ExternalMetadataTerm"},"StageTypeUser":{"type":"string","enum":["user"],"title":"StageTypeUser"},"LastfmClientConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this client. Used with sources to restrict where scrobbles are sent.","examples":["MyConfig"]},"data":{"$ref":"#/definitions/LastfmData","description":"Specific data required to configure this client"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"options":{"$ref":"#/definitions/LastfmClientOptions"},"configureAs":{"type":"string","enum":["client","source"],"description":"Should always be `client` when using LastFM as a client","default":"client","examples":["client"]}},"required":["data","name"],"title":"LastfmClientConfig"},"LastfmData":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"apiKey":{"type":"string","description":"API Key generated from Last.fm/Libre.fm account","examples":["787c921a2a2ab42320831aba0c8f2fc2"]},"secret":{"type":"string","description":"Secret generated from Last.fm/Libre.fm account","examples":["ec42e09d5ae0ee0f0816ca151008412a"]},"session":{"type":"string","description":"Optional session id returned from a completed auth flow"},"redirectUri":{"type":"string","description":"Optional URI to use for callback. Specify this if callback should be different than the default. MUST have \"lastfm/callback\" in the URL somewhere.","default":"http://localhost:9078/lastfm/callback","examples":["http://localhost:9078/lastfm/callback"]}},"required":["apiKey","secret"],"title":"LastfmData"},"LastfmClientOptions":{"type":"object","properties":{"nowPlaying":{"anyOf":[{"type":"boolean"},{"type":"array","items":{"type":"string"}}],"description":"Configure if this Client should report Now Playing from Sources that can scrobble to it\n\n* `true` (default) => Report Now Playing from any eligible Source. \n * If multiple Sources are Playing then reported Play is based on alphabetical order of Source names\n* `false` => Do not report Now Playing\n* `string` list => list of Source `names` that should be allowed to report Now Playing. Order of list determine priority of Play to Report.","default":true},"refreshEnabled":{"type":"boolean","description":"Try to get fresh scrobble history from client when tracks to be scrobbled are newer than the last scrobble found in client history","default":true,"examples":[true]},"refreshStaleAfter":{"type":"number","description":"Refresh scrobbled plays from upstream service if last refresh was at least X seconds ago\n\n**In most case this setting does NOT need to be changed.** The default value is sufficient for the majority of use-cases. Increasing this setting may increase upstream service load and slow down scrobbles.\n\nThis setting should only be changed in specific scenarios where MS is handling multiple \"relaying\" client-services (IE lfm -> lz -> lfm) and there is the potential for a client to be out of sync after more than a few seconds.","examples":[60],"default":60},"refreshMinInterval":{"type":"number","description":"Minimum time (milliseconds) required to pass before upstream scrobbles can be refreshed.\n\n**In most case this setting does NOT need to be changed.** This will always be equal to or smaller than `refreshStaleAfter`.","default":5000,"examples":[5000]},"refreshInitialCount":{"type":"number","description":"The number of tracks to retrieve on initial refresh (related to scrobbleBacklogCount). If not specified this is the maximum supported by the client in 1 API call."},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"checkExistingScrobbles":{"type":"boolean","description":"Check client for an existing scrobble at the same recorded time as the \"new\" track to be scrobbled. If an existing scrobble is found this track is not track scrobbled.","default":true,"examples":[true]},"verbose":{"type":"object","properties":{"match":{"$ref":"#/definitions/MatchLoggingOptions"}},"description":"Options used for increasing verbosity of logging in MS (used for debugging)"},"deadLetterRetries":{"type":"number","description":"Number of times MS should automatically retry scrobbles in dead letter queue","default":1,"examples":[1]},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"LastfmClientOptions"},"LibrefmClientConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this client. Used with sources to restrict where scrobbles are sent.","examples":["MyConfig"]},"data":{"$ref":"#/definitions/LibrefmData","description":"Specific data required to configure this client"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"options":{"$ref":"#/definitions/LibrefmClientOptions"},"configureAs":{"type":"string","enum":["client","source"],"description":"Should always be `client` when using Librefm as a client","default":"client","examples":["client"]}},"required":["data","name"],"title":"LibrefmClientConfig"},"LibrefmData":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"apiKey":{"type":"string","description":"Optional Secret for Libre.fm account\n\nThis can be anything, or it will be generated by multi-scrobbler","examples":["anyValue"]},"secret":{"type":"string","description":"Optional Secret for Libre.fm account\n\nThis can be anything, or it will be generated by multi-scrobbler","examples":["anyValue"]},"session":{"type":"string","description":"Optional session id returned from a completed auth flow"},"path":{"type":"string"},"urlBase":{"type":"string","description":"(Optional) The host and path prefix for your Libre.fm instance","default":"https://libre.fm/2.0/"},"redirectUri":{"type":"string","description":"Optional URI to use for callback. Specify this if callback should be different than the default. MUST have \"librefm/callback\" in the URL somewhere.","default":"http://localhost:9078/librefm/callback","examples":["http://localhost:9078/librefm/callback"]}},"title":"LibrefmData"},"LibrefmClientOptions":{"type":"object","properties":{"nowPlaying":{"anyOf":[{"type":"boolean"},{"type":"array","items":{"type":"string"}}],"description":"Configure if this Client should report Now Playing from Sources that can scrobble to it\n\n* `true` (default) => Report Now Playing from any eligible Source. \n * If multiple Sources are Playing then reported Play is based on alphabetical order of Source names\n* `false` => Do not report Now Playing\n* `string` list => list of Source `names` that should be allowed to report Now Playing. Order of list determine priority of Play to Report.","default":true},"refreshEnabled":{"type":"boolean","description":"Try to get fresh scrobble history from client when tracks to be scrobbled are newer than the last scrobble found in client history","default":true,"examples":[true]},"refreshStaleAfter":{"type":"number","description":"Refresh scrobbled plays from upstream service if last refresh was at least X seconds ago\n\n**In most case this setting does NOT need to be changed.** The default value is sufficient for the majority of use-cases. Increasing this setting may increase upstream service load and slow down scrobbles.\n\nThis setting should only be changed in specific scenarios where MS is handling multiple \"relaying\" client-services (IE lfm -> lz -> lfm) and there is the potential for a client to be out of sync after more than a few seconds.","examples":[60],"default":60},"refreshMinInterval":{"type":"number","description":"Minimum time (milliseconds) required to pass before upstream scrobbles can be refreshed.\n\n**In most case this setting does NOT need to be changed.** This will always be equal to or smaller than `refreshStaleAfter`.","default":5000,"examples":[5000]},"refreshInitialCount":{"type":"number","description":"The number of tracks to retrieve on initial refresh (related to scrobbleBacklogCount). If not specified this is the maximum supported by the client in 1 API call."},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"checkExistingScrobbles":{"type":"boolean","description":"Check client for an existing scrobble at the same recorded time as the \"new\" track to be scrobbled. If an existing scrobble is found this track is not track scrobbled.","default":true,"examples":[true]},"verbose":{"type":"object","properties":{"match":{"$ref":"#/definitions/MatchLoggingOptions"}},"description":"Options used for increasing verbosity of logging in MS (used for debugging)"},"deadLetterRetries":{"type":"number","description":"Number of times MS should automatically retry scrobbles in dead letter queue","default":1,"examples":[1]},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"LibrefmClientOptions"},"ListenBrainzClientConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this client. Used with sources to restrict where scrobbles are sent.","examples":["MyConfig"]},"data":{"$ref":"#/definitions/ListenBrainzClientData","description":"Specific data required to configure this client"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"options":{"$ref":"#/definitions/CommonClientOptions"},"configureAs":{"type":"string","enum":["client","source"],"description":"Should always be `client` when using Listenbrainz as a client","default":"client","examples":["client"]}},"required":["data","name"],"title":"ListenBrainzClientConfig"},"ListenBrainzClientData":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"url":{"type":"string","description":"URL for the ListenBrainz server, if not using the default","examples":["https://api.listenbrainz.org/"],"default":"https://api.listenbrainz.org/"},"token":{"type":"string","description":"User token for the user to scrobble for","examples":["6794186bf-1157-4de6-80e5-uvb411f3ea2b"]},"username":{"type":"string","description":"Username of the user to scrobble for"}},"required":["token","username"],"title":"ListenBrainzClientData"},"KoitoClientConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this client. Used with sources to restrict where scrobbles are sent.","examples":["MyConfig"]},"data":{"$ref":"#/definitions/KoitoClientData","description":"Specific data required to configure this client"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"options":{"$ref":"#/definitions/CommonClientOptions"},"configureAs":{"type":"string","enum":["client","source"],"description":"Should always be `client` when using Koito as a client","default":"client","examples":["client"]}},"required":["data","name"],"title":"KoitoClientConfig"},"KoitoClientData":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"url":{"type":"string","description":"URL for the Koito server","examples":["http://192.168.0.100:4110"]},"token":{"type":"string","description":"User token for the user to scrobble for","examples":["pM195xPV98CDpk0QW47FIIOR8AKATAX5DblBF-Jq0t1MbbKL"]},"username":{"type":"string","description":"Username of the user to scrobble for"}},"required":["token","url","username"],"title":"KoitoClientData"},"TealClientConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this client. Used with sources to restrict where scrobbles are sent.","examples":["MyConfig"]},"data":{"$ref":"#/definitions/TealClientData","description":"Specific data required to configure this client"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"options":{"$ref":"#/definitions/TealClientOptions"},"configureAs":{"type":"string","enum":["client","source"],"description":"Should always be `client` when using Tealfm as a client","default":"client","examples":["client"]}},"required":["data","name"],"title":"TealClientConfig"},"TealClientData":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"baseUri":{"type":"string","description":"The base URI of the Multi-Scrobbler to use for ATProto OAuth\n\nOnly include this if you want to use OAuth. The URI must be a non-IP/non-local domain using https: protocol."},"identifier":{"type":"string","description":"Identify the account to login as\n\n* For **App Password** Auth - your email\n* For **Oauth** - your handle minus the @"},"appPassword":{"type":"string","description":"The [App Password](https://atproto.com/specs/xrpc#app-passwords) you created for your account\n\nThis is created under https://bsky.app/settings/app-passwords\n\n**Use this if you are self-hosting Multi-Scrobbler on localhost or accessed like http://IP:PORT**"}},"required":["identifier"],"title":"TealClientData"},"TealClientOptions":{"type":"object","properties":{"refreshEnabled":{"type":"boolean","description":"Try to get fresh scrobble history from client when tracks to be scrobbled are newer than the last scrobble found in client history","default":true,"examples":[true]},"refreshStaleAfter":{"type":"number","description":"Refresh scrobbled plays from upstream service if last refresh was at least X seconds ago\n\n**In most case this setting does NOT need to be changed.** The default value is sufficient for the majority of use-cases. Increasing this setting may increase upstream service load and slow down scrobbles.\n\nThis setting should only be changed in specific scenarios where MS is handling multiple \"relaying\" client-services (IE lfm -> lz -> lfm) and there is the potential for a client to be out of sync after more than a few seconds.","examples":[60],"default":60},"refreshMinInterval":{"type":"number","description":"Minimum time (milliseconds) required to pass before upstream scrobbles can be refreshed.\n\n**In most case this setting does NOT need to be changed.** This will always be equal to or smaller than `refreshStaleAfter`.","default":5000,"examples":[5000]},"refreshInitialCount":{"type":"number","description":"The number of tracks to retrieve on initial refresh (related to scrobbleBacklogCount). If not specified this is the maximum supported by the client in 1 API call."},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"checkExistingScrobbles":{"type":"boolean","description":"Check client for an existing scrobble at the same recorded time as the \"new\" track to be scrobbled. If an existing scrobble is found this track is not track scrobbled.","default":true,"examples":[true]},"verbose":{"type":"object","properties":{"match":{"$ref":"#/definitions/MatchLoggingOptions"}},"description":"Options used for increasing verbosity of logging in MS (used for debugging)"},"deadLetterRetries":{"type":"number","description":"Number of times MS should automatically retry scrobbles in dead letter queue","default":1,"examples":[1]},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"TealClientOptions"},"RockSkyClientConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this client. Used with sources to restrict where scrobbles are sent.","examples":["MyConfig"]},"data":{"$ref":"#/definitions/RockSkyClientData","description":"Specific data required to configure this client"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"options":{"$ref":"#/definitions/RockSkyClientOptions"},"configureAs":{"type":"string","enum":["client","source"],"description":"Should always be `client` when using RockSky as a client","default":"client","examples":["client"]}},"required":["data","name"],"title":"RockSkyClientConfig"},"RockSkyClientData":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"key":{"type":"string","description":"API Key generated from [API Applications](https://docs.rocksky.app/migrating-from-listenbrainz-to-rocksky-1040189m0) in Rocksky for your account","examples":["6794186bf-1157-4de6-80e5-uvb411f3ea2b"]},"handle":{"type":"string","description":"The **fully-qualified** handle for your ATPRoto/Bluesky account, like:\n\n* alice.bsky.social\n* foxxmd.com\n* mysuer.blacksky.app"}},"required":["handle","key"],"title":"RockSkyClientData"},"RockSkyClientOptions":{"type":"object","properties":{"nowPlaying":{"anyOf":[{"type":"boolean"},{"type":"array","items":{"type":"string"}}],"description":"Configure if this Client should report Now Playing from Sources that can scrobble to it\n\n* `true` (default) => Report Now Playing from any eligible Source. \n * If multiple Sources are Playing then reported Play is based on alphabetical order of Source names\n* `false` => Do not report Now Playing\n* `string` list => list of Source `names` that should be allowed to report Now Playing. Order of list determine priority of Play to Report.","default":true},"refreshEnabled":{"type":"boolean","description":"Try to get fresh scrobble history from client when tracks to be scrobbled are newer than the last scrobble found in client history","default":true,"examples":[true]},"refreshStaleAfter":{"type":"number","description":"Refresh scrobbled plays from upstream service if last refresh was at least X seconds ago\n\n**In most case this setting does NOT need to be changed.** The default value is sufficient for the majority of use-cases. Increasing this setting may increase upstream service load and slow down scrobbles.\n\nThis setting should only be changed in specific scenarios where MS is handling multiple \"relaying\" client-services (IE lfm -> lz -> lfm) and there is the potential for a client to be out of sync after more than a few seconds.","examples":[60],"default":60},"refreshMinInterval":{"type":"number","description":"Minimum time (milliseconds) required to pass before upstream scrobbles can be refreshed.\n\n**In most case this setting does NOT need to be changed.** This will always be equal to or smaller than `refreshStaleAfter`.","default":5000,"examples":[5000]},"refreshInitialCount":{"type":"number","description":"The number of tracks to retrieve on initial refresh (related to scrobbleBacklogCount). If not specified this is the maximum supported by the client in 1 API call."},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"checkExistingScrobbles":{"type":"boolean","description":"Check client for an existing scrobble at the same recorded time as the \"new\" track to be scrobbled. If an existing scrobble is found this track is not track scrobbled.","default":true,"examples":[true]},"verbose":{"type":"object","properties":{"match":{"$ref":"#/definitions/MatchLoggingOptions"}},"description":"Options used for increasing verbosity of logging in MS (used for debugging)"},"deadLetterRetries":{"type":"number","description":"Number of times MS should automatically retry scrobbles in dead letter queue","default":1,"examples":[1]},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"},"audioScrobblerUrl":{"type":"string","description":"URL for the Rocksky *Listenbrainz* endpoint, if not using the default","examples":["https://audioscrobbler.rocksky.app"],"default":"https://audioscrobbler.rocksky.app"},"apiUrl":{"type":"string","description":"URL for the Rocksky *API* endpoint, if not using the default","examples":["https://api.rocksky.app"],"default":"https://api.rocksky.app"}},"title":"RockSkyClientOptions"},"DiscordClientConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this client. Used with sources to restrict where scrobbles are sent.","examples":["MyConfig"]},"data":{"$ref":"#/definitions/DiscordClientData","description":"Specific data required to configure this client"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"options":{"$ref":"#/definitions/CommonClientOptions"},"configureAs":{"type":"string","enum":["client","source"],"description":"Should always be `client` when using Koito as a client","default":"client","examples":["client"]}},"required":["data","name"],"title":"DiscordClientConfig"},"DiscordClientData":{"type":"object","properties":{"token":{"type":"string"},"applicationId":{"type":"string"},"artwork":{"anyOf":[{"type":"boolean"},{"type":"string"},{"type":"array","items":{"type":"string"}}]},"artworkDefaultUrl":{"type":"string"},"statusOverrideAllow":{"anyOf":[{"type":"string"},{"type":"array","items":{"$ref":"#/definitions/StatusType"}}]},"listeningActivityAllow":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}]},"ipcLocations":{"anyOf":[{"type":"string"},{"type":"array","items":{"anyOf":[{"type":"string"},{"type":"array","minItems":2,"items":[{"type":"number"},{"type":"string"}],"maxItems":2}]}}]}},"title":"DiscordClientData"},"StatusType":{"type":"string","enum":["online","idle","dnd","invisible"],"title":"StatusType"}}} \ No newline at end of file diff --git a/src/backend/common/schema/source.json b/src/backend/common/schema/source.json index f30d854a..9da6e470 100644 --- a/src/backend/common/schema/source.json +++ b/src/backend/common/schema/source.json @@ -1 +1 @@ -{"$schema":"http://json-schema.org/draft-07/schema#","anyOf":[{"$ref":"#/definitions/SpotifySourceConfig"},{"$ref":"#/definitions/PlexApiSourceConfig"},{"$ref":"#/definitions/DeezerSourceConfig"},{"$ref":"#/definitions/DeezerInternalSourceConfig"},{"$ref":"#/definitions/ListenbrainzEndpointSourceConfig"},{"$ref":"#/definitions/LastFMEndpointSourceConfig"},{"$ref":"#/definitions/SubSonicSourceConfig"},{"$ref":"#/definitions/JellyApiSourceConfig"},{"$ref":"#/definitions/LastfmSourceConfig"},{"$ref":"#/definitions/LibrefmSourceConfig"},{"$ref":"#/definitions/YTMusicSourceConfig"},{"$ref":"#/definitions/MPRISSourceConfig"},{"$ref":"#/definitions/MopidySourceConfig"},{"$ref":"#/definitions/ListenBrainzSourceConfig"},{"$ref":"#/definitions/JRiverSourceConfig"},{"$ref":"#/definitions/KodiSourceConfig"},{"$ref":"#/definitions/WebScrobblerSourceConfig"},{"$ref":"#/definitions/ChromecastSourceConfig"},{"$ref":"#/definitions/MalojaSourceConfig"},{"$ref":"#/definitions/MusikcubeSourceConfig"},{"$ref":"#/definitions/MusicCastSourceConfig"},{"$ref":"#/definitions/MPDSourceConfig"},{"$ref":"#/definitions/VLCSourceConfig"},{"$ref":"#/definitions/IcecastSourceConfig"},{"$ref":"#/definitions/AzuracastSourceConfig"},{"$ref":"#/definitions/KoitoSourceConfig"},{"$ref":"#/definitions/TealSourceConfig"},{"$ref":"#/definitions/RockskySourceConfig"}],"definitions":{"SpotifySourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/SpotifySourceData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"}},"required":["data"],"title":"SpotifySourceConfig"},"SpotifySourceData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)\n\nIt is unlikely you should need to change this unless you scrobble many very short tracks often\n\nReading:\n* https://developer.spotify.com/documentation/web-api/guides/rate-limits/\n* https://medium.com/mendix/limiting-your-amount-of-calls-in-mendix-most-of-the-time-rest-835dde55b10e\n * Rate limit may ~180 req/min\n* https://community.spotify.com/t5/Spotify-for-Developers/Web-API-ratelimit/m-p/5503150/highlight/true#M7930\n * Informally indicated as 20 req/sec? Probably for burstiness","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"clientId":{"type":"string","description":"spotify client id","examples":["787c921a2a2ab42320831aba0c8f2fc2"]},"clientSecret":{"type":"string","description":"spotify client secret","examples":["ec42e09d5ae0ee0f0816ca151008412a"]},"redirectUri":{"type":"string","description":"spotify redirect URI -- required only if not the default shown here. URI must end in \"callback\"","default":"http://localhost:9078/callback","examples":["http://localhost:9078/callback"]}},"required":["clientId","clientSecret"],"title":"SpotifySourceData"},"CommonSourceOptions":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"CommonSourceOptions"},"LogLevel":{"type":"string","enum":["silent","fatal","error","warn","info","log","verbose","debug"],"description":"Names of log levels that can be invoked on the logger\n\nFrom lowest to highest:\n\n* `debug`\n* `verbose`\n* `log`\n* `info`\n* `warn`\n* `error`\n* `fatal`\n* `silent` (will never output anything)\n\nWhen used in `LogOptions` specifies the **minimum** level the output should log at.","title":"LogLevel"},"FileLogOptions":{"type":"object","properties":{"timestamp":{"type":"string","enum":["unix","iso","auto"],"description":"For rolling log files\n\nWhen\n* value passed to rolling destination is a string (`path` from LogOptions is a string) and\n* `frequency` is defined\n\nThis determines the format of the datetime inserted into the log file name:\n\n* `unix` - unix epoch timestamp in milliseconds\n* `iso` - Full [ISO8601](https://en.wikipedia.org/wiki/ISO_8601) datetime IE '2024-03-07T20:11:34Z'\n* `auto`\n * When frequency is `daily` only inserts date IE YYYY-MM-DD\n * Otherwise inserts full ISO8601 datetime","default":"auto"},"size":{"type":["number","string"],"description":"The maximum size of a given rolling log file.\n\nCan be combined with frequency. Use k, m and g to express values in KB, MB or GB.\n\nNumerical values will be considered as MB.","default":"10MB"},"frequency":{"anyOf":[{"type":"string","enum":["daily"]},{"type":"string","enum":["hourly"]},{"type":"number"}],"description":"The amount of time a given rolling log file is used. Can be combined with size.\n\nUse `daily` or `hourly` to rotate file every day (or every hour). Existing file within the current day (or hour) will be re-used.\n\nNumerical values will be considered as a number of milliseconds. Using a numerical value will always create a new file upon startup.","default":"daily"},"path":{"anyOf":[{"type":"string"},{"$comment":"() => string"}],"description":"The path and filename to use for log files.\n\nIf using rolling files the filename will be appended with `.N` (a number) BEFORE the extension based on rolling status.\n\nMay also be specified using env LOG_PATH or a function that returns a string.\n\nIf path is relative the absolute path will be derived from `logBaseDir` (in `LoggerAppExtras`) which defaults to CWD","default":"./logs/app.log"},"level":{"anyOf":[{"$ref":"#/definitions/LogLevel"},{"type":"boolean","const":false}],"description":"Specify the minimum log level to output to rotating files. If `false` no log files will be created."}},"title":"FileLogOptions"},"ScrobbleThresholds":{"type":"object","properties":{"duration":{"type":["number","null"],"description":"The number of seconds a track has been listened to before it should be considered scrobbled.\n\nSet to null to disable.","default":240,"examples":[240]},"percent":{"type":["number","null"],"description":"The percentage (as an integer) of a track that should have been seen played before it should be scrobbled. Only used if the Source provides information about how long the track is.\n\nSet to null to disable.\n\nNOTE: This should be used with care when the Source is a \"polling\" type (has an 'interval' property). If the track is short and the interval is too high MS may ignore the track if percentage is high because it had not \"seen\" the track for long enough from first discovery, even if you have been playing the track for longer.","default":50,"examples":[50]}},"title":"ScrobbleThresholds"},"PlayTransformOptions":{"type":"object","properties":{"log":{"anyOf":[{"type":"boolean"},{"type":"string","enum":["all"]}]},"preCompare":{"$ref":"#/definitions/PlayTransformPartsConfig%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%3E"},"compare":{"type":"object","properties":{"candidate":{"$ref":"#/definitions/PlayTransformPartsConfig%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%3E"},"existing":{"$ref":"#/definitions/PlayTransformPartsConfig%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%3E"}}},"postCompare":{"$ref":"#/definitions/PlayTransformPartsConfig%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%3E"}},"title":"PlayTransformOptions"},"PlayTransformPartsConfig<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm)>":{"anyOf":[{"$ref":"#/definitions/PlayTransformPartsArray%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%2CMaybeStageTyped%3E"},{"$ref":"#/definitions/PlayTransformParts%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%2CMaybeStageTyped%3E"}],"description":"Represents the weakly-defined user config. May be an array of parts or one parts object","title":"PlayTransformPartsConfig<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm)>"},"PlayTransformPartsArray<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm),MaybeStageTyped>":{"type":"array","items":{"$ref":"#/definitions/PlayTransformParts%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%2CMaybeStageTyped%3E"},"title":"PlayTransformPartsArray<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm),MaybeStageTyped>"},"PlayTransformParts<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm),MaybeStageTyped>":{"anyOf":[{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"title":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"artists":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"albumArtists":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"album":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"duration":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"meta":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"onSuccess":{"$ref":"#/definitions/FlowControlTerm"},"onFailure":{"$ref":"#/definitions/FlowControlTerm"},"onSkip":{"$ref":"#/definitions/FlowControlTerm"},"failureReturnPartial":{"type":"boolean"},"type":{"$ref":"#/definitions/StageTypeMetadata"},"name":{"type":"string"},"stageHash":{"type":"string"},"score":{"type":"number"}},"required":["type"]},{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"title":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"artists":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"albumArtists":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"album":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"duration":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"meta":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"onSuccess":{"$ref":"#/definitions/FlowControlTerm"},"onFailure":{"$ref":"#/definitions/FlowControlTerm"},"onSkip":{"$ref":"#/definitions/FlowControlTerm"},"failureReturnPartial":{"type":"boolean"},"type":{"$ref":"#/definitions/StageTypeUser"},"name":{"type":"string"},"stageHash":{"type":"string"}},"required":["type"]},{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"title":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"artists":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"albumArtists":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"album":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"duration":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"meta":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"onSuccess":{"$ref":"#/definitions/FlowControlTerm"},"onFailure":{"$ref":"#/definitions/FlowControlTerm"},"onSkip":{"$ref":"#/definitions/FlowControlTerm"},"failureReturnPartial":{"type":"boolean"},"type":{"type":"string","enum":["native"]},"name":{"type":"string"},"stageHash":{"type":"string"}},"required":["type"]},{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"title":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"artists":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"albumArtists":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"album":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"duration":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"meta":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"onSuccess":{"$ref":"#/definitions/FlowControlTerm"},"onFailure":{"$ref":"#/definitions/FlowControlTerm"},"onSkip":{"$ref":"#/definitions/FlowControlTerm"},"failureReturnPartial":{"type":"boolean"},"name":{"type":"string"}}},{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"title":{},"artists":{},"albumArtists":{},"album":{},"duration":{},"meta":{},"onSuccess":{"$ref":"#/definitions/FlowControlTerm"},"onFailure":{"$ref":"#/definitions/FlowControlTerm"},"onSkip":{"$ref":"#/definitions/FlowControlTerm"},"failureReturnPartial":{"type":"boolean"},"type":{"type":"string"},"name":{"type":"string"},"stageHash":{"type":"string"}},"required":["type"]}],"title":"PlayTransformParts<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm),MaybeStageTyped>"},"WhenConditionsConfig":{"$ref":"#/definitions/WhenConditions%3Cstring%3E","title":"WhenConditionsConfig"},"WhenConditions":{"type":"array","items":{"$ref":"#/definitions/WhenParts%3Cstring%3E"},"title":"WhenConditions"},"WhenParts":{"$ref":"#/definitions/PlayTransformPartsAtomic%3Cstring%3E","title":"WhenParts"},"PlayTransformPartsAtomic":{"type":"object","properties":{"title":{"type":"string"},"artists":{"type":"string"},"albumArtists":{"type":"string"},"album":{"type":"string"},"duration":{"type":"string"},"meta":{"type":"string"}},"title":"PlayTransformPartsAtomic"},"Whennable":{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"}},"title":"Whennable"},"FlowControlTerm":{"type":"string","enum":["continue","stop"],"title":"FlowControlTerm"},"StageTypeMetadata":{"type":"string","enum":["spotify","musicbrainz","native"],"title":"StageTypeMetadata"},"SearchAndReplaceTerm":{"anyOf":[{"type":"string"},{"$ref":"#/definitions/ConditionalSearchAndReplaceTerm"}],"title":"SearchAndReplaceTerm"},"ConditionalSearchAndReplaceTerm":{"$ref":"#/definitions/ConditionalSearchAndReplaceRegExp","title":"ConditionalSearchAndReplaceTerm"},"ConditionalSearchAndReplaceRegExp":{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"search":{"anyOf":[{"type":"string"},{"type":"string","format":"regex"}],"description":"The search value to test for\n\nCan be a normal string (converted to a case-sensitive literal) or a valid regular expression as a string, or an actual RegExp object","examples":[["find this string","/some string*/ig"]]},"replace":{"type":"string","description":"The replacement string/value to use when search is found\n\nThis can be a literal string like `'replace with this`, an empty string to remove the search value (`''`), or a special regex value\n\nSee replacement here for more information: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace"},"test":{"$comment":"(obj: SearchAndReplaceRegExp) => boolean","type":"object","properties":{"namedArgs":{"type":"object","properties":{"obj":{"$ref":"#/definitions/SearchAndReplaceRegExp"}},"required":["obj"],"additionalProperties":false}},"description":"An optional function to execute before running this search-and-replace that decides if it should run at all"}},"required":["replace","search"],"title":"ConditionalSearchAndReplaceRegExp"},"SearchAndReplaceRegExp":{"type":"object","properties":{"search":{"anyOf":[{"type":"string"},{"type":"string","format":"regex"}],"description":"The search value to test for\n\nCan be a normal string (converted to a case-sensitive literal) or a valid regular expression as a string, or an actual RegExp object","examples":[["find this string","/some string*/ig"]]},"replace":{"type":"string","description":"The replacement string/value to use when search is found\n\nThis can be a literal string like `'replace with this`, an empty string to remove the search value (`''`), or a special regex value\n\nSee replacement here for more information: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace"},"test":{"$comment":"(obj: SearchAndReplaceRegExp) => boolean","type":"object","properties":{"namedArgs":{"type":"object","properties":{"obj":{"$ref":"#/definitions/SearchAndReplaceRegExp"}},"required":["obj"],"additionalProperties":false}},"description":"An optional function to execute before running this search-and-replace that decides if it should run at all"}},"required":["search","replace"],"title":"SearchAndReplaceRegExp"},"ExternalMetadataTerm":{"anyOf":[{"type":"boolean"},{"not":{}},{"$ref":"#/definitions/Whennable"}],"title":"ExternalMetadataTerm"},"StageTypeUser":{"type":"string","enum":["user"],"title":"StageTypeUser"},"PlexApiSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/PlexApiData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/PlexApiOptions"}},"required":["data"],"title":"PlexApiSourceConfig"},"PlexApiData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"token":{"type":"string"},"url":{"type":"string","description":"http(s)://HOST:PORT of the Plex server to connect to"},"usersAllow":{"anyOf":[{"type":"string"},{"type":"boolean","enum":[true]},{"type":"array","items":{"type":"string"}}],"description":"Only scrobble for specific users (case-insensitive)\n\nIf `true` MS will scrobble activity from all users"},"usersBlock":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Do not scrobble for these users (case-insensitive)"},"devicesAllow":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Only scrobble if device or application name contains strings from this list (case-insensitive)"},"devicesBlock":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Do not scrobble if device or application name contains strings from this list (case-insensitive)"},"librariesAllow":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Only scrobble if library name contains string from this list (case-insensitive)"},"librariesBlock":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Do not scrobble if library name contains strings from this list (case-insensitive)"}},"required":["url"],"title":"PlexApiData"},"PlexApiOptions":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"},"ignoreInvalidCert":{"type":"boolean","description":"Ignore invalid cert errors when connecting to Plex\n\nUseful for Plex servers using \"Required\" Secure Connections with self-signed certificates\n\nDo not enable unless you know you need this.","default":false}},"title":"PlexApiOptions"},"DeezerSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/DeezerData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"}},"required":["data"],"title":"DeezerSourceConfig"},"DeezerData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"clientId":{"type":"string","description":"deezer client id","examples":["a89cba1569901a0671d5a9875fed4be1"]},"clientSecret":{"type":"string","description":"deezer client secret","examples":["ec42e09d5ae0ee0f0816ca151008412a"]},"redirectUri":{"type":"string","description":"deezer redirect URI -- required only if not the default shown here. URI must end in \"callback\"","default":"http://localhost:9078/deezer/callback","examples":["http://localhost:9078/deezer/callback"]}},"required":["clientId","clientSecret"],"title":"DeezerData"},"DeezerInternalSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/DeezerInternalData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/DeezerInternalSourceOptions"}},"required":["data"],"title":"DeezerInternalSourceConfig"},"DeezerInternalData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"arl":{"type":"string","description":"ARL retrieved from Deezer response header"},"userAgent":{"type":"string","description":"User agent","default":"Mozilla/5.0 (X11; Linux i686; rv:135.0) Gecko/20100101 Firefox/135.0"}},"required":["arl"],"title":"DeezerInternalData"},"DeezerInternalSourceOptions":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"},"fuzzyDiscoveryIgnore":{"anyOf":[{"type":"boolean"},{"type":"string","enum":["aggressive"]}]}},"title":"DeezerInternalSourceOptions"},"ListenbrainzEndpointSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/ListenbrainzEndpointData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"}},"title":"ListenbrainzEndpointSourceConfig"},"ListenbrainzEndpointData":{"type":"object","properties":{"slug":{"type":["string","null"],"description":"The URL ending that should be used to identify scrobbles for this source\n\nIf you are using multiple Listenbrainz endpoint sources (scrobbles for many users) you can use a slug to match Sources with individual users/origins\n\nExample:\n\n* slug: 'usera' => API URL: http://localhost:9078/api/listenbrainz/usera\n* slug: 'originb' => API URL: http://localhost:9078/api/listenbrainz/originb\n\nIf no slug is found from an extension's incoming webhook event the first Listenbrainz source without a slug will be used"},"token":{"type":["string","null"],"description":"If an LZ submission request contains this token in the Authorization Header it will be used to match the submission with this Source\n\nSee: https://listenbrainz.readthedocs.io/en/latest/users/api/index.html#add-the-user-token-to-your-requests"}},"title":"ListenbrainzEndpointData"},"LastFMEndpointSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/LastFMEndpointData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"}},"title":"LastFMEndpointSourceConfig"},"LastFMEndpointData":{"type":"object","properties":{"slug":{"type":["string","null"],"description":"The URL ending that should be used to identify scrobbles for this source\n\nIf you are using multiple Last.fm endpoint sources (scrobbles for many users) you can use a slug to match Sources with individual users/origins\n\nExample:\n\n* slug: 'usera' => API URL: http://localhost:9078/api/lastfm/usera\n* slug: 'originb' => API URL: http://localhost:9078/api/lastfm/originb\n\nIf no slug is found from an extension's incoming webhook event the first Last.fm source without a slug will be used"}},"title":"LastFMEndpointData"},"SubSonicSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/SubsonicData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"}},"required":["data"],"title":"SubSonicSourceConfig"},"SubsonicData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"url":{"type":"string","description":"URL of the subsonic media server to query","examples":["http://airsonic.local"]},"user":{"type":"string","description":"Username to login to the server with","examples":[["MyUser"]]},"password":{"type":"string","description":"Password for the user to login to the server with","examples":["MyPassword"]},"ignoreTlsErrors":{"type":"boolean","description":"If your subsonic server is using self-signed certs you may need to disable TLS errors in order to get a connection\n\nWARNING: This should be used with caution as your traffic may not be encrypted.","default":false},"legacyAuthentication":{"type":"boolean","description":"Older Subsonic versions, and some badly implemented servers (Nextcloud), use legacy authentication which sends your password in CLEAR TEXT. This is less secure than the newer, recommended hashing authentication method but in some cases it is needed. See \"Authentication\" section here => https://www.subsonic.org/pages/api.jsp\n\nIf this option is not specified it will be turned on if the subsonic server responds with error code 41 \"Token authentication not supported for LDAP users.\" -- See Error Handling section => https://www.subsonic.org/pages/api.jsp","default":false},"usersAllow":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Only scrobble for specific users (case-insensitive)\n\nIf undefined or an empty string/list MS will scrobble activity from all users"}},"required":["url","user","password"],"title":"SubsonicData"},"JellyApiSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/JellyApiData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/JellyApiOptions"}},"required":["data","options"],"title":"JellyApiSourceConfig"},"JellyApiData":{"type":"object","properties":{"url":{"type":"string","description":"HOST:PORT of the Jellyfin server to connect to"},"user":{"type":"string","description":"The username of the user to authenticate for or track scrobbles for"},"password":{"type":"string","description":"Password of the username to authenticate for\n\nRequired if `apiKey` is not provided."},"apiKey":{"type":"string","description":"API Key to authenticate with.\n\nRequired if `password` is not provided."},"usersAllow":{"anyOf":[{"type":"string"},{"type":"boolean","enum":[true]},{"type":"array","items":{"type":"string"}}],"description":"Only scrobble for specific users (case-insensitive)\n\nIf `true` MS will scrobble activity from all users"},"usersBlock":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Do not scrobble for these users (case-insensitive)"},"devicesAllow":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Only scrobble if device or application name contains strings from this list (case-insensitive)"},"devicesBlock":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Do not scrobble if device or application name contains strings from this list (case-insensitive)"},"librariesAllow":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Only scrobble if library name contains string from this list (case-insensitive)"},"librariesBlock":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Do not scrobble if library name contains strings from this list (case-insensitive)"},"additionalAllowedLibraryTypes":{"type":"array","items":{},"description":"Allow MS to scrobble audio media in libraries classified other than 'music'\n\n`librariesAllow` will achieve the same result as this but this is more convenient if you do not want to explicitly list every library name or are only using `librariesBlock`"},"allowUnknown":{"type":"boolean","description":"Force media with a type of \"Unknown\" to be counted as Audio","default":false},"frontendUrlOverride":{"type":"string","description":"HOST:PORT of the Jellyfin server that your browser will be able to access from the frontend (and thus load images and links from)\nIf unspecified it will use the normal server HOST and PORT from the `url`\nNecessary if you are using a reverse proxy or other network configuration that prevents the frontend from accessing the server directly\n\nENV: JELLYFIN_FRONTEND_URL_OVERRIDE"}},"required":["url","user"],"title":"JellyApiData"},"JellyApiOptions":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"JellyApiOptions"},"LastfmSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/LastFmSourceData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"configureAs":{"type":"string","enum":["source"],"description":"When used in `lastfm.config` this tells multi-scrobbler whether to use this data to configure a source or client.","default":"source","examples":["source"]}},"required":["data"],"title":"LastfmSourceConfig"},"LastFmSourceData":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"apiKey":{"type":"string","description":"API Key generated from Last.fm/Libre.fm account","examples":["787c921a2a2ab42320831aba0c8f2fc2"]},"secret":{"type":"string","description":"Secret generated from Last.fm/Libre.fm account","examples":["ec42e09d5ae0ee0f0816ca151008412a"]},"session":{"type":"string","description":"Optional session id returned from a completed auth flow"},"redirectUri":{"type":"string","description":"Optional URI to use for callback. Specify this if callback should be different than the default. MUST have \"lastfm/callback\" in the URL somewhere.","default":"http://localhost:9078/lastfm/callback","examples":["http://localhost:9078/lastfm/callback"]},"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"}},"required":["apiKey","secret"],"title":"LastFmSourceData"},"LibrefmSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/LibrefmData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"configureAs":{"type":"string","enum":["source"],"description":"When used in `librefm.config` this tells multi-scrobbler whether to use this data to configure a source or client.","default":"source","examples":["source"]}},"required":["data"],"title":"LibrefmSourceConfig"},"LibrefmData":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"apiKey":{"type":"string","description":"Optional Secret for Libre.fm account\n\nThis can be anything, or it will be generated by multi-scrobbler","examples":["anyValue"]},"secret":{"type":"string","description":"Optional Secret for Libre.fm account\n\nThis can be anything, or it will be generated by multi-scrobbler","examples":["anyValue"]},"session":{"type":"string","description":"Optional session id returned from a completed auth flow"},"path":{"type":"string"},"urlBase":{"type":"string","description":"(Optional) The host and path prefix for your Libre.fm instance","default":"https://libre.fm/2.0/"},"redirectUri":{"type":"string","description":"Optional URI to use for callback. Specify this if callback should be different than the default. MUST have \"librefm/callback\" in the URL somewhere.","default":"http://localhost:9078/librefm/callback","examples":["http://localhost:9078/librefm/callback"]}},"title":"LibrefmData"},"YTMusicSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/YTMusicData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"type":"object","properties":{"logAuth":{"type":"boolean","description":"When true MS will log to DEBUG all of the credentials data it receives from YTM"},"logDiff":{"type":"boolean","description":"Always log history diff\n\nBy default MS will log to `WARN` if history diff is inconsistent but does not log if diff is expected (on new tracks found)\nSet this to `true` to ALWAYS log diff on new tracks. Expected diffs will log to `DEBUG` and inconsistent diffs will continue to log to `WARN`","default":false},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}}}},"title":"YTMusicSourceConfig"},"YTMusicData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"cookie":{"type":"string","description":"The cookie retrieved from the Request Headers of music.youtube.com after logging in.\n\nSee https://ytmusicapi.readthedocs.io/en/stable/setup/browser.html#copy-authentication-headers for how to retrieve this value.","examples":["VISITOR_INFO1_LIVE=jMp2xA1Xz2_PbVc; __Secure-3PAPISID=3AxsXpy0M/AkISpjek; ..."]},"clientId":{"type":"string","description":"Google Cloud Console project OAuth Client ID\n\nGenerated from a custom OAuth Client, see docs"},"clientSecret":{"type":"string","description":"Google Cloud Console project OAuth Client Secret\n\nGenerated from a custom OAuth Client, see docs"},"redirectUri":{"type":"string","description":"Google Cloud Console project OAuth Client Authorized redirect URI\n\nGenerated from a custom OAuth Client, see docs. multi-scrobbler will generate a default based on BASE_URL.\nOnly specify this if the default does not work for you."},"innertubeOptions":{"$ref":"#/definitions/InnertubeOptions","description":"Additional options for authorization and tailoring YTM client"}},"title":"YTMusicData"},"InnertubeOptions":{"type":"object","properties":{"po_token":{"type":"string","description":"Proof of Origin token\n\nMay be required if YTM starts returning 403"},"visitor_data":{"type":"string","description":"Visitor ID value found in VISITOR_INFO1_LIVE or visitorData cookie\n\nMay be required if YTM starts returning 403"},"account_index":{"type":"number","description":"If account login results in being able to choose multiple account, use a zero-based index to choose which one to monitor","examples":[0,1]},"location":{"type":"string"},"lang":{"type":"string"},"generate_session_locally":{"type":"boolean"},"device_category":{"type":"string"},"client_type":{"type":"string"},"timezone":{"type":"string"}},"title":"InnertubeOptions"},"MPRISSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/MPRISData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"}},"required":["data"],"title":"MPRISSourceConfig"},"MPRISData":{"type":"object","properties":{"blacklist":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"DO NOT scrobble from any players that START WITH these values, case-insensitive","examples":[["spotify","vlc"]]},"whitelist":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"ONLY from any players that START WITH these values, case-insensitive\n\nIf whitelist is present then blacklist is ignored","examples":[["spotify","vlc"]]}},"title":"MPRISData"},"MopidySourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/MopidyData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"}},"required":["data"],"title":"MopidySourceConfig"},"MopidyData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"url":{"type":"string","description":"URL of the Mopidy HTTP server to connect to\n\nYou MUST have Mopidy-HTTP extension enabled: https://mopidy.com/ext/http\n\nmulti-scrobbler connects to the WebSocket endpoint that ultimately looks like this => `ws://localhost:6680/mopidy/ws/`\n\nThe URL you provide here will have all parts not explicitly defined filled in for you so if these are not the default you must define them.\n\nParts => [default value]\n\n* Protocol => `ws://`\n* Hostname => `localhost`\n* Port => `6680`\n* Path => `/mopidy/ws/`","examples":["ws://localhost:6680/mopidy/ws/"],"default":"ws://localhost:6680/mopidy/ws/"},"uriBlacklist":{"type":"array","items":{"type":"string"},"description":"Do not scrobble tracks whose URI STARTS WITH any of these strings, case-insensitive\n\nEX: Don't scrobble tracks from soundcloud by adding 'soundcloud' to this list.\n\nList is ignored if uriWhitelist is used."},"uriWhitelist":{"type":"array","items":{"type":"string"},"description":"Only scrobble tracks whose URI STARTS WITH any of these strings, case-insensitive\n\nEX: Only scrobble tracks from soundcloud by adding 'soundcloud' to this list."},"albumBlacklist":{"type":"array","items":{"type":"string"},"description":"Remove album data that matches any case-insensitive string from this list when scrobbling,\n\nFor certain sources (Soundcloud) Mopidy does not have all track info (Album) and will instead use \"Soundcloud\" as the Album name. You can prevent multi-scrobbler from using this bad Album data by adding the fake name to this list. Multi-scrobbler will still scrobble the track, just without the bad data.","examples":[["Soundcloud","Mixcloud"]],"default":["Soundcloud"]}},"title":"MopidyData"},"ListenBrainzSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/ListenBrainzSourceData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"configureAs":{"type":"string","enum":["source"],"description":"When used in `listenbrainz.config` this tells multi-scrobbler whether to use this data to configure a source or client.","default":"source","examples":["source"]}},"required":["data"],"title":"ListenBrainzSourceConfig"},"ListenBrainzSourceData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"url":{"type":"string","description":"URL for the ListenBrainz server, if not using the default","examples":["https://api.listenbrainz.org/"],"default":"https://api.listenbrainz.org/"},"token":{"type":"string","description":"User token for the user to scrobble for","examples":["6794186bf-1157-4de6-80e5-uvb411f3ea2b"]},"username":{"type":"string","description":"Username of the user to scrobble for"}},"required":["token","username"],"title":"ListenBrainzSourceData"},"JRiverSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/JRiverData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"}},"required":["data"],"title":"JRiverSourceConfig"},"JRiverData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"url":{"type":"string","description":"URL of the JRiver HTTP server to connect to\n\nmulti-scrobbler connects to the Web Service Interface endpoint that ultimately looks like this => `http://yourDomain:52199/MCWS/v1/`\n\nThe URL you provide here will have all parts not explicitly defined filled in for you so if these are not the default you must define them.\n\nParts => [default value]\n\n* Protocol => `http://`\n* Hostname => `localhost`\n* Port => `52199`\n* Path => `/MCWS/v1/`","examples":["http://localhost:52199/MCWS/v1/"],"default":"http://localhost:52199/MCWS/v1/"},"username":{"type":"string","description":"If you have enabled authentication, the username you set"},"password":{"type":"string","description":"If you have enabled authentication, the password you set"}},"required":["url"],"title":"JRiverData"},"KodiSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/KodiData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"}},"required":["data"],"title":"KodiSourceConfig"},"KodiData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"url":{"type":"string","description":"URL of the Kodi HTTP server to connect to\n\nmulti-scrobbler connects to the Web Service Interface endpoint that ultimately looks like this => `http://yourDomain:8080/jsonrpc`\n\nThe URL you provide here will have all parts not explicitly defined filled in for you so if these are not the default you must define them.\n\nParts => [default value]\n\n* Protocol => `http://`\n* Hostname => `localhost`\n* Port => `8080`\n* Path => `/jsonrpc`","examples":["http://localhost:8080/jsonrpc"],"default":"http://localhost:8080/jsonrpc"},"username":{"type":"string","description":"The username set for Remote Control via Web Sever"},"password":{"type":"string","description":"The password set for Remote Control via Web Sever"}},"required":["url","username","password"],"title":"KodiData"},"WebScrobblerSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/WebScrobblerData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"}},"title":"WebScrobblerSourceConfig"},"WebScrobblerData":{"type":"object","properties":{"slug":{"type":["string","null"],"description":"The URL ending that should be used to identify scrobbles for this source\n\nIn WebScrobbler's Webhook you must set an 'API URL'. All MS WebScrobbler sources must start like:\n\nhttp://localhost:9078/api/webscrobbler\n\nIf you are using multiple WebScrobbler sources (scrobbles for many users) you must use a slug to match Sources with each users extension.\n\nExample:\n\n* slug: 'usera' => API URL: http://localhost:9078/api/webscrobbler/usera\n* slug: 'userb' => API URL: http://localhost:9078/api/webscrobbler/userb\n\nIf no slug is found from an extension's incoming webhook event the first WebScrobbler source without a slug will be used"},"blacklist":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Block scrobbling from specific WebScrobbler Connectors","examples":[["youtube"]]},"whitelist":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Only allow scrobbling from specific WebScrobbler Connectors","examples":[["mixcloud","soundcloud","bandcamp"]]}},"title":"WebScrobblerData"},"ChromecastSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/ChromecastData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"}},"required":["data"],"title":"ChromecastSourceConfig"},"ChromecastData":{"type":"object","properties":{"blacklistDevices":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"DO NOT scrobble from any cast devices that START WITH these values, case-insensitive\n\nUseful when used with auto discovery","examples":[["home-mini","family-tv"]]},"whitelistDevices":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"ONLY scrobble from any cast device that START WITH these values, case-insensitive\n\nIf whitelist is present then blacklist is ignored\n\nUseful when used with auto discovery","examples":[["home-mini","family-tv"]]},"blacklistApps":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"DO NOT scrobble from any application that START WITH these values, case-insensitive","examples":[["spotify","pandora"]]},"whitelistApps":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"ONLY scrobble from any application that START WITH these values, case-insensitive\n\nIf whitelist is present then blacklist is ignored","examples":[["spotify","pandora"]]},"useAvahi":{"type":"boolean","description":"Try to use Avahi and avahi-browse to resolve mDNS devices instead of native mDNS querying\n\nUseful for docker (alpine) container where mDNS resolution is not yet supported. Avahi socket must be exposed to the container and avahi-tools must be installed.","default":false},"useAutoDiscovery":{"type":"boolean","description":"Use mDNS to discovery Google Cast devices on your next automatically?\n\nIf not explicitly set then it is TRUE if `devices` is not set"},"devices":{"type":"array","items":{"$ref":"#/definitions/ChromecastDeviceInfo"},"description":"A list of Google Cast devices to monitor\n\nIf this is used then `useAutoDiscovery` is set to FALSE, if not explicitly set"},"allowUnknownMedia":{"anyOf":[{"type":"boolean"},{"type":"array","items":{"type":"string"}}],"description":"Chromecast Apps report a \"media type\" in the status info returned for whatever is currently playing\n\n* If set to TRUE then Music AND Generic/Unknown media will be tracked for ALL APPS\n* If set to FALSE then only media explicitly typed as Music will be tracked for ALL APPS\n* If set to a list then only Apps whose name contain one of these values, case-insensitive, will have Music AND Generic/Unknown tracked\n\nSee https://developers.google.com/cast/docs/media/messages#MediaInformation \"metadata\" property","default":false},"forceMediaRecognitionOn":{"type":"array","items":{"type":"string"},"description":"Media provided by any App whose name is listed here will ALWAYS be tracked, regardless of the \"media type\" reported\n\nApps will be recognized if they CONTAIN any of these values, case-insensitive"}},"title":"ChromecastData"},"ChromecastDeviceInfo":{"type":"object","properties":{"name":{"type":"string","description":"A friendly name to identify this device","examples":["MySmartTV"]},"address":{"type":"string","description":"The IP address of the device","examples":["192.168.0.115"]}},"required":["name","address"],"title":"ChromecastDeviceInfo"},"MalojaSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/MalojaSourceData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"configureAs":{"type":"string","enum":["source"],"description":"When used in `maloja.config` this tells multi-scrobbler whether to use this data to configure a source or client.","default":"source","examples":["source"]}},"required":["data"],"title":"MalojaSourceConfig"},"MalojaSourceData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"url":{"type":"string","description":"URL for maloja server","examples":["http://localhost:42010"]},"apiKey":{"type":"string","description":"API Key for Maloja server","examples":["myApiKey"]}},"required":["apiKey","url"],"title":"MalojaSourceData"},"MusikcubeSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/MusikcubeData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"}},"required":["data"],"title":"MusikcubeSourceConfig"},"MusikcubeData":{"type":"object","properties":{"url":{"type":"string","description":"URL of the Musikcube Websocket (Metadata) server to connect to\n\nYou MUST have enabled 'metadata' server and set a password: https://github.com/clangen/musikcube/wiki/remote-api-documentation\n * musikcube -> settings -> server setup\n\nThe URL you provide here will have all parts not explicitly defined filled in for you so if these are not the default you must define them.\n\nParts => [default value]\n\n* Protocol => `ws://`\n* Hostname => `localhost`\n* Port => `7905`","examples":["ws://localhost:7905"],"default":"ws://localhost:7905"},"password":{"type":"string","description":"Password set in Musikcube https://github.com/clangen/musikcube/wiki/remote-api-documentation\n\n* musikcube -> settings -> server setup -> password"},"device_id":{"type":"string"}},"required":["password"],"title":"MusikcubeData"},"MusicCastSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/MusicCastData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"}},"required":["data"],"title":"MusicCastSourceConfig"},"MusicCastData":{"type":"object","properties":{"url":{"type":"string","description":"The host or URL of the YamahaExtendedControl endpoint to use","examples":[["192.168.0.101","http://192.168.0.101/YamahaExtendedControl"]]}},"required":["url"],"title":"MusicCastData"},"MPDSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/MPDData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/MPDSourceOptions"}},"required":["data","options"],"title":"MPDSourceConfig"},"MPDData":{"type":"object","properties":{"url":{"type":"string","description":"URL:PORT of the MPD server to connect to\n\nTo use this you must have TCP connections enabled for your MPD server https://mpd.readthedocs.io/en/stable/user.html#client-connections","examples":["localhost:6600"],"default":"localhost:6600"},"path":{"type":"string","description":"If using socket specify the path instead of url.\n\ntrailing `~` is replaced by your home directory"},"password":{"type":"string","description":"Password for the server, if set https://mpd.readthedocs.io/en/stable/user.html#permissions-and-passwords"}},"title":"MPDData"},"MPDSourceOptions":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"MPDSourceOptions"},"VLCSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/VLCData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/VLCSourceOptions"}},"required":["data"],"title":"VLCSourceConfig"},"VLCData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"url":{"type":"string","description":"URL:PORT of the VLC server to connect to\n\nTo use this you must have the Web (http) interface module enabled and a password set https://foxxmd.github.io/multi-scrobbler/docs/configuration#vlc","examples":["localhost:8080"],"default":"localhost:8080"},"password":{"type":"string","description":"Password for the server"}},"required":["password"],"title":"VLCData"},"VLCSourceOptions":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"},"filenamePatterns":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"A list of regular expressions to use to extract metadata (title, album, artist) from a filename\n\nUsed when VLC reports only the filename for the current audio track"},"logFilenamePatterns":{"type":"boolean","description":"Log to DEBUG when a filename-only track is matched or not matched by filenamePatterns","default":false},"dumpVlcMetadata":{"type":"boolean","description":"Dump all the metadata VLC reports for an audio track to DEBUG.\n\nUse this if reporting an issue with VLC not correctly capturing metadata for a track.","default":false}},"title":"VLCSourceOptions"},"IcecastSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/IcecastData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/IcecastSourceOptions"}},"required":["data"],"title":"IcecastSourceConfig"},"IcecastData":{"type":"object","properties":{"sources":{"type":"array","items":{"$ref":"#/definitions/IcecastSource"}},"icestatsEndpoint":{"type":"string"},"statsEndpoint":{"type":"string"},"nextsongsEndpoint":{"type":"string"},"sevenhtmlEndpoint":{"type":"string"},"icyMetaInt":{"type":"number"},"url":{"type":"string","description":"The Icecast stream URL"}},"required":["url"],"title":"IcecastData"},"IcecastSource":{"type":"string","enum":["icy","ogg","icestats","stats","sevenhtml","nextsongs"],"title":"IcecastSource"},"IcecastSourceOptions":{"type":"object","properties":{"systemScrobble":{"type":"boolean","description":"For Sources that support manual listening, should MS default to scrobbling when no user interaction has occurred?\n\nIf not specified MS will use a Source's specific behavior, see Source's documentation."},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"IcecastSourceOptions"},"AzuracastSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/AzuracastData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"}},"required":["data"],"title":"AzuracastSourceConfig"},"AzuracastData":{"type":"object","properties":{"url":{"type":"string","description":"Base URL of the Azuracast instance\n\nThis does NOT include the station. If a station is included it will be ignored. Use `station` field to specify station, if necessary","examples":["https://radio.mydomain.tld","http://localhost:80"]},"station":{"type":"string","description":"The specific station to monitor\n\nScrobbling will only occur if any of the monitor conditions are met AND the station is ONLINE.\n\nTo monitor multiple stations create a Source for each station.","examples":["my-station-1"]},"monitorWhenListeners":{"type":["boolean","number"],"description":"Only activate scrobble monitoring if station\n\n* `true` => has any current listeners\n* `number` => has EQUAL TO or MORE THAN X number of listeners"},"monitorWhenLive":{"type":"boolean","description":"Only activate scrobble monitoring if station has a live DJ/Streamer","default":true},"apiKey":{"type":"string","description":"API Key used to access data about private streams\n\nhttps://www.azuracast.com/docs/developers/apis/#api-authentication"}},"required":["url","station"],"title":"AzuracastData"},"KoitoSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/KoitoSourceData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"configureAs":{"type":"string","enum":["source"],"description":"When used in `koito.config` this tells multi-scrobbler whether to use this data to configure a source or client.","default":"source","examples":["source"]}},"required":["data"],"title":"KoitoSourceConfig"},"KoitoSourceData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"url":{"type":"string","description":"URL for the Koito server","examples":["http://192.168.0.100:4110"]},"token":{"type":"string","description":"User token for the user to scrobble for","examples":["pM195xPV98CDpk0QW47FIIOR8AKATAX5DblBF-Jq0t1MbbKL"]},"username":{"type":"string","description":"Username of the user to scrobble for"}},"required":["token","url","username"],"title":"KoitoSourceData"},"TealSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/TealSourceData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/TealSourceOptions"},"configureAs":{"type":"string","enum":["source"],"description":"Should always be `souce` when using Tealfm as a Source","default":"source","examples":["source"]}},"required":["data"],"title":"TealSourceConfig"},"TealSourceData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"baseUri":{"type":"string","description":"The base URI of the Multi-Scrobbler to use for ATProto OAuth\n\nOnly include this if you want to use OAuth. The URI must be a non-IP/non-local domain using https: protocol."},"identifier":{"type":"string","description":"Identify the account to login as\n\n* For **App Password** Auth - your email\n* For **Oauth** - your handle minus the @"},"appPassword":{"type":"string","description":"The [App Password](https://atproto.com/specs/xrpc#app-passwords) you created for your account\n\nThis is created under https://bsky.app/settings/app-passwords\n\n**Use this if you are self-hosting Multi-Scrobbler on localhost or accessed like http://IP:PORT**"},"serviceAllow":{"type":"array","items":{"type":"string"}},"serviceDeny":{"type":"array","items":{"type":"string"}}},"required":["identifier"],"title":"TealSourceData"},"TealSourceOptions":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"TealSourceOptions"},"RockskySourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/RockskySourceData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/RockskySourceOptions"},"configureAs":{"type":"string","enum":["source"],"description":"When used in `rocksky.config` this tells multi-scrobbler whether to use this data to configure a source or client.","default":"source","examples":["source"]}},"required":["data"],"title":"RockskySourceConfig"},"RockskySourceData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"key":{"type":"string","description":"API Key generated from [API Applications](https://docs.rocksky.app/migrating-from-listenbrainz-to-rocksky-1040189m0) in Rocksky for your account","examples":["6794186bf-1157-4de6-80e5-uvb411f3ea2b"]},"handle":{"type":"string","description":"The **fully-qualified** handle for your ATPRoto/Bluesky account, like:\n\n* alice.bsky.social\n* foxxmd.com\n* mysuer.blacksky.app"}},"required":["handle","key"],"title":"RockskySourceData"},"RockskySourceOptions":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"},"audioScrobblerUrl":{"type":"string","description":"URL for the Rocksky *Listenbrainz* endpoint, if not using the default","examples":["https://audioscrobbler.rocksky.app"],"default":"https://audioscrobbler.rocksky.app"},"apiUrl":{"type":"string","description":"URL for the Rocksky *API* endpoint, if not using the default","examples":["https://api.rocksky.app"],"default":"https://api.rocksky.app"}},"title":"RockskySourceOptions"}}} \ No newline at end of file +{"$schema":"http://json-schema.org/draft-07/schema#","anyOf":[{"$ref":"#/definitions/SpotifySourceConfig"},{"$ref":"#/definitions/PlexApiSourceConfig"},{"$ref":"#/definitions/DeezerSourceConfig"},{"$ref":"#/definitions/DeezerInternalSourceConfig"},{"$ref":"#/definitions/ListenbrainzEndpointSourceConfig"},{"$ref":"#/definitions/LastFMEndpointSourceConfig"},{"$ref":"#/definitions/SubSonicSourceConfig"},{"$ref":"#/definitions/JellyApiSourceConfig"},{"$ref":"#/definitions/LastfmSourceConfig"},{"$ref":"#/definitions/LibrefmSourceConfig"},{"$ref":"#/definitions/YTMusicSourceConfig"},{"$ref":"#/definitions/MPRISSourceConfig"},{"$ref":"#/definitions/MopidySourceConfig"},{"$ref":"#/definitions/ListenBrainzSourceConfig"},{"$ref":"#/definitions/JRiverSourceConfig"},{"$ref":"#/definitions/KodiSourceConfig"},{"$ref":"#/definitions/WebScrobblerSourceConfig"},{"$ref":"#/definitions/ChromecastSourceConfig"},{"$ref":"#/definitions/MalojaSourceConfig"},{"$ref":"#/definitions/MusikcubeSourceConfig"},{"$ref":"#/definitions/MusicCastSourceConfig"},{"$ref":"#/definitions/MPDSourceConfig"},{"$ref":"#/definitions/VLCSourceConfig"},{"$ref":"#/definitions/IcecastSourceConfig"},{"$ref":"#/definitions/AzuracastSourceConfig"},{"$ref":"#/definitions/KoitoSourceConfig"},{"$ref":"#/definitions/TealSourceConfig"},{"$ref":"#/definitions/RockskySourceConfig"},{"$ref":"#/definitions/SonosSourceConfig"}],"definitions":{"SpotifySourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/SpotifySourceData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"}},"required":["data"],"title":"SpotifySourceConfig"},"SpotifySourceData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)\n\nIt is unlikely you should need to change this unless you scrobble many very short tracks often\n\nReading:\n* https://developer.spotify.com/documentation/web-api/guides/rate-limits/\n* https://medium.com/mendix/limiting-your-amount-of-calls-in-mendix-most-of-the-time-rest-835dde55b10e\n * Rate limit may ~180 req/min\n* https://community.spotify.com/t5/Spotify-for-Developers/Web-API-ratelimit/m-p/5503150/highlight/true#M7930\n * Informally indicated as 20 req/sec? Probably for burstiness","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"clientId":{"type":"string","description":"spotify client id","examples":["787c921a2a2ab42320831aba0c8f2fc2"]},"clientSecret":{"type":"string","description":"spotify client secret","examples":["ec42e09d5ae0ee0f0816ca151008412a"]},"redirectUri":{"type":"string","description":"spotify redirect URI -- required only if not the default shown here. URI must end in \"callback\"","default":"http://localhost:9078/callback","examples":["http://localhost:9078/callback"]}},"required":["clientId","clientSecret"],"title":"SpotifySourceData"},"CommonSourceOptions":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"CommonSourceOptions"},"LogLevel":{"type":"string","enum":["silent","fatal","error","warn","info","log","verbose","debug","trace"],"description":"Names of log levels that can be invoked on the logger\n\nFrom lowest to highest:\n\n* `trace`\n* `debug`\n* `verbose`\n* `log`\n* `info`\n* `warn`\n* `error`\n* `fatal`\n* `silent` (will never output anything)\n\nWhen used in `LogOptions` specifies the **minimum** level the output should log at.","title":"LogLevel"},"FileLogOptions":{"type":"object","properties":{"timestamp":{"type":"string","enum":["unix","iso","auto"],"description":"For rolling log files\n\nWhen\n* value passed to rolling destination is a string (`path` from LogOptions is a string) and\n* `frequency` is defined\n\nThis determines the format of the datetime inserted into the log file name:\n\n* `unix` - unix epoch timestamp in milliseconds\n* `iso` - Full [ISO8601](https://en.wikipedia.org/wiki/ISO_8601) datetime IE '2024-03-07T20:11:34Z'\n* `auto`\n * When frequency is `daily` only inserts date IE YYYY-MM-DD\n * Otherwise inserts full ISO8601 datetime","default":"auto"},"size":{"type":["number","string"],"description":"The maximum size of a given rolling log file.\n\nCan be combined with frequency. Use k, m and g to express values in KB, MB or GB.\n\nNumerical values will be considered as MB.","default":"10MB"},"frequency":{"anyOf":[{"type":"string","enum":["daily"]},{"type":"string","enum":["hourly"]},{"type":"number"}],"description":"The amount of time a given rolling log file is used. Can be combined with size.\n\nUse `daily` or `hourly` to rotate file every day (or every hour). Existing file within the current day (or hour) will be re-used.\n\nNumerical values will be considered as a number of milliseconds. Using a numerical value will always create a new file upon startup.","default":"daily"},"path":{"anyOf":[{"type":"string"},{"$comment":"() => string"}],"description":"The path and filename to use for log files.\n\nIf using rolling files the filename will be appended with `.N` (a number) BEFORE the extension based on rolling status.\n\nMay also be specified using env LOG_PATH or a function that returns a string.\n\nIf path is relative the absolute path will be derived from `logBaseDir` (in `LoggerAppExtras`) which defaults to CWD","default":"./logs/app.log"},"level":{"anyOf":[{"$ref":"#/definitions/LogLevel"},{"type":"boolean","const":false}],"description":"Specify the minimum log level to output to rotating files. If `false` no log files will be created."}},"title":"FileLogOptions"},"ScrobbleThresholds":{"type":"object","properties":{"duration":{"type":["number","null"],"description":"The number of seconds a track has been listened to before it should be considered scrobbled.\n\nSet to null to disable.","default":240,"examples":[240]},"percent":{"type":["number","null"],"description":"The percentage (as an integer) of a track that should have been seen played before it should be scrobbled. Only used if the Source provides information about how long the track is.\n\nSet to null to disable.\n\nNOTE: This should be used with care when the Source is a \"polling\" type (has an 'interval' property). If the track is short and the interval is too high MS may ignore the track if percentage is high because it had not \"seen\" the track for long enough from first discovery, even if you have been playing the track for longer.","default":50,"examples":[50]}},"title":"ScrobbleThresholds"},"PlayTransformOptions":{"type":"object","properties":{"log":{"anyOf":[{"type":"boolean"},{"type":"string","enum":["all"]}]},"preCompare":{"$ref":"#/definitions/PlayTransformPartsConfig%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%3E"},"compare":{"type":"object","properties":{"candidate":{"$ref":"#/definitions/PlayTransformPartsConfig%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%3E"},"existing":{"$ref":"#/definitions/PlayTransformPartsConfig%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%3E"}}},"postCompare":{"$ref":"#/definitions/PlayTransformPartsConfig%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%3E"}},"title":"PlayTransformOptions"},"PlayTransformPartsConfig<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm)>":{"anyOf":[{"$ref":"#/definitions/PlayTransformPartsArray%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%2CMaybeStageTyped%3E"},{"$ref":"#/definitions/PlayTransformParts%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%2CMaybeStageTyped%3E"}],"description":"Represents the weakly-defined user config. May be an array of parts or one parts object","title":"PlayTransformPartsConfig<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm)>"},"PlayTransformPartsArray<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm),MaybeStageTyped>":{"type":"array","items":{"$ref":"#/definitions/PlayTransformParts%3C(def-alias-617285649-262-339-617285649-0-4937%5B%5D%7CExternalMetadataTerm)%2CMaybeStageTyped%3E"},"title":"PlayTransformPartsArray<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm),MaybeStageTyped>"},"PlayTransformParts<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm),MaybeStageTyped>":{"anyOf":[{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"title":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"artists":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"albumArtists":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"album":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"duration":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"meta":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"onSuccess":{"$ref":"#/definitions/FlowControlTerm"},"onFailure":{"$ref":"#/definitions/FlowControlTerm"},"onSkip":{"$ref":"#/definitions/FlowControlTerm"},"failureReturnPartial":{"type":"boolean"},"type":{"$ref":"#/definitions/StageTypeMetadata"},"name":{"type":"string"},"stageHash":{"type":"string"},"score":{"type":"number"}},"required":["type"]},{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"title":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"artists":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"albumArtists":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"album":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"duration":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"meta":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"onSuccess":{"$ref":"#/definitions/FlowControlTerm"},"onFailure":{"$ref":"#/definitions/FlowControlTerm"},"onSkip":{"$ref":"#/definitions/FlowControlTerm"},"failureReturnPartial":{"type":"boolean"},"type":{"$ref":"#/definitions/StageTypeUser"},"name":{"type":"string"},"stageHash":{"type":"string"}},"required":["type"]},{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"title":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"artists":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"albumArtists":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"album":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"duration":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"meta":{"anyOf":[{"type":"boolean"},{"$ref":"#/definitions/Whennable"}]},"onSuccess":{"$ref":"#/definitions/FlowControlTerm"},"onFailure":{"$ref":"#/definitions/FlowControlTerm"},"onSkip":{"$ref":"#/definitions/FlowControlTerm"},"failureReturnPartial":{"type":"boolean"},"type":{"type":"string","enum":["native"]},"name":{"type":"string"},"stageHash":{"type":"string"}},"required":["type"]},{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"title":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"artists":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"albumArtists":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"album":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"duration":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"meta":{"anyOf":[{"type":"array","items":{"$ref":"#/definitions/SearchAndReplaceTerm"}},{"$ref":"#/definitions/ExternalMetadataTerm"}]},"onSuccess":{"$ref":"#/definitions/FlowControlTerm"},"onFailure":{"$ref":"#/definitions/FlowControlTerm"},"onSkip":{"$ref":"#/definitions/FlowControlTerm"},"failureReturnPartial":{"type":"boolean"},"name":{"type":"string"}}},{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"title":{},"artists":{},"albumArtists":{},"album":{},"duration":{},"meta":{},"onSuccess":{"$ref":"#/definitions/FlowControlTerm"},"onFailure":{"$ref":"#/definitions/FlowControlTerm"},"onSkip":{"$ref":"#/definitions/FlowControlTerm"},"failureReturnPartial":{"type":"boolean"},"type":{"type":"string"},"name":{"type":"string"},"stageHash":{"type":"string"}},"required":["type"]}],"title":"PlayTransformParts<(def-alias-617285649-262-339-617285649-0-4937[]|ExternalMetadataTerm),MaybeStageTyped>"},"WhenConditionsConfig":{"$ref":"#/definitions/WhenConditions%3Cstring%3E","title":"WhenConditionsConfig"},"WhenConditions":{"type":"array","items":{"$ref":"#/definitions/WhenParts%3Cstring%3E"},"title":"WhenConditions"},"WhenParts":{"$ref":"#/definitions/PlayTransformPartsAtomic%3Cstring%3E","title":"WhenParts"},"PlayTransformPartsAtomic":{"type":"object","properties":{"title":{"type":"string"},"artists":{"type":"string"},"albumArtists":{"type":"string"},"album":{"type":"string"},"duration":{"type":"string"},"meta":{"type":"string"}},"title":"PlayTransformPartsAtomic"},"Whennable":{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"}},"title":"Whennable"},"FlowControlTerm":{"type":"string","enum":["continue","stop"],"title":"FlowControlTerm"},"StageTypeMetadata":{"type":"string","enum":["spotify","musicbrainz","native"],"title":"StageTypeMetadata"},"SearchAndReplaceTerm":{"anyOf":[{"type":"string"},{"$ref":"#/definitions/ConditionalSearchAndReplaceTerm"}],"title":"SearchAndReplaceTerm"},"ConditionalSearchAndReplaceTerm":{"$ref":"#/definitions/ConditionalSearchAndReplaceRegExp","title":"ConditionalSearchAndReplaceTerm"},"ConditionalSearchAndReplaceRegExp":{"type":"object","properties":{"when":{"$ref":"#/definitions/WhenConditionsConfig"},"search":{"anyOf":[{"type":"string"},{"type":"string","format":"regex"}],"description":"The search value to test for\n\nCan be a normal string (converted to a case-sensitive literal) or a valid regular expression as a string, or an actual RegExp object","examples":[["find this string","/some string*/ig"]]},"replace":{"type":"string","description":"The replacement string/value to use when search is found\n\nThis can be a literal string like `'replace with this`, an empty string to remove the search value (`''`), or a special regex value\n\nSee replacement here for more information: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace"},"test":{"$comment":"(obj: SearchAndReplaceRegExp) => boolean","type":"object","properties":{"namedArgs":{"type":"object","properties":{"obj":{"$ref":"#/definitions/SearchAndReplaceRegExp"}},"required":["obj"],"additionalProperties":false}},"description":"An optional function to execute before running this search-and-replace that decides if it should run at all"}},"required":["replace","search"],"title":"ConditionalSearchAndReplaceRegExp"},"SearchAndReplaceRegExp":{"type":"object","properties":{"search":{"anyOf":[{"type":"string"},{"type":"string","format":"regex"}],"description":"The search value to test for\n\nCan be a normal string (converted to a case-sensitive literal) or a valid regular expression as a string, or an actual RegExp object","examples":[["find this string","/some string*/ig"]]},"replace":{"type":"string","description":"The replacement string/value to use when search is found\n\nThis can be a literal string like `'replace with this`, an empty string to remove the search value (`''`), or a special regex value\n\nSee replacement here for more information: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace"},"test":{"$comment":"(obj: SearchAndReplaceRegExp) => boolean","type":"object","properties":{"namedArgs":{"type":"object","properties":{"obj":{"$ref":"#/definitions/SearchAndReplaceRegExp"}},"required":["obj"],"additionalProperties":false}},"description":"An optional function to execute before running this search-and-replace that decides if it should run at all"}},"required":["search","replace"],"title":"SearchAndReplaceRegExp"},"ExternalMetadataTerm":{"anyOf":[{"type":"boolean"},{"not":{}},{"$ref":"#/definitions/Whennable"}],"title":"ExternalMetadataTerm"},"StageTypeUser":{"type":"string","enum":["user"],"title":"StageTypeUser"},"PlexApiSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/PlexApiData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/PlexApiOptions"}},"required":["data"],"title":"PlexApiSourceConfig"},"PlexApiData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"token":{"type":"string"},"url":{"type":"string","description":"http(s)://HOST:PORT of the Plex server to connect to"},"usersAllow":{"anyOf":[{"type":"string"},{"type":"boolean","enum":[true]},{"type":"array","items":{"type":"string"}}],"description":"Only scrobble for specific users (case-insensitive)\n\nIf `true` MS will scrobble activity from all users"},"usersBlock":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Do not scrobble for these users (case-insensitive)"},"devicesAllow":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Only scrobble if device or application name contains strings from this list (case-insensitive)"},"devicesBlock":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Do not scrobble if device or application name contains strings from this list (case-insensitive)"},"librariesAllow":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Only scrobble if library name contains string from this list (case-insensitive)"},"librariesBlock":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Do not scrobble if library name contains strings from this list (case-insensitive)"}},"required":["url"],"title":"PlexApiData"},"PlexApiOptions":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"},"ignoreInvalidCert":{"type":"boolean","description":"Ignore invalid cert errors when connecting to Plex\n\nUseful for Plex servers using \"Required\" Secure Connections with self-signed certificates\n\nDo not enable unless you know you need this.","default":false}},"title":"PlexApiOptions"},"DeezerSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/DeezerData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"}},"required":["data"],"title":"DeezerSourceConfig"},"DeezerData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"clientId":{"type":"string","description":"deezer client id","examples":["a89cba1569901a0671d5a9875fed4be1"]},"clientSecret":{"type":"string","description":"deezer client secret","examples":["ec42e09d5ae0ee0f0816ca151008412a"]},"redirectUri":{"type":"string","description":"deezer redirect URI -- required only if not the default shown here. URI must end in \"callback\"","default":"http://localhost:9078/deezer/callback","examples":["http://localhost:9078/deezer/callback"]}},"required":["clientId","clientSecret"],"title":"DeezerData"},"DeezerInternalSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/DeezerInternalData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/DeezerInternalSourceOptions"}},"required":["data"],"title":"DeezerInternalSourceConfig"},"DeezerInternalData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"arl":{"type":"string","description":"ARL retrieved from Deezer response header"},"userAgent":{"type":"string","description":"User agent","default":"Mozilla/5.0 (X11; Linux i686; rv:135.0) Gecko/20100101 Firefox/135.0"},"accountId":{"type":"string","description":"The ID (USER_ID) of the linked account to monitor. If not set, monitors the main ARL account"}},"required":["arl"],"title":"DeezerInternalData"},"DeezerInternalSourceOptions":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"},"fuzzyDiscoveryIgnore":{"anyOf":[{"type":"boolean"},{"type":"string","enum":["aggressive"]}]}},"title":"DeezerInternalSourceOptions"},"ListenbrainzEndpointSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/ListenbrainzEndpointData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"}},"title":"ListenbrainzEndpointSourceConfig"},"ListenbrainzEndpointData":{"type":"object","properties":{"slug":{"type":["string","null"],"description":"The URL ending that should be used to identify scrobbles for this source\n\nIf you are using multiple Listenbrainz endpoint sources (scrobbles for many users) you can use a slug to match Sources with individual users/origins\n\nExample:\n\n* slug: 'usera' => API URL: http://localhost:9078/api/listenbrainz/usera\n* slug: 'originb' => API URL: http://localhost:9078/api/listenbrainz/originb\n\nIf no slug is found from an extension's incoming webhook event the first Listenbrainz source without a slug will be used"},"token":{"type":["string","null"],"description":"If an LZ submission request contains this token in the Authorization Header it will be used to match the submission with this Source\n\nSee: https://listenbrainz.readthedocs.io/en/latest/users/api/index.html#add-the-user-token-to-your-requests"}},"title":"ListenbrainzEndpointData"},"LastFMEndpointSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/LastFMEndpointData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"}},"title":"LastFMEndpointSourceConfig"},"LastFMEndpointData":{"type":"object","properties":{"slug":{"type":["string","null"],"description":"The URL ending that should be used to identify scrobbles for this source\n\nIf you are using multiple Last.fm endpoint sources (scrobbles for many users) you can use a slug to match Sources with individual users/origins\n\nExample:\n\n* slug: 'usera' => API URL: http://localhost:9078/api/lastfm/usera\n* slug: 'originb' => API URL: http://localhost:9078/api/lastfm/originb\n\nIf no slug is found from an extension's incoming webhook event the first Last.fm source without a slug will be used"}},"title":"LastFMEndpointData"},"SubSonicSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/SubsonicData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"}},"required":["data"],"title":"SubSonicSourceConfig"},"SubsonicData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"url":{"type":"string","description":"URL of the subsonic media server to query","examples":["http://airsonic.local"]},"user":{"type":"string","description":"Username to login to the server with","examples":[["MyUser"]]},"password":{"type":"string","description":"Password for the user to login to the server with","examples":["MyPassword"]},"ignoreTlsErrors":{"type":"boolean","description":"If your subsonic server is using self-signed certs you may need to disable TLS errors in order to get a connection\n\nWARNING: This should be used with caution as your traffic may not be encrypted.","default":false},"legacyAuthentication":{"type":"boolean","description":"Older Subsonic versions, and some badly implemented servers (Nextcloud), use legacy authentication which sends your password in CLEAR TEXT. This is less secure than the newer, recommended hashing authentication method but in some cases it is needed. See \"Authentication\" section here => https://www.subsonic.org/pages/api.jsp\n\nIf this option is not specified it will be turned on if the subsonic server responds with error code 41 \"Token authentication not supported for LDAP users.\" -- See Error Handling section => https://www.subsonic.org/pages/api.jsp","default":false},"usersAllow":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Only scrobble for specific users (case-insensitive)\n\nIf undefined or an empty string/list MS will scrobble activity from all users"}},"required":["url","user","password"],"title":"SubsonicData"},"JellyApiSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/JellyApiData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/JellyApiOptions"}},"required":["data"],"title":"JellyApiSourceConfig"},"JellyApiData":{"type":"object","properties":{"url":{"type":"string","description":"HOST:PORT of the Jellyfin server to connect to"},"user":{"type":"string","description":"The username of the user to authenticate for or track scrobbles for"},"password":{"type":"string","description":"Password of the username to authenticate for\n\nRequired if `apiKey` is not provided."},"apiKey":{"type":"string","description":"API Key to authenticate with.\n\nRequired if `password` is not provided."},"usersAllow":{"anyOf":[{"type":"string"},{"type":"boolean","enum":[true]},{"type":"array","items":{"type":"string"}}],"description":"Only scrobble for specific users (case-insensitive)\n\nIf `true` MS will scrobble activity from all users"},"usersBlock":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Do not scrobble for these users (case-insensitive)"},"devicesAllow":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Only scrobble if device or application name contains strings from this list (case-insensitive)"},"devicesBlock":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Do not scrobble if device or application name contains strings from this list (case-insensitive)"},"librariesAllow":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Only scrobble if library name contains string from this list (case-insensitive)"},"librariesBlock":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Do not scrobble if library name contains strings from this list (case-insensitive)"},"additionalAllowedLibraryTypes":{"type":"array","items":{},"description":"Allow MS to scrobble audio media in libraries classified other than 'music'\n\n`librariesAllow` will achieve the same result as this but this is more convenient if you do not want to explicitly list every library name or are only using `librariesBlock`"},"allowUnknown":{"type":"boolean","description":"Force media with a type of \"Unknown\" to be counted as Audio","default":false,"deprecated":"use allowMediaTypes instead"},"allowMediaTypes":{"anyOf":[{"type":"array","items":{}},{"type":"string"}],"description":"Allow these media types to be scrobbled.\n\nIf not defined or empty, uses 'Audio' as default. If non-empty then *only* uses these types (make sure you include Audio!)\n\nValues are case-insensitive.\n\nSee https://github.com/jellyfin/jellyfin-sdk-typescript/blob/master/src/generated-client/models/media-type.ts#L22 for possible types"},"frontendUrlOverride":{"type":"string","description":"HOST:PORT of the Jellyfin server that your browser will be able to access from the frontend (and thus load images and links from)\nIf unspecified it will use the normal server HOST and PORT from the `url`\nNecessary if you are using a reverse proxy or other network configuration that prevents the frontend from accessing the server directly\n\nENV: JELLYFIN_FRONTEND_URL_OVERRIDE"}},"required":["url","user"],"title":"JellyApiData"},"JellyApiOptions":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"JellyApiOptions"},"LastfmSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/LastFmSourceData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"configureAs":{"type":"string","enum":["source"],"description":"When used in `lastfm.config` this tells multi-scrobbler whether to use this data to configure a source or client.","default":"source","examples":["source"]}},"required":["data"],"title":"LastfmSourceConfig"},"LastFmSourceData":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"apiKey":{"type":"string","description":"API Key generated from Last.fm/Libre.fm account","examples":["787c921a2a2ab42320831aba0c8f2fc2"]},"secret":{"type":"string","description":"Secret generated from Last.fm/Libre.fm account","examples":["ec42e09d5ae0ee0f0816ca151008412a"]},"session":{"type":"string","description":"Optional session id returned from a completed auth flow"},"redirectUri":{"type":"string","description":"Optional URI to use for callback. Specify this if callback should be different than the default. MUST have \"lastfm/callback\" in the URL somewhere.","default":"http://localhost:9078/lastfm/callback","examples":["http://localhost:9078/lastfm/callback"]},"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"}},"required":["apiKey","secret"],"title":"LastFmSourceData"},"LibrefmSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/LibrefmData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"configureAs":{"type":"string","enum":["source"],"description":"When used in `librefm.config` this tells multi-scrobbler whether to use this data to configure a source or client.","default":"source","examples":["source"]}},"required":["data"],"title":"LibrefmSourceConfig"},"LibrefmData":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"apiKey":{"type":"string","description":"Optional Secret for Libre.fm account\n\nThis can be anything, or it will be generated by multi-scrobbler","examples":["anyValue"]},"secret":{"type":"string","description":"Optional Secret for Libre.fm account\n\nThis can be anything, or it will be generated by multi-scrobbler","examples":["anyValue"]},"session":{"type":"string","description":"Optional session id returned from a completed auth flow"},"path":{"type":"string"},"urlBase":{"type":"string","description":"(Optional) The host and path prefix for your Libre.fm instance","default":"https://libre.fm/2.0/"},"redirectUri":{"type":"string","description":"Optional URI to use for callback. Specify this if callback should be different than the default. MUST have \"librefm/callback\" in the URL somewhere.","default":"http://localhost:9078/librefm/callback","examples":["http://localhost:9078/librefm/callback"]}},"title":"LibrefmData"},"YTMusicSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/YTMusicData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"type":"object","properties":{"logAuth":{"type":"boolean","description":"When true MS will log to DEBUG all of the credentials data it receives from YTM"},"logDiff":{"type":"boolean","description":"Always log history diff\n\nBy default MS will log to `WARN` if history diff is inconsistent but does not log if diff is expected (on new tracks found)\nSet this to `true` to ALWAYS log diff on new tracks. Expected diffs will log to `DEBUG` and inconsistent diffs will continue to log to `WARN`","default":false},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}}}},"title":"YTMusicSourceConfig"},"YTMusicData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"cookie":{"type":"string","description":"The cookie retrieved from the Request Headers of music.youtube.com after logging in.\n\nSee https://ytmusicapi.readthedocs.io/en/stable/setup/browser.html#copy-authentication-headers for how to retrieve this value.","examples":["VISITOR_INFO1_LIVE=jMp2xA1Xz2_PbVc; __Secure-3PAPISID=3AxsXpy0M/AkISpjek; ..."]},"clientId":{"type":"string","description":"Google Cloud Console project OAuth Client ID\n\nGenerated from a custom OAuth Client, see docs"},"clientSecret":{"type":"string","description":"Google Cloud Console project OAuth Client Secret\n\nGenerated from a custom OAuth Client, see docs"},"redirectUri":{"type":"string","description":"Google Cloud Console project OAuth Client Authorized redirect URI\n\nGenerated from a custom OAuth Client, see docs. multi-scrobbler will generate a default based on BASE_URL.\nOnly specify this if the default does not work for you."},"innertubeOptions":{"$ref":"#/definitions/InnertubeOptions","description":"Additional options for authorization and tailoring YTM client"}},"title":"YTMusicData"},"InnertubeOptions":{"type":"object","properties":{"po_token":{"type":"string","description":"Proof of Origin token\n\nMay be required if YTM starts returning 403"},"visitor_data":{"type":"string","description":"Visitor ID value found in VISITOR_INFO1_LIVE or visitorData cookie\n\nMay be required if YTM starts returning 403"},"account_index":{"type":"number","description":"If account login results in being able to choose multiple account, use a zero-based index to choose which one to monitor","examples":[0,1]},"location":{"type":"string"},"lang":{"type":"string"},"generate_session_locally":{"type":"boolean"},"device_category":{"type":"string"},"client_type":{"type":"string"},"timezone":{"type":"string"}},"title":"InnertubeOptions"},"MPRISSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/MPRISData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"}},"required":["data"],"title":"MPRISSourceConfig"},"MPRISData":{"type":"object","properties":{"blacklist":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"DO NOT scrobble from any players that START WITH these values, case-insensitive","examples":[["spotify","vlc"]]},"whitelist":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"ONLY from any players that START WITH these values, case-insensitive\n\nIf whitelist is present then blacklist is ignored","examples":[["spotify","vlc"]]}},"title":"MPRISData"},"MopidySourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/MopidyData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"}},"required":["data"],"title":"MopidySourceConfig"},"MopidyData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"url":{"type":"string","description":"URL of the Mopidy HTTP server to connect to\n\nYou MUST have Mopidy-HTTP extension enabled: https://mopidy.com/ext/http\n\nmulti-scrobbler connects to the WebSocket endpoint that ultimately looks like this => `ws://localhost:6680/mopidy/ws/`\n\nThe URL you provide here will have all parts not explicitly defined filled in for you so if these are not the default you must define them.\n\nParts => [default value]\n\n* Protocol => `ws://`\n* Hostname => `localhost`\n* Port => `6680`\n* Path => `/mopidy/ws/`","examples":["ws://localhost:6680/mopidy/ws/"],"default":"ws://localhost:6680/mopidy/ws/"},"uriBlacklist":{"type":"array","items":{"type":"string"},"description":"Do not scrobble tracks whose URI STARTS WITH any of these strings, case-insensitive\n\nEX: Don't scrobble tracks from soundcloud by adding 'soundcloud' to this list.\n\nList is ignored if uriWhitelist is used."},"uriWhitelist":{"type":"array","items":{"type":"string"},"description":"Only scrobble tracks whose URI STARTS WITH any of these strings, case-insensitive\n\nEX: Only scrobble tracks from soundcloud by adding 'soundcloud' to this list."},"albumBlacklist":{"type":"array","items":{"type":"string"},"description":"Remove album data that matches any case-insensitive string from this list when scrobbling,\n\nFor certain sources (Soundcloud) Mopidy does not have all track info (Album) and will instead use \"Soundcloud\" as the Album name. You can prevent multi-scrobbler from using this bad Album data by adding the fake name to this list. Multi-scrobbler will still scrobble the track, just without the bad data.","examples":[["Soundcloud","Mixcloud"]],"default":["Soundcloud"]}},"title":"MopidyData"},"ListenBrainzSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/ListenBrainzSourceData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"configureAs":{"type":"string","enum":["source"],"description":"When used in `listenbrainz.config` this tells multi-scrobbler whether to use this data to configure a source or client.","default":"source","examples":["source"]}},"required":["data"],"title":"ListenBrainzSourceConfig"},"ListenBrainzSourceData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"url":{"type":"string","description":"URL for the ListenBrainz server, if not using the default","examples":["https://api.listenbrainz.org/"],"default":"https://api.listenbrainz.org/"},"token":{"type":"string","description":"User token for the user to scrobble for","examples":["6794186bf-1157-4de6-80e5-uvb411f3ea2b"]},"username":{"type":"string","description":"Username of the user to scrobble for"}},"required":["token","username"],"title":"ListenBrainzSourceData"},"JRiverSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/JRiverData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"}},"required":["data"],"title":"JRiverSourceConfig"},"JRiverData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"url":{"type":"string","description":"URL of the JRiver HTTP server to connect to\n\nmulti-scrobbler connects to the Web Service Interface endpoint that ultimately looks like this => `http://yourDomain:52199/MCWS/v1/`\n\nThe URL you provide here will have all parts not explicitly defined filled in for you so if these are not the default you must define them.\n\nParts => [default value]\n\n* Protocol => `http://`\n* Hostname => `localhost`\n* Port => `52199`\n* Path => `/MCWS/v1/`","examples":["http://localhost:52199/MCWS/v1/"],"default":"http://localhost:52199/MCWS/v1/"},"username":{"type":"string","description":"If you have enabled authentication, the username you set"},"password":{"type":"string","description":"If you have enabled authentication, the password you set"}},"required":["url"],"title":"JRiverData"},"KodiSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/KodiData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"}},"required":["data"],"title":"KodiSourceConfig"},"KodiData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"url":{"type":"string","description":"URL of the Kodi HTTP server to connect to\n\nmulti-scrobbler connects to the Web Service Interface endpoint that ultimately looks like this => `http://yourDomain:8080/jsonrpc`\n\nThe URL you provide here will have all parts not explicitly defined filled in for you so if these are not the default you must define them.\n\nParts => [default value]\n\n* Protocol => `http://`\n* Hostname => `localhost`\n* Port => `8080`\n* Path => `/jsonrpc`","examples":["http://localhost:8080/jsonrpc"],"default":"http://localhost:8080/jsonrpc"},"username":{"type":"string","description":"The username set for Remote Control via Web Sever"},"password":{"type":"string","description":"The password set for Remote Control via Web Sever"}},"required":["url","username","password"],"title":"KodiData"},"WebScrobblerSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/WebScrobblerData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"}},"title":"WebScrobblerSourceConfig"},"WebScrobblerData":{"type":"object","properties":{"slug":{"type":["string","null"],"description":"The URL ending that should be used to identify scrobbles for this source\n\nIn WebScrobbler's Webhook you must set an 'API URL'. All MS WebScrobbler sources must start like:\n\nhttp://localhost:9078/api/webscrobbler\n\nIf you are using multiple WebScrobbler sources (scrobbles for many users) you must use a slug to match Sources with each users extension.\n\nExample:\n\n* slug: 'usera' => API URL: http://localhost:9078/api/webscrobbler/usera\n* slug: 'userb' => API URL: http://localhost:9078/api/webscrobbler/userb\n\nIf no slug is found from an extension's incoming webhook event the first WebScrobbler source without a slug will be used"},"blacklist":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Block scrobbling from specific WebScrobbler Connectors","examples":[["youtube"]]},"whitelist":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Only allow scrobbling from specific WebScrobbler Connectors","examples":[["mixcloud","soundcloud","bandcamp"]]}},"title":"WebScrobblerData"},"ChromecastSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/ChromecastData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"}},"required":["data"],"title":"ChromecastSourceConfig"},"ChromecastData":{"type":"object","properties":{"blacklistDevices":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"DO NOT scrobble from any cast devices that START WITH these values, case-insensitive\n\nUseful when used with auto discovery","examples":[["home-mini","family-tv"]]},"whitelistDevices":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"ONLY scrobble from any cast device that START WITH these values, case-insensitive\n\nIf whitelist is present then blacklist is ignored\n\nUseful when used with auto discovery","examples":[["home-mini","family-tv"]]},"blacklistApps":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"DO NOT scrobble from any application that START WITH these values, case-insensitive","examples":[["spotify","pandora"]]},"whitelistApps":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"ONLY scrobble from any application that START WITH these values, case-insensitive\n\nIf whitelist is present then blacklist is ignored","examples":[["spotify","pandora"]]},"useAvahi":{"type":"boolean","description":"Try to use Avahi and avahi-browse to resolve mDNS devices instead of native mDNS querying\n\nUseful for docker (alpine) container where mDNS resolution is not yet supported. Avahi socket must be exposed to the container and avahi-tools must be installed.","default":false},"useAutoDiscovery":{"type":"boolean","description":"Use mDNS to discovery Google Cast devices on your next automatically?\n\nIf not explicitly set then it is TRUE if `devices` is not set"},"devices":{"type":"array","items":{"$ref":"#/definitions/ChromecastDeviceInfo"},"description":"A list of Google Cast devices to monitor\n\nIf this is used then `useAutoDiscovery` is set to FALSE, if not explicitly set"},"allowUnknownMedia":{"anyOf":[{"type":"boolean"},{"type":"array","items":{"type":"string"}}],"description":"Chromecast Apps report a \"media type\" in the status info returned for whatever is currently playing\n\n* If set to TRUE then Music AND Generic/Unknown media will be tracked for ALL APPS\n* If set to FALSE then only media explicitly typed as Music will be tracked for ALL APPS\n* If set to a list then only Apps whose name contain one of these values, case-insensitive, will have Music AND Generic/Unknown tracked\n\nSee https://developers.google.com/cast/docs/media/messages#MediaInformation \"metadata\" property","default":false},"forceMediaRecognitionOn":{"type":"array","items":{"type":"string"},"description":"Media provided by any App whose name is listed here will ALWAYS be tracked, regardless of the \"media type\" reported\n\nApps will be recognized if they CONTAIN any of these values, case-insensitive"}},"title":"ChromecastData"},"ChromecastDeviceInfo":{"type":"object","properties":{"name":{"type":"string","description":"A friendly name to identify this device","examples":["MySmartTV"]},"address":{"type":"string","description":"The IP address of the device","examples":["192.168.0.115"]}},"required":["name","address"],"title":"ChromecastDeviceInfo"},"MalojaSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/MalojaSourceData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"configureAs":{"type":"string","enum":["source"],"description":"When used in `maloja.config` this tells multi-scrobbler whether to use this data to configure a source or client.","default":"source","examples":["source"]}},"required":["data"],"title":"MalojaSourceConfig"},"MalojaSourceData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"url":{"type":"string","description":"URL for maloja server","examples":["http://localhost:42010"]},"apiKey":{"type":"string","description":"API Key for Maloja server","examples":["myApiKey"]}},"required":["apiKey","url"],"title":"MalojaSourceData"},"MusikcubeSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/MusikcubeData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"}},"required":["data"],"title":"MusikcubeSourceConfig"},"MusikcubeData":{"type":"object","properties":{"url":{"type":"string","description":"URL of the Musikcube Websocket (Metadata) server to connect to\n\nYou MUST have enabled 'metadata' server and set a password: https://github.com/clangen/musikcube/wiki/remote-api-documentation\n * musikcube -> settings -> server setup\n\nThe URL you provide here will have all parts not explicitly defined filled in for you so if these are not the default you must define them.\n\nParts => [default value]\n\n* Protocol => `ws://`\n* Hostname => `localhost`\n* Port => `7905`","examples":["ws://localhost:7905"],"default":"ws://localhost:7905"},"password":{"type":"string","description":"Password set in Musikcube https://github.com/clangen/musikcube/wiki/remote-api-documentation\n\n* musikcube -> settings -> server setup -> password"},"device_id":{"type":"string"}},"required":["password"],"title":"MusikcubeData"},"MusicCastSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/MusicCastData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"}},"required":["data"],"title":"MusicCastSourceConfig"},"MusicCastData":{"type":"object","properties":{"url":{"type":"string","description":"The host or URL of the YamahaExtendedControl endpoint to use","examples":[["192.168.0.101","http://192.168.0.101/YamahaExtendedControl"]]}},"required":["url"],"title":"MusicCastData"},"MPDSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/MPDData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/MPDSourceOptions"}},"required":["data","options"],"title":"MPDSourceConfig"},"MPDData":{"type":"object","properties":{"url":{"type":"string","description":"URL:PORT of the MPD server to connect to\n\nTo use this you must have TCP connections enabled for your MPD server https://mpd.readthedocs.io/en/stable/user.html#client-connections","examples":["localhost:6600"],"default":"localhost:6600"},"path":{"type":"string","description":"If using socket specify the path instead of url.\n\ntrailing `~` is replaced by your home directory"},"password":{"type":"string","description":"Password for the server, if set https://mpd.readthedocs.io/en/stable/user.html#permissions-and-passwords"}},"title":"MPDData"},"MPDSourceOptions":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"MPDSourceOptions"},"VLCSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/VLCData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/VLCSourceOptions"}},"required":["data"],"title":"VLCSourceConfig"},"VLCData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"url":{"type":"string","description":"URL:PORT of the VLC server to connect to\n\nTo use this you must have the Web (http) interface module enabled and a password set https://foxxmd.github.io/multi-scrobbler/docs/configuration#vlc","examples":["localhost:8080"],"default":"localhost:8080"},"password":{"type":"string","description":"Password for the server"}},"required":["password"],"title":"VLCData"},"VLCSourceOptions":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"},"filenamePatterns":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"A list of regular expressions to use to extract metadata (title, album, artist) from a filename\n\nUsed when VLC reports only the filename for the current audio track"},"logFilenamePatterns":{"type":"boolean","description":"Log to DEBUG when a filename-only track is matched or not matched by filenamePatterns","default":false},"dumpVlcMetadata":{"type":"boolean","description":"Dump all the metadata VLC reports for an audio track to DEBUG.\n\nUse this if reporting an issue with VLC not correctly capturing metadata for a track.","default":false}},"title":"VLCSourceOptions"},"IcecastSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/IcecastData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/IcecastSourceOptions"}},"required":["data"],"title":"IcecastSourceConfig"},"IcecastData":{"type":"object","properties":{"sources":{"type":"array","items":{"$ref":"#/definitions/IcecastSource"}},"icestatsEndpoint":{"type":"string"},"statsEndpoint":{"type":"string"},"nextsongsEndpoint":{"type":"string"},"sevenhtmlEndpoint":{"type":"string"},"icyMetaInt":{"type":"number"},"url":{"type":"string","description":"The Icecast stream URL"}},"required":["url"],"title":"IcecastData"},"IcecastSource":{"type":"string","enum":["icy","ogg","icestats","stats","sevenhtml","nextsongs"],"title":"IcecastSource"},"IcecastSourceOptions":{"type":"object","properties":{"systemScrobble":{"type":"boolean","description":"For Sources that support manual listening, should MS default to scrobbling when no user interaction has occurred?\n\nIf not specified MS will use a Source's specific behavior, see Source's documentation."},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"IcecastSourceOptions"},"AzuracastSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/AzuracastData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"}},"required":["data"],"title":"AzuracastSourceConfig"},"AzuracastData":{"type":"object","properties":{"url":{"type":"string","description":"Base URL of the Azuracast instance\n\nThis does NOT include the station. If a station is included it will be ignored. Use `station` field to specify station, if necessary","examples":["https://radio.mydomain.tld","http://localhost:80"]},"station":{"type":"string","description":"The specific station to monitor\n\nScrobbling will only occur if any of the monitor conditions are met AND the station is ONLINE.\n\nTo monitor multiple stations create a Source for each station.","examples":["my-station-1"]},"monitorWhenListeners":{"type":["boolean","number"],"description":"Only activate scrobble monitoring if station\n\n* `true` => has any current listeners\n* `number` => has EQUAL TO or MORE THAN X number of listeners"},"monitorWhenLive":{"type":"boolean","description":"Only activate scrobble monitoring if station has a live DJ/Streamer","default":true},"apiKey":{"type":"string","description":"API Key used to access data about private streams\n\nhttps://www.azuracast.com/docs/developers/apis/#api-authentication"}},"required":["url","station"],"title":"AzuracastData"},"KoitoSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/KoitoSourceData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/CommonSourceOptions"},"configureAs":{"type":"string","enum":["source"],"description":"When used in `koito.config` this tells multi-scrobbler whether to use this data to configure a source or client.","default":"source","examples":["source"]}},"required":["data"],"title":"KoitoSourceConfig"},"KoitoSourceData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"url":{"type":"string","description":"URL for the Koito server","examples":["http://192.168.0.100:4110"]},"token":{"type":"string","description":"User token for the user to scrobble for","examples":["pM195xPV98CDpk0QW47FIIOR8AKATAX5DblBF-Jq0t1MbbKL"]},"username":{"type":"string","description":"Username of the user to scrobble for"}},"required":["token","url","username"],"title":"KoitoSourceData"},"TealSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/TealSourceData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/TealSourceOptions"},"configureAs":{"type":"string","enum":["source"],"description":"Should always be `souce` when using Tealfm as a Source","default":"source","examples":["source"]}},"required":["data"],"title":"TealSourceConfig"},"TealSourceData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"baseUri":{"type":"string","description":"The base URI of the Multi-Scrobbler to use for ATProto OAuth\n\nOnly include this if you want to use OAuth. The URI must be a non-IP/non-local domain using https: protocol."},"identifier":{"type":"string","description":"Identify the account to login as\n\n* For **App Password** Auth - your email\n* For **Oauth** - your handle minus the @"},"appPassword":{"type":"string","description":"The [App Password](https://atproto.com/specs/xrpc#app-passwords) you created for your account\n\nThis is created under https://bsky.app/settings/app-passwords\n\n**Use this if you are self-hosting Multi-Scrobbler on localhost or accessed like http://IP:PORT**"},"serviceAllow":{"type":"array","items":{"type":"string"}},"serviceDeny":{"type":"array","items":{"type":"string"}}},"required":["identifier"],"title":"TealSourceData"},"TealSourceOptions":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"}},"title":"TealSourceOptions"},"RockskySourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/RockskySourceData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/RockskySourceOptions"},"configureAs":{"type":"string","enum":["source"],"description":"When used in `rocksky.config` this tells multi-scrobbler whether to use this data to configure a source or client.","default":"source","examples":["source"]}},"required":["data"],"title":"RockskySourceConfig"},"RockskySourceData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"key":{"type":"string","description":"API Key generated from [API Applications](https://docs.rocksky.app/migrating-from-listenbrainz-to-rocksky-1040189m0) in Rocksky for your account","examples":["6794186bf-1157-4de6-80e5-uvb411f3ea2b"]},"handle":{"type":"string","description":"The **fully-qualified** handle for your ATPRoto/Bluesky account, like:\n\n* alice.bsky.social\n* foxxmd.com\n* mysuer.blacksky.app"}},"required":["handle","key"],"title":"RockskySourceData"},"RockskySourceOptions":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"},"audioScrobblerUrl":{"type":"string","description":"URL for the Rocksky *Listenbrainz* endpoint, if not using the default","examples":["https://audioscrobbler.rocksky.app"],"default":"https://audioscrobbler.rocksky.app"},"apiUrl":{"type":"string","description":"URL for the Rocksky *API* endpoint, if not using the default","examples":["https://api.rocksky.app"],"default":"https://api.rocksky.app"}},"title":"RockskySourceOptions"},"SonosSourceConfig":{"type":"object","properties":{"name":{"type":"string","description":"Unique identifier for this source."},"data":{"$ref":"#/definitions/SonosData"},"enable":{"type":"boolean","description":"Should MS use this client/source? Defaults to true","default":true,"examples":[true]},"clients":{"type":"array","items":{"type":"string"},"description":"Restrict scrobbling tracks played from this source to Clients with names from this list. If list is empty is not present Source scrobbles to all configured Clients.","examples":[["MyMalojaConfigName","MyLastFMConfigName"]]},"options":{"$ref":"#/definitions/SonosSourceOptions"}},"required":["data"],"title":"SonosSourceConfig"},"SonosData":{"type":"object","properties":{"interval":{"type":"number","description":"How long to wait before polling the source API for new tracks (in seconds)","default":10,"examples":[10]},"maxInterval":{"type":"number","description":"When there has been no new activity from the Source API multi-scrobbler will gradually increase the wait time between polling up to this value (in seconds)","default":30,"examples":[30]},"staleAfter":{"type":"number","description":"Number of seconds after which A Player is considered Stale\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Stale. When the Player becomes Stale:\n\n* The current listening session is ended. If the Player becomes active again a new listening session is started (Player will miss `interval` seconds of listening)\n* If the player has an existing session w/ track then MS attempts to scrobble it\n\nThis option DOES NOT need to be set. It is automatically calculated as (`interval` * 3) when not defined."},"orphanedAfter":{"type":"number","description":"Number of seconds after which A Player is considered Orphaned\n\nWhen Polling the source does not recieve data about a specific Player after X seconds it becomes Orphaned. When the Player becomes Orphaned:\n\n* The current Player session is ended and the Player is removed from MS\n* MS attempts to scrobble, if the Player has an existing session w/ track\n\nA Player should become Orphaned EQUAL TO OR AFTER it becomes Stale.\n\n* This option DOES NOT need to be set. It is automatically calculated as (`interval` * 5) when not defined.\n* If it is set it must be equal to or larger than `staleAfter` or (`interval * 3`)"},"host":{"type":"string","description":"IP address of any connected Sonos speaker or device","examples":["192.168.0.170"]},"devicesAllow":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Only scrobble if device name contains strings from this list (case-insensitive)"},"devicesBlock":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Do not scrobble if device name contains strings from this list (case-insensitive)"},"groupsAllow":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Only scrobble if the name of a group the playing device belongs to contains strings from this list (case-insensitive)"},"groupsBlock":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Do not scrobble if the name of a group the playing device belongs to contains strings from this list (case-insensitive)"}},"required":["host"],"title":"SonosData"},"SonosSourceOptions":{"type":"object","properties":{"maxRequestRetries":{"type":"number","description":"default # of http request retries a source/client can make before error is thrown","default":1,"examples":[1]},"retryMultiplier":{"type":"number","description":"default retry delay multiplier (retry attempt * multiplier = # of seconds to wait before retrying)","default":1.5,"examples":[1.5]},"maxPollRetries":{"type":"number","description":"default # of automatic polling restarts on error","default":5,"examples":[5]},"logPayload":{"type":"boolean","description":"* If this source has INGRESS to MS (sends a payload, rather than MS GETTING requesting a payload) then setting this option to true will make MS log the payload JSON to DEBUG output\n* If this source is POLLING then it will log the raw data for each unique track/response the first time it is seen","default":false,"examples":[false]},"logFilterFailure":{"type":["boolean","string"],"enum":[false,"debug","warn"],"description":"If this source has INGRESS to MS and has filters this determines how MS logs when a payload (event) fails a defined filter (IE users/servers/library filters)\n\n* `false` => do not log\n* `debug` => log to DEBUG level\n* `warn` => log to WARN level (default)\n\nHint: This is useful if you are sure this source is setup correctly and you have multiple other sources. Set to `debug` or `false` to reduce log noise.","default":"warn","examples":["warn"]},"logPlayerState":{"type":"boolean","description":"For Sources that track Player State (currently playing) this logs a simple player state/summary to DEBUG output","default":false,"examples":[false]},"logToFile":{"anyOf":[{"type":"boolean","enum":[true]},{"$ref":"#/definitions/LogLevel"},{"$ref":"#/definitions/FileLogOptions"}],"description":"**Exprimental:** Log to a separate file for this Source.\n\nUseful for debugging long-running Sources"},"scrobbleBacklog":{"type":"boolean","description":"If this source\n\n* supports fetching a listen history\n* and this option is enabled\n\nthen on startup MS will attempt to scrobble the recent listens from that history","default":true,"examples":[true,false]},"scrobbleThresholds":{"$ref":"#/definitions/ScrobbleThresholds","description":"Set thresholds for when multi-scrobbler should consider a tracked play to be \"scrobbable\". If both duration and percent are defined then if either condition is met the track is scrobbled."},"scrobbleBacklogCount":{"type":"number","description":"The number of listens to fetch when scrobbling from backlog\n\n* Only applies if this source supports fetching a listen history\n* If not specified it defaults to the maximum number of listens the source API supports"},"playTransform":{"$ref":"#/definitions/PlayTransformOptions"},"logEmptyPlayer":{"type":"boolean"}},"title":"SonosSourceOptions"}}} \ No newline at end of file diff --git a/src/backend/utils/SchemaDocsStaticUtils.ts b/src/backend/utils/SchemaDocsStaticUtils.ts index 696e00a3..8f88b215 100644 --- a/src/backend/utils/SchemaDocsStaticUtils.ts +++ b/src/backend/utils/SchemaDocsStaticUtils.ts @@ -1,4 +1,4 @@ -import { writeFileSync } from "node:fs"; +import { writeFileSync, mkdirSync } from "node:fs"; import { resolve } from "path"; import { projectDir } from "../common/index.js"; import {getTypeSchemaFromConfigGenerator} from "./SchemaUtils.js"; @@ -20,3 +20,8 @@ writeFileSync(resolve(projectDir, 'src/backend/common/schema/aio-client.json'), const aio_source = getTypeSchemaFromConfigGenerator('AIOSourceConfig'); writeFileSync(resolve(projectDir, 'src/backend/common/schema/aio-source.json'), JSON.stringify(aio_source)); + +mkdirSync(resolve(projectDir, 'docsite/static/schemas'), {recursive: true}); + +const plex = getTypeSchemaFromConfigGenerator('PlexApiSourceConfigs'); +writeFileSync(resolve(projectDir, 'docsite/static/schemas/PlexApiSourceConfig.json'), JSON.stringify(plex)); \ No newline at end of file diff --git a/vite.config.ts b/vite.config.ts index 82521b42..5287ef5b 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -41,7 +41,8 @@ export default defineConfig(() => { tailwindcss(), ], build: { - sourcemap: true + sourcemap: true, + cssCodeSplit: true }, define: { "__USE_HASH_ROUTER__": JSON.stringify((process.env.USE_HASH_ROUTER ?? false))