podcast manager
at main 168 lines 4.9 kB view raw
1import {includeIgnoreFile} from '@eslint/compat' 2import js from '@eslint/js' 3import json from '@eslint/json' 4import restrictedGlobals from 'confusing-browser-globals' 5import prettier from 'eslint-plugin-prettier/recommended' 6import react from 'eslint-plugin-react' 7import reactHooks from 'eslint-plugin-react-hooks' 8import tsdoc from 'eslint-plugin-tsdoc' 9import {defineConfig} from 'eslint/config' 10import globals from 'globals' 11import path from 'node:path' 12import tseslint from 'typescript-eslint' 13 14const gitignore = path.resolve(import.meta.dirname, '.gitignore') 15 16export default defineConfig( 17 includeIgnoreFile(gitignore, '.gitignore'), 18 19 // all files by default get shared globals 20 { 21 name: 'javascript basics', 22 files: ['**/*.@(js|jsx|ts|tsx)'], 23 extends: [js.configs.recommended], 24 25 languageOptions: { 26 globals: { 27 ...globals.es2024, 28 ...globals['shared-node-browser'], 29 }, 30 }, 31 32 rules: { 33 // eg, `open` is a global, but probably not really intended that way in our code 34 'no-restricted-globals': ['error', ...restrictedGlobals], 35 'no-unused-vars': ['warn', {varsIgnorePattern: '(?:^_)'}], 36 }, 37 }, 38 39 { 40 name: 'typescript basics', 41 files: ['**/*.@(ts|tsx)'], 42 extends: [tseslint.configs.strictTypeChecked], 43 plugins: {tsdoc}, 44 languageOptions: { 45 parserOptions: { 46 projectService: true, 47 tsconfigRootDir: import.meta.dirname, 48 }, 49 }, 50 rules: { 51 // allow leading underscore for marking unused vars 52 '@typescript-eslint/no-unused-vars': ['warn', {varsIgnorePattern: '(?:^_)'}], 53 54 // template literals default to calling toString(), but I mean what I say 55 '@typescript-eslint/restrict-template-expressions': 'off', 56 57 // I need to be able to do `while(true)`, come on yall... 58 '@typescript-eslint/no-unnecessary-condition': ['warn', {allowConstantLoopConditions: 'always'}], 59 60 // this breaks when I want to use a type parameter to allow type checking inline arguments 61 // it's "unnecessary type parameters" or an `as` declaration, which I don't like 62 '@typescript-eslint/no-unnecessary-type-parameters': 'off', 63 '@typescript-eslint/no-unnecessary-type-constraint': 'off', 64 65 // the breaks Promise.withResolvers<void>(), 66 // see https://github.com/typescript-eslint/typescript-eslint/issues/8113 67 '@typescript-eslint/no-invalid-void-type': 'off', 68 69 // make sure the docs look good 70 'tsdoc/syntax': 'warn', 71 }, 72 }, 73 74 { 75 name: 'node files', 76 files: ['src/server/**/*.@(js|jsx|ts|tsx)', 'src/cmd/**/*.@(js|jsx|ts|tsx)'], 77 languageOptions: { 78 globals: { 79 ...globals.es2024, 80 ...globals.node, 81 }, 82 }, 83 }, 84 85 { 86 // mostly cribbed from preact's config, but that's not setup to handle eslint9 87 // https://github.com/preactjs/eslint-config-preact/blob/master/index.js 88 name: 'client files', 89 files: ['src/client/**/*.@(js|ts)', 'src/**/*.@(jsx|tsx)'], 90 languageOptions: { 91 globals: { 92 ...globals.es2024, 93 ...globals.browser, 94 }, 95 }, 96 plugins: { 97 react, 98 reactHooks, 99 }, 100 settings: { 101 react: { 102 pragma: 'h', 103 version: '16.0', 104 }, 105 }, 106 rules: { 107 // preact / jsx rules 108 'react/no-deprecated': 2, 109 'react/react-in-jsx-scope': 0, // handled this automatically 110 'react/display-name': [1, {ignoreTranspilerName: false}], 111 'react/jsx-no-bind': [ 112 1, 113 { 114 ignoreRefs: true, 115 allowFunctions: true, 116 allowArrowFunctions: true, 117 }, 118 ], 119 'react/jsx-no-comment-textnodes': 2, 120 'react/jsx-no-duplicate-props': 2, 121 'react/jsx-no-target-blank': 2, 122 'react/jsx-no-undef': 2, 123 'react/jsx-tag-spacing': [2, {beforeSelfClosing: 'always'}], 124 'react/jsx-uses-react': 1, // debatable 125 'react/jsx-uses-vars': 2, 126 'react/jsx-key': [2, {checkFragmentShorthand: true}], 127 'react/self-closing-comp': 2, 128 'react/prefer-es6-class': 2, 129 'react/prefer-stateless-function': 1, 130 'react/require-render-return': 2, 131 'react/no-danger': 1, 132 133 // Legacy APIs not supported in Preact: 134 'react/no-did-mount-set-state': 2, 135 'react/no-did-update-set-state': 2, 136 'react/no-find-dom-node': 2, 137 'react/no-is-mounted': 2, 138 'react/no-string-refs': 2, 139 140 // hooks 141 'reactHooks/rules-of-hooks': 2, 142 'reactHooks/exhaustive-deps': 1, 143 }, 144 }, 145 146 // tests don't have jsdoc requirements 147 { 148 files: ['src/**/*.spec.{js,jsx}'], 149 rules: {}, 150 }, 151 152 // json (with comments in some files) 153 { 154 files: ['**/*.json'], 155 ignores: ['package-lock.json'], 156 157 plugins: {json}, 158 language: 'json/json', 159 extends: [json.configs.recommended], 160 }, 161 { 162 files: ['tsconfig.json'], 163 language: 'json/jsonc', 164 }, 165 166 // prettier last, so it can turn everything off 167 prettier, 168)