eslint.config.mjs99 lines · main
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
16import js from '@eslint/js';
17import globals from 'globals';
18import tseslint from 'typescript-eslint';
19
20export default [
21 // Ignore generated artefacts before any rule loads — saves multi-second
22 // walks of node_modules / .next / dist on every invocation.
23 {
24 ignores: [
25 '**/node_modules/**',
26 '**/.next/**',
27 '**/.turbo/**',
28 '**/dist/**',
29 '**/dist-pack/**',
30 '**/build/**',
31 '**/coverage/**',
32 '**/.pnpm-store/**',
33 '**/*.d.ts',
34 // Generated drizzle-kit migration snapshots — don't touch.
35 '**/drizzle/**',
36 ],
37 },
38
39 js.configs.recommended,
40 ...tseslint.configs.recommended,
41
42 // Globals — apply to every JS/TS file. node + browser is intentional;
43 // briven ships server-side (node/bun) and browser SDKs from the same
44 // tree, and our shared utilities target both.
45 {
46 languageOptions: {
47 globals: {
48 ...globals.node,
49 ...globals.browser,
50 },
51 },
52 },
53
54 // TS-specific overrides — the recommended set is conservative; we tighten
55 // the things that bit us during phase 0 and loosen the ones that produce
56 // friction without catching bugs.
57 {
58 files: ['**/*.{ts,tsx,mts,cts}'],
59 rules: {
60 // Enforce import-name correctness without forcing the type-checked
61 // ruleset.
62 '@typescript-eslint/no-unused-vars': [
63 'error',
64 { argsIgnorePattern: '^_', varsIgnorePattern: '^_', caughtErrorsIgnorePattern: '^_' },
65 ],
66 // we use `any` deliberately at boundary types where zod
67 // post-transform shapes are awkward — prefer `unknown` everywhere
68 // else, but warn rather than error so we can ship.
69 '@typescript-eslint/no-explicit-any': 'warn',
70 // Allow `@ts-ignore` etc. with a justification.
71 '@typescript-eslint/ban-ts-comment': [
72 'error',
73 { 'ts-ignore': 'allow-with-description', 'ts-expect-error': 'allow-with-description' },
74 ],
75 // `no-empty-object-type` triggers on Hono's standard `{ Variables: {...} }` pattern.
76 '@typescript-eslint/no-empty-object-type': 'off',
77 // Allow `require()` only in JS config files (next.config, etc.).
78 '@typescript-eslint/no-require-imports': 'error',
79 },
80 },
81
82 // CommonJS / config files — relax module rules.
83 {
84 files: ['**/*.{js,cjs}', '*.config.{js,ts,mjs,cjs}'],
85 rules: {
86 '@typescript-eslint/no-require-imports': 'off',
87 '@typescript-eslint/no-var-requires': 'off',
88 },
89 },
90
91 // Tests — slightly looser; allow `any` for fixture shapes.
92 {
93 files: ['**/*.test.{ts,tsx}', '**/*.spec.{ts,tsx}', '**/test-utils/**'],
94 rules: {
95 '@typescript-eslint/no-explicit-any': 'off',
96 '@typescript-eslint/no-non-null-assertion': 'off',
97 },
98 },
99];