eslint.config.mjs 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. // Flat ESLint config for the briven monorepo. Intentionally narrow — we
  2. // only assert the rules that have caught real regressions in code review,
  3. // and we lean on TypeScript's `--noEmit` for everything ESLint would
  4. // otherwise duplicate.
  5. //
  6. // Why flat config:
  7. // - eslint v9+ defaults to flat; `eslintrc` is on its way out
  8. // - one file at the root drives every workspace; no per-package
  9. // copies to keep in sync
  10. //
  11. // Why we don't enable @typescript-eslint/recommended-type-checked:
  12. // - it requires `parserOptions.project` which makes lint orders of
  13. // magnitude slower and forces every `tsconfig.json` to opt in
  14. // - the rules it adds are largely redundant with TS strict mode
  15. import js from '@eslint/js';
  16. import globals from 'globals';
  17. import tseslint from 'typescript-eslint';
  18. export default [
  19. // Ignore generated artefacts before any rule loads — saves multi-second
  20. // walks of node_modules / .next / dist on every invocation.
  21. {
  22. ignores: [
  23. '**/node_modules/**',
  24. '**/.next/**',
  25. '**/.turbo/**',
  26. '**/dist/**',
  27. '**/dist-pack/**',
  28. '**/build/**',
  29. '**/coverage/**',
  30. '**/.pnpm-store/**',
  31. '**/*.d.ts',
  32. // Generated drizzle-kit migration snapshots — don't touch.
  33. '**/drizzle/**',
  34. ],
  35. },
  36. js.configs.recommended,
  37. ...tseslint.configs.recommended,
  38. // Globals — apply to every JS/TS file. node + browser is intentional;
  39. // briven ships server-side (node/bun) and browser SDKs from the same
  40. // tree, and our shared utilities target both.
  41. {
  42. languageOptions: {
  43. globals: {
  44. ...globals.node,
  45. ...globals.browser,
  46. },
  47. },
  48. },
  49. // TS-specific overrides — the recommended set is conservative; we tighten
  50. // the things that bit us during phase 0 and loosen the ones that produce
  51. // friction without catching bugs.
  52. {
  53. files: ['**/*.{ts,tsx,mts,cts}'],
  54. rules: {
  55. // Enforce import-name correctness without forcing the type-checked
  56. // ruleset.
  57. '@typescript-eslint/no-unused-vars': [
  58. 'error',
  59. { argsIgnorePattern: '^_', varsIgnorePattern: '^_', caughtErrorsIgnorePattern: '^_' },
  60. ],
  61. // we use `any` deliberately at boundary types where zod
  62. // post-transform shapes are awkward — prefer `unknown` everywhere
  63. // else, but warn rather than error so we can ship.
  64. '@typescript-eslint/no-explicit-any': 'warn',
  65. // Allow `@ts-ignore` etc. with a justification.
  66. '@typescript-eslint/ban-ts-comment': [
  67. 'error',
  68. { 'ts-ignore': 'allow-with-description', 'ts-expect-error': 'allow-with-description' },
  69. ],
  70. // `no-empty-object-type` triggers on Hono's standard `{ Variables: {...} }` pattern.
  71. '@typescript-eslint/no-empty-object-type': 'off',
  72. // Allow `require()` only in JS config files (next.config, etc.).
  73. '@typescript-eslint/no-require-imports': 'error',
  74. },
  75. },
  76. // CommonJS / config files — relax module rules.
  77. {
  78. files: ['**/*.{js,cjs}', '*.config.{js,ts,mjs,cjs}'],
  79. rules: {
  80. '@typescript-eslint/no-require-imports': 'off',
  81. '@typescript-eslint/no-var-requires': 'off',
  82. },
  83. },
  84. // Tests — slightly looser; allow `any` for fixture shapes.
  85. {
  86. files: ['**/*.test.{ts,tsx}', '**/*.spec.{ts,tsx}', '**/test-utils/**'],
  87. rules: {
  88. '@typescript-eslint/no-explicit-any': 'off',
  89. '@typescript-eslint/no-non-null-assertion': 'off',
  90. },
  91. },
  92. ];