mirror of
https://github.com/FoxxMD/multi-scrobbler.git
synced 2026-08-19 21:53:22 +00:00
254 lines
No EOL
9.7 KiB
JavaScript
254 lines
No EOL
9.7 KiB
JavaScript
// For more info, see https://github.com/storybookjs/eslint-plugin-storybook#configuration-flat-config-format
|
|
import storybook from "eslint-plugin-storybook";
|
|
import boundaries from 'eslint-plugin-boundaries';
|
|
import unusedImports from 'eslint-plugin-unused-imports';
|
|
import { importX } from 'eslint-plugin-import-x'
|
|
|
|
import { defineConfig, globalIgnores } from "eslint/config";
|
|
|
|
// @ts-check
|
|
|
|
import js from '@eslint/js';
|
|
import globals from 'globals';
|
|
import tsEslint from 'typescript-eslint';
|
|
import arrow from 'eslint-plugin-prefer-arrow-functions';
|
|
import hooks from 'eslint-plugin-react-hooks';
|
|
import mochaPlugin from 'eslint-plugin-mocha';
|
|
import unicorn from 'eslint-plugin-unicorn';
|
|
|
|
const defaultRules = {
|
|
'no-useless-catch': 'off',
|
|
'@typescript-eslint/no-unused-vars': 'warn',
|
|
'no-unused-vars': [
|
|
'warn',
|
|
{
|
|
args: 'none',
|
|
caughtErrors: 'none',
|
|
destructuredArrayIgnorePattern: "^_",
|
|
"argsIgnorePattern": "^_",
|
|
ignoreRestSiblings: true,
|
|
ignoreUsingDeclarations: true
|
|
}
|
|
],
|
|
"@typescript-eslint/no-unused-vars": [
|
|
"warn",
|
|
{
|
|
args: 'none',
|
|
caughtErrors: 'none',
|
|
destructuredArrayIgnorePattern: "^_",
|
|
"argsIgnorePattern": "^_",
|
|
ignoreRestSiblings: true,
|
|
ignoreUsingDeclarations: true
|
|
}
|
|
],
|
|
"prefer-arrow-functions/prefer-arrow-functions": [
|
|
"warn",
|
|
{
|
|
"allowNamedFunctions": false,
|
|
"classPropertiesAllowed": false,
|
|
"disallowPrototype": false,
|
|
"returnStyle": "unchanged",
|
|
"singleReturnOnly": false
|
|
}
|
|
],
|
|
"arrow-body-style": ["warn", "as-needed"],
|
|
"@typescript-eslint/no-explicit-any": "warn",
|
|
"@typescript-eslint/no-empty-object-type": [
|
|
"warn",
|
|
{
|
|
"allowInterfaces": 'with-single-extends'
|
|
}
|
|
]
|
|
};
|
|
|
|
export default defineConfig([
|
|
globalIgnores([
|
|
'docsite/build',
|
|
'docsite/.docusaurus',
|
|
'public/mockServiceWorker.js',
|
|
'dist'
|
|
]),
|
|
{
|
|
plugins: {
|
|
"prefer-arrow-functions": arrow,
|
|
js,
|
|
'unused-imports': unusedImports,
|
|
unicorn,
|
|
'import-x': importX,
|
|
},
|
|
rules: {
|
|
...defaultRules,
|
|
// https://typescript-eslint.io/rules/consistent-type-imports/#comparison-with-importsnotusedasvalues--verbatimmodulesyntax
|
|
//
|
|
// when using tsconfig compiler verbatimModuleSyntax and EX import {type Foo, type Bar} from 'a';
|
|
// true => typescript will *still* import a module if all types are inline
|
|
// false => typescript will erase the entire module import
|
|
//
|
|
// we need to use verbatimModuleSyntax: true for nodejs type stripping compatibility so
|
|
// its important that we use top-level type imports so we don't accidentally import server-side modules into frontend
|
|
// but can still use types where necessary
|
|
//
|
|
// this rule *should* do this...it does detect imports that are typed but not explicitly declared
|
|
// but its not moving inline -> top-level
|
|
"@typescript-eslint/consistent-type-imports": [
|
|
"error",
|
|
{
|
|
prefer: 'type-imports',
|
|
fixStyle: "separate-type-imports"
|
|
}
|
|
],
|
|
// however, import/consistent-type-specifier-style from eslint-plugin-import *does* move inline => top-level
|
|
// but it does not yet support eslint10 :(
|
|
//
|
|
// TODO eventually add this once plugin-import supports eslint10
|
|
// https://github.com/import-js/eslint-plugin-import
|
|
// https://github.com/import-js/eslint-plugin-import/blob/main/docs/rules/consistent-type-specifier-style.md
|
|
// -- this enforces that type-only imports are fixed to top-level type imports IE
|
|
// import {type Foo, type Bar} from 'a'; => import type { Foo, Bar} from 'a';
|
|
//
|
|
// USE eslint-plugin-import-x since its more actively developed?
|
|
// waiting on the status of this for supporting mixed inline types
|
|
// https://github.com/un-ts/eslint-plugin-import-x/issues/501
|
|
// "import-x/consistent-type-specifier-style": [
|
|
// "error", "prefer-top-level"
|
|
// ],
|
|
"unicorn/prefer-then-catch": "error",
|
|
"unicorn/consistent-destructuring": "warn",
|
|
"unicorn/consistent-function-scoping": "warn",
|
|
"unicorn/consistent-optional-chaining": "error",
|
|
"unicorn/no-array-callback-reference": "warn",
|
|
"unicorn/no-accidental-bitwise-operator": "warn",
|
|
"no-obj-calls": "error",
|
|
"unicorn/new-for-builtins": "error",
|
|
"unicorn/no-impossible-length-comparison": "error",
|
|
"unicorn/no-duplicate-loops": "warn",
|
|
"unicorn/no-duplicate-logical-operands": "warn",
|
|
"unicorn/no-declarations-before-early-exit": "warn",
|
|
"unicorn/prefer-negative-index": "warn",
|
|
"unicorn/prefer-import-meta-properties": "error",
|
|
"unicorn/prefer-array-from-async": "warn",
|
|
"unicorn/prefer-array-flat-map": "warn",
|
|
"unicorn/no-useless-else": "warn",
|
|
"unicorn/no-unused-array-method-return": "error",
|
|
//"unicorn/no-unreadable-object-destructuring": "warn",
|
|
"unicorn/prefer-object-destructuring-defaults": "warn"
|
|
},
|
|
extends: [
|
|
tsEslint.configs.recommended,
|
|
"js/recommended"
|
|
],
|
|
languageOptions: {
|
|
globals: {
|
|
...globals.node,
|
|
},
|
|
ecmaVersion: 'latest',
|
|
sourceType: 'module',
|
|
},
|
|
files: ['src/**/*.ts','src/**/*.tsx']
|
|
},
|
|
{
|
|
extends: [
|
|
storybook.configs["flat/recommended"],
|
|
],
|
|
files: ['src/client/stories/**/*.tsx'],
|
|
},
|
|
{
|
|
extends: [
|
|
hooks.configs.flat.recommended,
|
|
],
|
|
languageOptions: {
|
|
globals: {
|
|
...globals.browser,
|
|
}
|
|
},
|
|
files: ['src/client/**/*.tsx'],
|
|
},
|
|
{
|
|
extends: [
|
|
mochaPlugin.configs.recommended,
|
|
],
|
|
languageOptions: {
|
|
globals: {
|
|
...globals.node,
|
|
}
|
|
},
|
|
files: ['src/backend/tests/**/*.ts'],
|
|
rules: {
|
|
...defaultRules,
|
|
"prefer-arrow-functions/prefer-arrow-functions": ["off"],
|
|
"@typescript-eslint/no-unused-expressions": 'off',
|
|
'mocha/max-top-level-suites': 'off'
|
|
},
|
|
},
|
|
{
|
|
// 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
|
|
files: ['**/*.{ts,tsx,mts,cts}'],
|
|
plugins: {
|
|
'unused-imports': unusedImports
|
|
},
|
|
rules: {
|
|
'no-undef': 'off',
|
|
'unused-imports/no-unused-imports': 'error'
|
|
}
|
|
},
|
|
// this ruleset helps keep backend, frontend, and core keep imports isolated
|
|
// in order to prevent frontend (vite) from accidentally bundling backend files + backend packages when importing directly (backend) or transitively (through core)
|
|
//
|
|
// folder (module?) boundaries should be like
|
|
//
|
|
// backend <-- all node/server side code
|
|
// core <-- shared types, utils, and logic between backend and client
|
|
// client <-- frontend code to be bundled by vite, SHOULD NOT import directly/transitively from backend
|
|
{
|
|
files: ['src/**/*.{ts,tsx}'],
|
|
plugins: { boundaries },
|
|
settings: {
|
|
// Define your three architectural layers
|
|
'boundaries/elements': [
|
|
{ type: 'frontend', mode: 'file', pattern: 'src/client/**/*' },
|
|
{ type: 'config', mode: 'file', pattern: 'config/*.example' },
|
|
{ type: 'core', mode: 'file', pattern: ['src/core/!(tests)/**','src/core/!(tests)'] },
|
|
{ type: 'core-tests', mode: 'file', pattern: ['src/core/tests/**'] },
|
|
{ type: 'backend', mode: 'file', pattern: 'src/backend/**/*' },
|
|
{ type: 'stories', mode: 'file', pattern: ['src/stories/**/*', '.storybook/**'] },
|
|
],
|
|
// So it understands TS path aliases when resolving imports
|
|
'import/resolver': {
|
|
typescript: true,
|
|
},
|
|
},
|
|
rules: {
|
|
'boundaries/element-types': [
|
|
'warn',
|
|
{
|
|
default: 'disallow', // deny anything not explicitly allowed
|
|
rules: [
|
|
{
|
|
from: 'frontend',
|
|
allow: ['frontend', 'core'], // frontend can use itself + core, never backend
|
|
},
|
|
{
|
|
from: 'core',
|
|
allow: ['core'], // core can only use itself — never backend, never frontend
|
|
},
|
|
{
|
|
from: 'backend',
|
|
allow: ['backend', 'core', 'config', 'core-tests'], // backend can use itself + core + tests
|
|
},
|
|
{
|
|
from: 'stories',
|
|
allow: ['stories', 'core', 'frontend', 'core-tests'], // backend can use itself + core
|
|
},
|
|
{
|
|
from: 'core-tests',
|
|
allow: ['core', 'core-tests'], // backend can use itself + core
|
|
},
|
|
],
|
|
},
|
|
],
|
|
// Optional: flag any file under src/ that doesn't match one of the
|
|
// three element patterns above (catches stray/misplaced files)
|
|
'boundaries/no-unknown': 'warn'
|
|
},
|
|
}
|
|
]); |