Skip to content

Commit c9f88b9

Browse files
authored
Migrate eslint v9 flat config (#15)
* Migrate eslint v9 flat config * Update eslint deps * Fix refactor lint
1 parent ac84d18 commit c9f88b9

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+3279
-3279
lines changed

.eslintrc

-83
This file was deleted.

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ If you focus on the performance or features of the module, you can consider:
1414
- or [Prisma](https://docs.nestjs.com/recipes/prisma)
1515
- [SWC](https://docs.nestjs.com/recipes/swc#swc) instead of `TypeScript compiler`
1616
- [Vitest](https://docs.nestjs.com/recipes/swc#vitest) instead of `Jest`
17+
- `CommonJS` instead of `ESM`
1718

1819
Check out the [nestjs-project-performance](https://github.com/CatsMiaow/nestjs-project-performance) repository for examples using this alternative.
1920

bin/entity.ts

+9-9
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
/* eslint-disable no-console, import/no-extraneous-dependencies */
1+
/* eslint-disable no-console, @typescript-eslint/triple-slash-reference */
22
/// <reference types="../typings/global" />
3-
import { spawnSync } from 'child_process';
43
import { config } from 'dotenv';
5-
import { readdirSync, writeFileSync } from 'fs';
6-
import { join as pathJoin } from 'path';
4+
import { spawnSync } from 'node:child_process';
5+
import { readdirSync, writeFileSync } from 'node:fs';
6+
import path from 'node:path';
77
import prompts from 'prompts';
88
import { rimrafSync } from 'rimraf';
99

@@ -31,7 +31,7 @@ if (!process.env.DB_HOST) {
3131
]);
3232

3333
const { db } = <{ db: string }>response;
34-
const MODEL_DIR = pathJoin(__dirname, '../src/entity', db);
34+
const MODEL_DIR = path.join(__dirname, '../src/entity', db);
3535
rimrafSync(`${MODEL_DIR}/*`);
3636

3737
const generatorConfig = [
@@ -40,7 +40,7 @@ if (!process.env.DB_HOST) {
4040
'--ce pascal', // class names
4141
'--cp none', // property names
4242
'--strictMode !', // strictPropertyInitialization
43-
`--namingStrategy ${pathJoin(__dirname, 'NamingStrategy.js')}`,
43+
`--namingStrategy ${path.join(__dirname, 'NamingStrategy.js')}`,
4444
`-h ${process.env.DB_HOST}`,
4545
`-p ${process.env.DB_PORT}`,
4646
// https://github.com/Kononnable/typeorm-model-generator/issues/204#issuecomment-533709527
@@ -61,14 +61,14 @@ if (!process.env.DB_HOST) {
6161
}
6262

6363
const files = [];
64-
readdirSync(MODEL_DIR).forEach((file: string) => {
64+
for (const file of readdirSync(MODEL_DIR)) {
6565
files.push(`export * from './${file.replace('.ts', '')}';`);
66-
});
66+
}
6767
files.push('');
6868
// export entity db tables
6969
// AS-IS import { Tablename } from './entity/dbname/tablename';
7070
// TO-BE import { Tablename } from './entity/dbname';
71-
writeFileSync(pathJoin(MODEL_DIR, 'index.ts'), files.join('\n'));
71+
writeFileSync(path.join(MODEL_DIR, 'index.ts'), files.join('\n'));
7272

7373
console.log(`> '${db}' database entities has been created: ${MODEL_DIR}`);
7474
})().catch((error: unknown) => {

bin/ormconfig.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
/* eslint-disable import/no-extraneous-dependencies */
1+
// eslint-disable-next-line @typescript-eslint/triple-slash-reference
22
/// <reference types="../typings/global" />
33
import * as dotenv from 'dotenv';
4-
import { DataSource, DataSourceOptions } from 'typeorm';
4+
import { DataSource, type DataSourceOptions } from 'typeorm';
55

66
import { configuration } from '../src/config';
77

eslint.config.js

+150
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
/* eslint-disable no-undef, @typescript-eslint/no-require-imports, @typescript-eslint/no-unused-vars */
2+
const eslint = require('@eslint/js');
3+
const importPlugin = require('eslint-plugin-import');
4+
const jest = require('eslint-plugin-jest');
5+
const prettierRecommended = require('eslint-plugin-prettier/recommended');
6+
const sonarjs = require('eslint-plugin-sonarjs');
7+
const tseslint = require('typescript-eslint');
8+
9+
// https://eslint.org/docs/latest/use/configure/configuration-files#typescript-configuration-files
10+
module.exports = (async function config() {
11+
const { default: stylistic } = await import('@stylistic/eslint-plugin');
12+
const { default: love } = await import('eslint-config-love');
13+
const { default: unicorn } = await import('eslint-plugin-unicorn');
14+
15+
return tseslint.config(
16+
eslint.configs.recommended,
17+
tseslint.configs.recommendedTypeChecked,
18+
tseslint.configs.strictTypeChecked,
19+
tseslint.configs.stylisticTypeChecked,
20+
love,
21+
stylistic.configs.recommended,
22+
prettierRecommended,
23+
unicorn.configs.recommended,
24+
sonarjs.configs.recommended,
25+
jest.configs['flat/recommended'],
26+
{
27+
ignores: ['**/node_modules/**', 'dist/**', 'src/entity/**'],
28+
},
29+
{
30+
languageOptions: {
31+
parserOptions: {
32+
// projectService: true,
33+
projectService: {
34+
allowDefaultProject: ['*.js'],
35+
},
36+
tsconfigRootDir: __dirname,
37+
},
38+
},
39+
plugins: {
40+
'@typescript-eslint': tseslint.plugin,
41+
jest,
42+
},
43+
// https://github.com/import-js/eslint-plugin-import?tab=readme-ov-file#config---flat-with-config-in-typescript-eslint
44+
// extends: [importPlugin.flatConfigs.recommended, importPlugin.flatConfigs.typescript],
45+
settings: {
46+
'import/resolver': {
47+
typescript: true,
48+
node: true,
49+
},
50+
},
51+
// These rules are for reference only.
52+
rules: {
53+
// #region eslint
54+
'class-methods-use-this': 'off',
55+
complexity: ['error', 20],
56+
// https://github.com/typescript-eslint/typescript-eslint/issues/1277
57+
'consistent-return': 'off',
58+
'eslint-comments/require-description': 'off',
59+
'func-names': 'off',
60+
'max-len': ['error', { code: 140, ignoreTemplateLiterals: true, ignoreUrls: true }],
61+
'newline-per-chained-call': 'off',
62+
'no-await-in-loop': 'off',
63+
'no-continue': 'off',
64+
// https://github.com/airbnb/javascript/issues/1342
65+
'no-param-reassign': ['error', { props: false }],
66+
// https://github.com/airbnb/javascript/issues/1271
67+
// https://github.com/airbnb/javascript/blob/fd77bbebb77362ddecfef7aba3bf6abf7bdd81f2/packages/eslint-config-airbnb-base/rules/style.js#L340-L358
68+
'no-restricted-syntax': ['error', 'ForInStatement', 'LabeledStatement', 'WithStatement'],
69+
'no-underscore-dangle': ['error', { allow: ['_id'] }],
70+
'no-void': ['error', { allowAsStatement: true }],
71+
'object-curly-newline': 'off',
72+
'spaced-comment': ['error', 'always', { line: { markers: ['/', '#region', '#endregion'] } }],
73+
// #endregion
74+
75+
// #region import
76+
'import/no-default-export': 'error',
77+
'import/order': [
78+
'error',
79+
{
80+
groups: [
81+
['builtin', 'external'],
82+
['internal', 'parent', 'sibling', 'index'],
83+
],
84+
'newlines-between': 'always',
85+
alphabetize: { order: 'asc', caseInsensitive: true },
86+
},
87+
],
88+
'import/prefer-default-export': 'off',
89+
// #endregion
90+
91+
// #region @typescript-eslint
92+
'@typescript-eslint/class-methods-use-this': 'off',
93+
'@typescript-eslint/consistent-type-assertions': ['error', { assertionStyle: 'angle-bracket' }],
94+
'@typescript-eslint/init-declarations': ['error', 'never', { ignoreForLoopInit: true }],
95+
'@typescript-eslint/naming-convention': [
96+
'error',
97+
{ selector: 'default', format: ['strictCamelCase'] },
98+
{ selector: 'variable', format: ['strictCamelCase', 'UPPER_CASE', 'StrictPascalCase'] },
99+
// https://github.com/microsoft/TypeScript/issues/9458
100+
{ selector: 'parameter', modifiers: ['unused'], format: ['strictCamelCase'], leadingUnderscore: 'allow' },
101+
{ selector: 'property', format: null },
102+
{ selector: 'typeProperty', format: null },
103+
{ selector: 'typeLike', format: ['StrictPascalCase'] },
104+
{ selector: 'enumMember', format: ['UPPER_CASE'] },
105+
],
106+
'@typescript-eslint/no-extraneous-class': 'off',
107+
'@typescript-eslint/no-magic-numbers': 'off',
108+
'@typescript-eslint/no-unsafe-member-access': 'off',
109+
'@typescript-eslint/no-unsafe-type-assertion': 'off',
110+
'@typescript-eslint/restrict-template-expressions': [
111+
'error',
112+
{ allowAny: true, allowBoolean: true, allowNullish: true, allowNumber: true, allowRegExp: true },
113+
],
114+
'@typescript-eslint/prefer-destructuring': 'off',
115+
'@typescript-eslint/prefer-readonly': 'off',
116+
'@typescript-eslint/strict-boolean-expressions': 'off',
117+
// #endregion
118+
119+
// #region stylistic
120+
'@stylistic/arrow-parens': ['error', 'always'],
121+
'@stylistic/brace-style': ['error', '1tbs'],
122+
'@stylistic/lines-between-class-members': ['error', 'always', { exceptAfterSingleLine: true }],
123+
'@stylistic/no-extra-parens': ['error', 'functions'],
124+
'@stylistic/object-curly-spacing': ['error', 'always'],
125+
'@stylistic/semi': ['error', 'always'],
126+
127+
// for prettier
128+
'@stylistic/indent': 'off',
129+
'@stylistic/keyword-spacing': 'off',
130+
'@stylistic/member-delimiter-style': 'off',
131+
'@stylistic/operator-linebreak': 'off',
132+
// #endregion
133+
134+
// #region sonarjs
135+
'sonarjs/cognitive-complexity': ['error', 25],
136+
'sonarjs/no-duplicate-string': 'off',
137+
'sonarjs/no-nested-assignment': 'off',
138+
// #endregion
139+
140+
// #region unicorn
141+
'unicorn/no-null': 'off',
142+
'unicorn/prevent-abbreviations': 'off',
143+
'unicorn/prefer-module': 'off',
144+
'unicorn/prefer-ternary': ['error', 'only-single-line'],
145+
'unicorn/prefer-top-level-await': 'off',
146+
// #endregion
147+
},
148+
},
149+
);
150+
})();

0 commit comments

Comments
 (0)