[READ-ONLY] Mirror of https://github.com/FoxxMD/multi-scrobbler. Scrobble plays from multiple sources to multiple clients docs.multi-scrobbler.app
deezer docker jellyfin koito lastfm listenbrainz maloja mopidy mpris music music-assistant plex scrobble self-hosted spotify subsonic tautulli youtube-music
0

Configure Feed

Select the types of activity you want to include in your feed.

multi-scrobbler / eslint.config.js
9.9 kB 254 lines
1// For more info, see https://github.com/storybookjs/eslint-plugin-storybook#configuration-flat-config-format 2import storybook from "eslint-plugin-storybook"; 3import boundaries from 'eslint-plugin-boundaries'; 4import unusedImports from 'eslint-plugin-unused-imports'; 5import { importX } from 'eslint-plugin-import-x' 6 7import { defineConfig, globalIgnores } from "eslint/config"; 8 9// @ts-check 10 11import js from '@eslint/js'; 12import globals from 'globals'; 13import tsEslint from 'typescript-eslint'; 14import arrow from 'eslint-plugin-prefer-arrow-functions'; 15import hooks from 'eslint-plugin-react-hooks'; 16import mochaPlugin from 'eslint-plugin-mocha'; 17import unicorn from 'eslint-plugin-unicorn'; 18 19const defaultRules = { 20 'no-useless-catch': 'off', 21 '@typescript-eslint/no-unused-vars': 'warn', 22 'no-unused-vars': [ 23 'warn', 24 { 25 args: 'none', 26 caughtErrors: 'none', 27 destructuredArrayIgnorePattern: "^_", 28 "argsIgnorePattern": "^_", 29 ignoreRestSiblings: true, 30 ignoreUsingDeclarations: true 31 } 32 ], 33 "@typescript-eslint/no-unused-vars": [ 34 "warn", 35 { 36 args: 'none', 37 caughtErrors: 'none', 38 destructuredArrayIgnorePattern: "^_", 39 "argsIgnorePattern": "^_", 40 ignoreRestSiblings: true, 41 ignoreUsingDeclarations: true 42 } 43 ], 44 "prefer-arrow-functions/prefer-arrow-functions": [ 45 "warn", 46 { 47 "allowNamedFunctions": false, 48 "classPropertiesAllowed": false, 49 "disallowPrototype": false, 50 "returnStyle": "unchanged", 51 "singleReturnOnly": false 52 } 53 ], 54 "arrow-body-style": ["warn", "as-needed"], 55 "@typescript-eslint/no-explicit-any": "warn", 56 "@typescript-eslint/no-empty-object-type": [ 57 "warn", 58 { 59 "allowInterfaces": 'with-single-extends' 60 } 61 ] 62}; 63 64export default defineConfig([ 65 globalIgnores([ 66 'docsite/build', 67 'docsite/.docusaurus', 68 'public/mockServiceWorker.js', 69 'dist' 70 ]), 71 { 72 plugins: { 73 "prefer-arrow-functions": arrow, 74 js, 75 'unused-imports': unusedImports, 76 unicorn, 77 'import-x': importX, 78 }, 79 rules: { 80 ...defaultRules, 81 // https://typescript-eslint.io/rules/consistent-type-imports/#comparison-with-importsnotusedasvalues--verbatimmodulesyntax 82 // 83 // when using tsconfig compiler verbatimModuleSyntax and EX import {type Foo, type Bar} from 'a'; 84 // true => typescript will *still* import a module if all types are inline 85 // false => typescript will erase the entire module import 86 // 87 // we need to use verbatimModuleSyntax: true for nodejs type stripping compatibility so 88 // its important that we use top-level type imports so we don't accidentally import server-side modules into frontend 89 // but can still use types where necessary 90 // 91 // this rule *should* do this...it does detect imports that are typed but not explicitly declared 92 // but its not moving inline -> top-level 93 "@typescript-eslint/consistent-type-imports": [ 94 "error", 95 { 96 prefer: 'type-imports', 97 fixStyle: "separate-type-imports" 98 } 99 ], 100 // however, import/consistent-type-specifier-style from eslint-plugin-import *does* move inline => top-level 101 // but it does not yet support eslint10 :( 102 // 103 // TODO eventually add this once plugin-import supports eslint10 104 // https://github.com/import-js/eslint-plugin-import 105 // https://github.com/import-js/eslint-plugin-import/blob/main/docs/rules/consistent-type-specifier-style.md 106 // -- this enforces that type-only imports are fixed to top-level type imports IE 107 // import {type Foo, type Bar} from 'a'; => import type { Foo, Bar} from 'a'; 108 // 109 // USE eslint-plugin-import-x since its more actively developed? 110 // waiting on the status of this for supporting mixed inline types 111 // https://github.com/un-ts/eslint-plugin-import-x/issues/501 112 // "import-x/consistent-type-specifier-style": [ 113 // "error", "prefer-top-level" 114 // ], 115 "unicorn/prefer-then-catch": "error", 116 "unicorn/consistent-destructuring": "warn", 117 "unicorn/consistent-function-scoping": "warn", 118 "unicorn/consistent-optional-chaining": "error", 119 "unicorn/no-array-callback-reference": "warn", 120 "unicorn/no-accidental-bitwise-operator": "warn", 121 "no-obj-calls": "error", 122 "unicorn/new-for-builtins": "error", 123 "unicorn/no-impossible-length-comparison": "error", 124 "unicorn/no-duplicate-loops": "warn", 125 "unicorn/no-duplicate-logical-operands": "warn", 126 "unicorn/no-declarations-before-early-exit": "warn", 127 "unicorn/prefer-negative-index": "warn", 128 "unicorn/prefer-import-meta-properties": "error", 129 "unicorn/prefer-array-from-async": "warn", 130 "unicorn/prefer-array-flat-map": "warn", 131 "unicorn/no-useless-else": "warn", 132 "unicorn/no-unused-array-method-return": "error", 133 //"unicorn/no-unreadable-object-destructuring": "warn", 134 "unicorn/prefer-object-destructuring-defaults": "warn" 135 }, 136 extends: [ 137 tsEslint.configs.recommended, 138 "js/recommended" 139 ], 140 languageOptions: { 141 globals: { 142 ...globals.node, 143 }, 144 ecmaVersion: 'latest', 145 sourceType: 'module', 146 }, 147 files: ['src/**/*.ts','src/**/*.tsx'] 148 }, 149 { 150 extends: [ 151 storybook.configs["flat/recommended"], 152 ], 153 files: ['src/client/stories/**/*.tsx'], 154 }, 155 { 156 extends: [ 157 hooks.configs.flat.recommended, 158 ], 159 languageOptions: { 160 globals: { 161 ...globals.browser, 162 } 163 }, 164 files: ['src/client/**/*.tsx'], 165 }, 166 { 167 extends: [ 168 mochaPlugin.configs.recommended, 169 ], 170 languageOptions: { 171 globals: { 172 ...globals.node, 173 } 174 }, 175 files: ['src/backend/tests/**/*.ts'], 176 rules: { 177 ...defaultRules, 178 "prefer-arrow-functions/prefer-arrow-functions": ["off"], 179 "@typescript-eslint/no-unused-expressions": 'off', 180 'mocha/max-top-level-suites': 'off' 181 }, 182 }, 183 { 184 // https://typescript-eslint.io/troubleshooting/faqs/eslint#i-get-errors-from-the-no-undef-rule-about-global-variables-not-being-defined-even-though-there-are-no-typescript-errors 185 files: ['**/*.{ts,tsx,mts,cts}'], 186 plugins: { 187 'unused-imports': unusedImports 188 }, 189 rules: { 190 'no-undef': 'off', 191 'unused-imports/no-unused-imports': 'error' 192 } 193 }, 194 // this ruleset helps keep backend, frontend, and core keep imports isolated 195 // in order to prevent frontend (vite) from accidentally bundling backend files + backend packages when importing directly (backend) or transitively (through core) 196 // 197 // folder (module?) boundaries should be like 198 // 199 // backend <-- all node/server side code 200 // core <-- shared types, utils, and logic between backend and client 201 // client <-- frontend code to be bundled by vite, SHOULD NOT import directly/transitively from backend 202 { 203 files: ['src/**/*.{ts,tsx}'], 204 plugins: { boundaries }, 205 settings: { 206 // Define your three architectural layers 207 'boundaries/elements': [ 208 { type: 'frontend', mode: 'file', pattern: 'src/client/**/*' }, 209 { type: 'config', mode: 'file', pattern: 'config/*.example' }, 210 { type: 'core', mode: 'file', pattern: ['src/core/!(tests)/**','src/core/!(tests)'] }, 211 { type: 'core-tests', mode: 'file', pattern: ['src/core/tests/**'] }, 212 { type: 'backend', mode: 'file', pattern: 'src/backend/**/*' }, 213 { type: 'stories', mode: 'file', pattern: ['src/stories/**/*', '.storybook/**'] }, 214 ], 215 // So it understands TS path aliases when resolving imports 216 'import/resolver': { 217 typescript: true, 218 }, 219 }, 220 rules: { 221 'boundaries/element-types': [ 222 'warn', 223 { 224 default: 'disallow', // deny anything not explicitly allowed 225 rules: [ 226 { 227 from: 'frontend', 228 allow: ['frontend', 'core'], // frontend can use itself + core, never backend 229 }, 230 { 231 from: 'core', 232 allow: ['core'], // core can only use itself — never backend, never frontend 233 }, 234 { 235 from: 'backend', 236 allow: ['backend', 'core', 'config', 'core-tests'], // backend can use itself + core + tests 237 }, 238 { 239 from: 'stories', 240 allow: ['stories', 'core', 'frontend', 'core-tests'], // backend can use itself + core 241 }, 242 { 243 from: 'core-tests', 244 allow: ['core', 'core-tests'], // backend can use itself + core 245 }, 246 ], 247 }, 248 ], 249 // Optional: flag any file under src/ that doesn't match one of the 250 // three element patterns above (catches stray/misplaced files) 251 'boundaries/no-unknown': 'warn' 252 }, 253 } 254]);