eslint.config.js
Rama main · réplica de lectura del repositorio original.
// Type-safety linting, focused. Biome owns formatting and base lint; this config
// adds ONLY the type-aware rules Biome cannot run (it does not connect to the
// type checker). Scope: server/ + shared/ production code — the API contract
// surface. The goal is to forbid the escape hatches that strict tsconfig allows:
// `any`, any-typed value flow, and type assertions that bypass the checker.
import tseslint from 'typescript-eslint'
export default tseslint.config(
{
ignores: [
'**/dist/**',
'**/node_modules/**',
'**/.wrangler/**',
'sdk/**',
'cmd/**',
'packages/runtime-bridge/**',
'migrations/**',
'src/**',
'e2e/**',
'scripts/**',
'**/*.config.*',
'vitest*.ts',
// Tests legitimately cast mocks; the contract surface is the target.
'**/*.test.ts',
// Excluded from tsconfig.server.json, so typed linting cannot resolve them.
'server/integration/**',
// E2E_TEST_AUTH-gated test endpoint; design §1.8 exempts /api/e2e/* from
// the v1 contract, and it builds partial test fixtures like real test files.
'server/http/e2e.ts',
],
},
{
files: ['server/**/*.ts', 'shared/**/*.ts'],
plugins: { '@typescript-eslint': tseslint.plugin },
languageOptions: {
parser: tseslint.parser,
parserOptions: { projectService: true, tsconfigRootDir: import.meta.dirname },
},
rules: {
// 1. No `any` — explicit or implicit re-introduction.
'@typescript-eslint/no-explicit-any': 'error',
// 2. No `any`-typed value flowing through the code (the contagion Biome misses).
'@typescript-eslint/no-unsafe-assignment': 'error',
'@typescript-eslint/no-unsafe-member-access': 'error',
'@typescript-eslint/no-unsafe-call': 'error',
'@typescript-eslint/no-unsafe-return': 'error',
'@typescript-eslint/no-unsafe-argument': 'error',
// 3. Prefer `satisfies` over object-literal `as` casts (the cast bypasses
// excess-property checks). A warning, not a block: at genuine trust
// boundaries and in partial test fixtures an assertion is the honest
// tool, and `satisfies` cannot express loose-record normalization.
'@typescript-eslint/consistent-type-assertions': [
'warn',
{ assertionStyle: 'as', objectLiteralTypeAssertions: 'never' },
],
// 4. Ban ONLY the `x as unknown as T` double cast — it launders a value
// through `unknown` to a type it does not overlap. The single
// `JSON.parse(x) as unknown` narrowing pattern is safe and stays allowed:
// the inner-as-unknown is matched only when it is the operand of an
// outer assertion.
'no-restricted-syntax': [
'error',
{
selector: 'TSAsExpression > TSAsExpression[typeAnnotation.type="TSUnknownKeyword"]',
message: 'No `as unknown as` double cast — validate at the boundary (zod) instead of telling the compiler to trust you.',
},
],
},
},
)