eslint.config.js
Rama main · réplica de lectura del repositorio original.
import js from "@eslint/js";
import prettier from "eslint-config-prettier";
import svelte from "eslint-plugin-svelte";
import globals from "globals";
import ts from "typescript-eslint";
import svelteConfig from "./svelte.config.js";
import noPgOnlyApi from "./eslint-rules/no-pg-only-api.js";
import noQueryTerminals from "./eslint-rules/no-query-terminals.js";
const kept = {
rules: {
"no-query-terminals": noQueryTerminals,
"no-pg-only-api": noPgOnlyApi,
},
};
export default ts.config(
{
ignores: [
".svelte-kit/",
".claude/worktrees/",
"build/",
"coverage/",
"drizzle/",
"eslint-rules/fixtures/",
"src/lib/components/ui/",
],
},
js.configs.recommended,
...ts.configs.recommended,
...svelte.configs.recommended,
prettier,
...svelte.configs.prettier,
{
languageOptions: {
globals: { ...globals.browser, ...globals.node, Bun: "readonly" },
},
rules: {
"@typescript-eslint/no-explicit-any": "error",
"@typescript-eslint/no-unused-vars": [
"error",
{ argsIgnorePattern: "^_" },
],
"no-empty": ["error", { allowEmptyCatch: false }],
},
},
{
files: ["src/**/*.ts"],
languageOptions: {
parserOptions: {
projectService: true,
tsconfigRootDir: import.meta.dirname,
},
},
},
{
files: ["**/*.svelte", "**/*.svelte.ts", "**/*.svelte.js"],
languageOptions: {
parserOptions: {
projectService: true,
tsconfigRootDir: import.meta.dirname,
extraFileExtensions: [".svelte"],
parser: ts.parser,
svelteConfig,
},
},
},
{
// A forgotten await on a drizzle query builder silently drops the query,
// so these rules are errors. They need type information, so they run on
// TypeScript files only. `bun run lint` also lints the .ts files in a
// separate eslint process from everything else: mixed in one process,
// typescript-eslint rebuilds the checker whenever it alternates between
// .ts and .svelte files, which turns a ~75s run into ~9 minutes.
files: ["src/**/*.ts"],
rules: {
// drizzle's query builders implement PromiseLike without extending
// Promise, so they are only recognised with checkThenables.
"@typescript-eslint/no-floating-promises": [
"error",
{ checkThenables: true },
],
"@typescript-eslint/no-misused-promises": "error",
"@typescript-eslint/await-thenable": "error",
},
},
{
// Builders are awaited, never run through their sync-style terminals; see
// the rule for how a builder is recognised (by type, so Map.get is fine).
files: ["src/**/*.ts"],
plugins: { kept },
rules: { "kept/no-query-terminals": "error" },
},
{
// The schema and the queries are typed as pg-core but run on SQLite too, so
// the postgres-only api surface is banned (see the rule for the list).
files: ["src/**/*.ts"],
plugins: { kept },
rules: { "kept/no-pg-only-api": "error" },
},
{
// db/ is dialect code by nature: it may cast in raw SQL and import the
// drivers and the dialect-specific core packages.
files: ["src/lib/server/db/**/*.ts"],
rules: { "kept/no-pg-only-api": ["error", { dialectCode: true }] },
},
{
// Tests may run the migrator and open raw handles; their SQL must still be
// portable, because the suite also runs against PostgreSQL.
files: ["src/**/*.test.ts"],
ignores: ["src/lib/server/db/**"],
rules: { "kept/no-pg-only-api": ["error", { driverImports: true }] },
},
);