Skip to content

Commit 85c9551

Browse files
authored
fix(backend): add and configure ESLint for backend workspace (#181)
1 parent 3b9e458 commit 85c9551

3 files changed

Lines changed: 1144 additions & 1 deletion

File tree

apps/backend/eslint.config.js

Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
import tseslint from 'typescript-eslint';
2+
import pluginN from 'eslint-plugin-n';
3+
import pluginImportX from 'eslint-plugin-import-x';
4+
import pluginPromise from 'eslint-plugin-promise';
5+
import pluginSecurity from 'eslint-plugin-security';
6+
import pluginUnicorn from 'eslint-plugin-unicorn';
7+
8+
export default tseslint.config(
9+
10+
// ─── Global Ignores ──────────────────────────────────────────────────────────
11+
{
12+
ignores: [
13+
'dist/**',
14+
'build/**',
15+
'node_modules/**',
16+
'coverage/**',
17+
'prisma/migrations/**',
18+
'**/*.d.ts',
19+
],
20+
},
21+
22+
// ─── Base: ESLint Recommended + TypeScript ──────────────────────────────────
23+
...tseslint.configs.recommendedTypeChecked,
24+
25+
// ─── Main Config ────────────────────────────────────────────────────────────
26+
{
27+
files: ['src/**/*.ts'],
28+
29+
languageOptions: {
30+
parserOptions: {
31+
projectService: true,
32+
tsconfigRootDir: import.meta.dirname,
33+
},
34+
},
35+
36+
plugins: {
37+
n: pluginN,
38+
'import-x': pluginImportX,
39+
promise: pluginPromise,
40+
security: pluginSecurity,
41+
unicorn: pluginUnicorn,
42+
},
43+
44+
settings: {
45+
'import-x/resolver': {
46+
typescript: { project: './tsconfig.json' },
47+
node: true,
48+
},
49+
node: { version: '>=18.0.0' },
50+
},
51+
52+
rules: {
53+
54+
// ── TypeScript: Type Safety: currently off ─────────────────────────────────────────────
55+
'@typescript-eslint/no-explicit-any': 'off',
56+
'@typescript-eslint/no-unsafe-argument': 'off',
57+
'@typescript-eslint/no-unsafe-assignment': 'off',
58+
'@typescript-eslint/no-unsafe-call': 'off',
59+
'@typescript-eslint/no-unsafe-member-access': 'off',
60+
'@typescript-eslint/no-unsafe-return': 'off',
61+
'@typescript-eslint/no-non-null-assertion': 'off',
62+
'@typescript-eslint/no-unnecessary-type-assertion': 'off',
63+
'@typescript-eslint/prefer-nullish-coalescing': 'off',
64+
'@typescript-eslint/prefer-optional-chain': 'off',
65+
'@typescript-eslint/strict-boolean-expressions': 'off',
66+
67+
// ── TypeScript: Async / Promises: currently off ────────────────────────────────────────
68+
'@typescript-eslint/no-floating-promises': 'off',
69+
'@typescript-eslint/no-misused-promises': 'off',
70+
'@typescript-eslint/await-thenable': 'off',
71+
'@typescript-eslint/require-await': 'off',
72+
'@typescript-eslint/return-await': 'off',
73+
74+
// ── TypeScript: Imports ─────────────────────────────────────────────────
75+
'@typescript-eslint/consistent-type-imports': [
76+
'error',
77+
{ prefer: 'type-imports', fixStyle: 'inline-type-imports' },
78+
],
79+
'@typescript-eslint/consistent-type-exports': 'error',
80+
'@typescript-eslint/no-import-type-side-effects': 'error',
81+
82+
// ── TypeScript: Code Quality ────────────────────────────────────────────
83+
'@typescript-eslint/no-unused-vars': [
84+
'error',
85+
{
86+
argsIgnorePattern: '^_',
87+
varsIgnorePattern: '^_',
88+
caughtErrorsIgnorePattern: '^_',
89+
},
90+
],
91+
'@typescript-eslint/explicit-function-return-type': [
92+
'warn',
93+
{
94+
allowExpressions: true,
95+
allowTypedFunctionExpressions: true,
96+
},
97+
],
98+
'@typescript-eslint/prefer-as-const': 'error',
99+
'@typescript-eslint/no-redundant-type-constituents': 'warn',
100+
'@typescript-eslint/no-shadow': 'error',
101+
'@typescript-eslint/no-use-before-define': ['error', { functions: false }],
102+
103+
// ── Node.js ─────────────────────────────────────────────────────────────
104+
'n/no-deprecated-api': 'error',
105+
'n/no-extraneous-import': 'error',
106+
'n/no-process-exit': 'off',
107+
'n/prefer-global/buffer': ['error', 'always'],
108+
'n/prefer-global/process': ['error', 'always'],
109+
'n/prefer-promises/fs': 'error',
110+
'n/prefer-promises/dns': 'error',
111+
'n/no-sync': 'warn',
112+
113+
// ── Imports (import-x) ──────────────────────────────────────────────────
114+
'import-x/no-duplicates': 'error',
115+
'import-x/no-cycle': 'off',
116+
'import-x/no-self-import': 'error',
117+
'import-x/first': 'error',
118+
'import-x/newline-after-import': 'error',
119+
'import-x/order': [
120+
'error',
121+
{
122+
groups: ['builtin', 'external', 'internal', 'parent', 'sibling', 'index', 'type'],
123+
'newlines-between': 'always',
124+
alphabetize: { order: 'asc', caseInsensitive: true },
125+
},
126+
],
127+
128+
// ── Promises ────────────────────────────────────────────────────────────
129+
'promise/always-return': 'off',
130+
'promise/catch-or-return': 'off',
131+
'promise/no-new-statics': 'error',
132+
'promise/no-return-wrap': 'error',
133+
'promise/param-names': 'error',
134+
'promise/no-promise-in-callback': 'warn',
135+
136+
// ── Security ────────────────────────────────────────────────────────────
137+
'security/detect-object-injection': 'off',
138+
'security/detect-non-literal-regexp': 'warn',
139+
'security/detect-non-literal-fs-filename': 'warn',
140+
'security/detect-eval-with-expression': 'error',
141+
'security/detect-child-process': 'warn',
142+
'security/detect-possible-timing-attacks': 'warn',
143+
144+
// ── Unicorn ─────────────────────────────────────────────────────────────
145+
'unicorn/prefer-node-protocol': 'error',
146+
'unicorn/no-process-exit': 'off',
147+
'unicorn/error-message': 'off',
148+
'unicorn/throw-new-error': 'off',
149+
'unicorn/no-useless-undefined': 'off',
150+
'unicorn/prefer-string-slice': 'warn',
151+
'unicorn/no-for-loop': 'off',
152+
'unicorn/prefer-includes': 'warn',
153+
'unicorn/no-array-for-each': 'off',
154+
'unicorn/prefer-ternary': 'off',
155+
'unicorn/prevent-abbreviations': 'off',
156+
157+
// ── Core ESLint ─────────────────────────────────────────────────────────
158+
'no-console': 'warn',
159+
'eqeqeq': ['error', 'always'],
160+
'no-var': 'error',
161+
'prefer-const': 'error',
162+
'no-throw-literal': 'error',
163+
'curly': ['error', 'all'],
164+
'object-shorthand': 'error',
165+
'no-lonely-if': 'warn',
166+
'no-nested-ternary': 'off',
167+
'prefer-rest-params': 'error',
168+
'prefer-spread': 'error',
169+
'no-param-reassign': [
170+
'error',
171+
{
172+
props: true,
173+
ignorePropertyModificationsFor: ['acc', 'request', 'reply'],
174+
},
175+
],
176+
},
177+
},
178+
179+
// ─── Test File Overrides ────────────────────────────────────────────────────
180+
{
181+
files: ['**/*.test.ts', '**/*.spec.ts', 'src/__tests__/**/*.ts'],
182+
rules: {
183+
'@typescript-eslint/no-explicit-any': 'off',
184+
'@typescript-eslint/no-unsafe-assignment': 'off',
185+
'@typescript-eslint/no-unsafe-member-access': 'off',
186+
'@typescript-eslint/no-non-null-assertion': 'off',
187+
'@typescript-eslint/no-floating-promises': 'off',
188+
'security/detect-object-injection': 'off',
189+
'no-console': 'off',
190+
},
191+
},
192+
193+
// ─── Prisma Seed / Scripts Override ────────────────────────────────────────
194+
{
195+
files: ['prisma/**/*.ts', 'scripts/**/*.ts'],
196+
rules: {
197+
'n/no-process-exit': 'off',
198+
'unicorn/no-process-exit': 'off',
199+
'no-console': 'off',
200+
},
201+
},
202+
);

apps/backend/package.json

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
"start": "node dist/server.js",
1010
"test": "vitest run",
1111
"test:watch": "vitest",
12+
"lint:fix": "eslint src/ --fix",
1213
"lint": "eslint src/",
1314
"db:migrate": "prisma migrate dev",
1415
"db:deploy": "prisma migrate deploy",
@@ -34,10 +35,18 @@
3435
"devDependencies": {
3536
"@types/node": "^22.0.0",
3637
"@types/qrcode": "^1.5.0",
38+
"eslint": "^10.4.0",
39+
"eslint-import-resolver-typescript": "^4.4.4",
40+
"eslint-plugin-import-x": "^4.16.2",
41+
"eslint-plugin-n": "^18.0.1",
42+
"eslint-plugin-promise": "^7.3.0",
43+
"eslint-plugin-security": "^4.0.0",
44+
"eslint-plugin-unicorn": "^64.0.0",
3745
"pino-pretty": "^13.1.3",
3846
"prisma": "^6.0.0",
3947
"tsx": "^4.0.0",
4048
"typescript": "^5.4.0",
49+
"typescript-eslint": "^8.59.3",
4150
"vitest": "^2.0.0"
4251
}
43-
}
52+
}

0 commit comments

Comments
 (0)