@zerly/eslint-config 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +108 -0
- package/package.json +59 -0
- package/src/configs/base.d.ts +14 -0
- package/src/configs/base.js +149 -0
- package/src/configs/base.js.map +1 -0
- package/src/configs/jsdoc.d.ts +8 -0
- package/src/configs/jsdoc.js +48 -0
- package/src/configs/jsdoc.js.map +1 -0
- package/src/configs/nestjs.d.ts +18 -0
- package/src/configs/nestjs.js +43 -0
- package/src/configs/nestjs.js.map +1 -0
- package/src/configs/typescript.d.ts +12 -0
- package/src/configs/typescript.js +177 -0
- package/src/configs/typescript.js.map +1 -0
- package/src/index.d.ts +5 -0
- package/src/index.js +5 -0
- package/src/index.js.map +1 -0
package/README.md
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# @zerly/eslint-config
|
|
2
|
+
|
|
3
|
+
Opinionated [ESLint flat config](https://eslint.org/docs/latest/use/configure/configuration-files) preset for NestJS + TypeScript projects.
|
|
4
|
+
|
|
5
|
+
## What's included
|
|
6
|
+
|
|
7
|
+
| Plugin | Rules |
|
|
8
|
+
|----------------------------|---------------------------------------------------------------------|
|
|
9
|
+
| `typescript-eslint` | Strict type-aware rules, naming conventions, explicit return types |
|
|
10
|
+
| `eslint-plugin-sonarjs` | Code smell detection, cognitive complexity |
|
|
11
|
+
| `eslint-plugin-rxjs-x` | RxJS best practices (no floating observables, no nested subscribes) |
|
|
12
|
+
| `eslint-plugin-unicorn` | Modern JS patterns, `node:` protocol enforcement |
|
|
13
|
+
| `eslint-plugin-security` | Common backend vulnerability patterns |
|
|
14
|
+
| `eslint-plugin-no-secrets` | Accidentally committed credentials detection |
|
|
15
|
+
| `eslint-plugin-import-x` | Import ordering and deduplication |
|
|
16
|
+
| `eslint-plugin-jsdoc` | JSDoc validation (validate existing, not require everywhere) |
|
|
17
|
+
| `eslint-plugin-prettier` | Prettier integration |
|
|
18
|
+
| `eslint-config-prettier` | Disables formatting rules that conflict with Prettier |
|
|
19
|
+
|
|
20
|
+
## Installation
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
npm install -D @zerly/eslint-config
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
All plugins are bundled as direct dependencies — no extra installs needed.
|
|
27
|
+
|
|
28
|
+
## Usage
|
|
29
|
+
|
|
30
|
+
```js
|
|
31
|
+
// eslint.config.mjs
|
|
32
|
+
import { defineNestjsConfig } from '@zerly/eslint-config';
|
|
33
|
+
|
|
34
|
+
export default [
|
|
35
|
+
...defineNestjsConfig({ tsconfigRootDir: import.meta.dirname }),
|
|
36
|
+
];
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### With Nx
|
|
40
|
+
|
|
41
|
+
Nx-specific rules (`enforce-module-boundaries`, `dependency-checks`) stay in your own config:
|
|
42
|
+
|
|
43
|
+
```js
|
|
44
|
+
// eslint.config.mjs
|
|
45
|
+
import nx from '@nx/eslint-plugin';
|
|
46
|
+
import jsoncParser from 'jsonc-eslint-parser';
|
|
47
|
+
import { defineNestjsConfig } from '@zerly/eslint-config';
|
|
48
|
+
|
|
49
|
+
export default [
|
|
50
|
+
...nx.configs['flat/base'],
|
|
51
|
+
...nx.configs['flat/typescript'],
|
|
52
|
+
...nx.configs['flat/javascript'],
|
|
53
|
+
|
|
54
|
+
{
|
|
55
|
+
files: ['**/*.json'],
|
|
56
|
+
languageOptions: { parser: jsoncParser },
|
|
57
|
+
plugins: { '@nx': nx },
|
|
58
|
+
rules: {
|
|
59
|
+
'@nx/dependency-checks': ['error', { /* your options */ }],
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
|
|
63
|
+
{
|
|
64
|
+
files: ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx'],
|
|
65
|
+
plugins: { '@nx': nx },
|
|
66
|
+
rules: {
|
|
67
|
+
'@nx/enforce-module-boundaries': ['error', { /* your options */ }],
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
|
|
71
|
+
...defineNestjsConfig({ tsconfigRootDir: import.meta.dirname }),
|
|
72
|
+
];
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Options
|
|
76
|
+
|
|
77
|
+
```ts
|
|
78
|
+
interface ITypescriptConfigOptions {
|
|
79
|
+
/**
|
|
80
|
+
* Absolute path to the directory containing `tsconfig.base.json`.
|
|
81
|
+
* Pass `import.meta.dirname` from your root ESLint config.
|
|
82
|
+
*/
|
|
83
|
+
tsconfigRootDir: string;
|
|
84
|
+
}
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Individual configs
|
|
88
|
+
|
|
89
|
+
For fine-grained control, each config layer is exported separately:
|
|
90
|
+
|
|
91
|
+
```js
|
|
92
|
+
import {
|
|
93
|
+
baseConfig, // common JS/TS rules
|
|
94
|
+
typescriptConfig, // type-aware @typescript-eslint rules
|
|
95
|
+
jsdocConfig, // JSDoc validation
|
|
96
|
+
sonarjsConfig, // SonarJS recommended
|
|
97
|
+
ignoresConfig, // default ignores (node_modules, dist, .nx…)
|
|
98
|
+
} from '@zerly/eslint-config';
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## Notable conventions
|
|
102
|
+
|
|
103
|
+
- **Interface prefix** — interfaces must be prefixed with `I` (`IUserService`, not `UserService`)
|
|
104
|
+
- **Explicit accessibility** — all class members require explicit `public`/`private`/`protected`
|
|
105
|
+
- **No floating promises** — unhandled promises are errors; use `void` to explicitly ignore
|
|
106
|
+
- **No floating observables** — RxJS observables must be subscribed, returned, or marked `void`
|
|
107
|
+
- **`node:` protocol** — all Node.js built-in imports must use the explicit `node:` prefix
|
|
108
|
+
- **`return await` in try/catch** — required so rejections are caught by the surrounding block
|
package/package.json
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@zerly/eslint-config",
|
|
3
|
+
"version": "0.6.0",
|
|
4
|
+
"description": "Opinionated ESLint flat config preset for Zerly / NestJS projects",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "git+https://github.com/HorizonRepublic/zerly.git",
|
|
8
|
+
"directory": "libs/eslint-config"
|
|
9
|
+
},
|
|
10
|
+
"homepage": "https://github.com/HorizonRepublic/zerly/blob/main/libs/eslint-config/README.md",
|
|
11
|
+
"bugs": {
|
|
12
|
+
"url": "https://github.com/HorizonRepublic/zerly/issues"
|
|
13
|
+
},
|
|
14
|
+
"publishConfig": {
|
|
15
|
+
"access": "public"
|
|
16
|
+
},
|
|
17
|
+
"keywords": [
|
|
18
|
+
"nestjs",
|
|
19
|
+
"typescript",
|
|
20
|
+
"eslint",
|
|
21
|
+
"eslint-config",
|
|
22
|
+
"zerly",
|
|
23
|
+
"framework",
|
|
24
|
+
"library"
|
|
25
|
+
],
|
|
26
|
+
"author": {
|
|
27
|
+
"name": "Horizon Republic",
|
|
28
|
+
"url": "https://github.com/HorizonRepublic"
|
|
29
|
+
},
|
|
30
|
+
"license": "MIT",
|
|
31
|
+
"type": "module",
|
|
32
|
+
"main": "./dist/index.js",
|
|
33
|
+
"types": "./dist/index.d.ts",
|
|
34
|
+
"exports": {
|
|
35
|
+
".": {
|
|
36
|
+
"import": "./dist/index.js",
|
|
37
|
+
"types": "./dist/index.d.ts"
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
"peerDependencies": {
|
|
41
|
+
"eslint": ">=9.0.0",
|
|
42
|
+
"typescript": ">=5.0.0"
|
|
43
|
+
},
|
|
44
|
+
"dependencies": {
|
|
45
|
+
"eslint-config-prettier": "^10.1.8",
|
|
46
|
+
"eslint-plugin-import-x": "^4.16.1",
|
|
47
|
+
"eslint-plugin-jsdoc": "^62.7.1",
|
|
48
|
+
"eslint-plugin-no-secrets": "^2.2.2",
|
|
49
|
+
"eslint-plugin-prefer-arrow": "^1.2.3",
|
|
50
|
+
"eslint-plugin-prettier": "^5.5.5",
|
|
51
|
+
"eslint-plugin-rxjs-x": "^1.0.0",
|
|
52
|
+
"eslint-plugin-security": "^4.0.0",
|
|
53
|
+
"eslint-plugin-sonarjs": "^3.0.7",
|
|
54
|
+
"eslint-plugin-unicorn": "^63.0.0",
|
|
55
|
+
"eslint-plugin-unused-imports": "^4.4.1",
|
|
56
|
+
"typescript-eslint": "^8.55.0"
|
|
57
|
+
},
|
|
58
|
+
"module": "./src/index.js"
|
|
59
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Linter } from 'eslint';
|
|
2
|
+
/** Common ignores for all Zerly projects. Can be extended by the consumer. */
|
|
3
|
+
export declare const ignoresConfig: Linter.Config;
|
|
4
|
+
/** SonarJS recommended rules scoped to JS/TS files. */
|
|
5
|
+
export declare const sonarjsConfig: Linter.Config;
|
|
6
|
+
/**
|
|
7
|
+
* Base rules for all JS/TS files.
|
|
8
|
+
*
|
|
9
|
+
* Includes: import ordering, code structure, unicorn patterns,
|
|
10
|
+
* security checks, secret detection, and Prettier integration.
|
|
11
|
+
* Does NOT include type-aware rules — those live in `typescriptConfig`.
|
|
12
|
+
*/
|
|
13
|
+
export declare const baseConfig: Linter.Config;
|
|
14
|
+
export { default as eslintConfigPrettier } from 'eslint-config-prettier';
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import importPlugin from 'eslint-plugin-import-x';
|
|
2
|
+
import noSecrets from 'eslint-plugin-no-secrets';
|
|
3
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
4
|
+
// @ts-expect-error
|
|
5
|
+
import preferArrowPlugin from 'eslint-plugin-prefer-arrow';
|
|
6
|
+
import eslintPluginPrettier from 'eslint-plugin-prettier';
|
|
7
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
8
|
+
// @ts-expect-error
|
|
9
|
+
import security from 'eslint-plugin-security';
|
|
10
|
+
import sonarjs from 'eslint-plugin-sonarjs';
|
|
11
|
+
import unicorn from 'eslint-plugin-unicorn';
|
|
12
|
+
import unusedImports from 'eslint-plugin-unused-imports';
|
|
13
|
+
/** Common ignores for all Zerly projects. Can be extended by the consumer. */
|
|
14
|
+
export const ignoresConfig = {
|
|
15
|
+
ignores: [
|
|
16
|
+
'**/node_modules/**',
|
|
17
|
+
'**/dist/**',
|
|
18
|
+
'**/.nx/**',
|
|
19
|
+
'**/tmp/**',
|
|
20
|
+
'**/.docusaurus/**',
|
|
21
|
+
'**/webpack.config.js',
|
|
22
|
+
],
|
|
23
|
+
};
|
|
24
|
+
/** SonarJS recommended rules scoped to JS/TS files. */
|
|
25
|
+
export const sonarjsConfig = {
|
|
26
|
+
...sonarjs.configs.recommended,
|
|
27
|
+
files: ['**/*.{js,jsx,ts,tsx}'],
|
|
28
|
+
rules: {
|
|
29
|
+
...sonarjs.configs.recommended.rules,
|
|
30
|
+
'sonarjs/todo-tag': 'off',
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Base rules for all JS/TS files.
|
|
35
|
+
*
|
|
36
|
+
* Includes: import ordering, code structure, unicorn patterns,
|
|
37
|
+
* security checks, secret detection, and Prettier integration.
|
|
38
|
+
* Does NOT include type-aware rules — those live in `typescriptConfig`.
|
|
39
|
+
*/
|
|
40
|
+
export const baseConfig = {
|
|
41
|
+
files: ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx'],
|
|
42
|
+
plugins: {
|
|
43
|
+
'prefer-arrow': preferArrowPlugin,
|
|
44
|
+
prettier: eslintPluginPrettier,
|
|
45
|
+
'unused-imports': unusedImports,
|
|
46
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
47
|
+
// @ts-expect-error
|
|
48
|
+
'import-x': importPlugin,
|
|
49
|
+
unicorn,
|
|
50
|
+
security,
|
|
51
|
+
'no-secrets': noSecrets,
|
|
52
|
+
},
|
|
53
|
+
rules: {
|
|
54
|
+
// Naming conventions
|
|
55
|
+
camelcase: ['error', { ignoreDestructuring: false, properties: 'never' }],
|
|
56
|
+
// Import ordering and deduplication
|
|
57
|
+
'import-x/newline-after-import': ['error', { count: 1 }],
|
|
58
|
+
'import-x/no-duplicates': 'error',
|
|
59
|
+
'import-x/order': [
|
|
60
|
+
'error',
|
|
61
|
+
{
|
|
62
|
+
groups: ['builtin', 'external', 'internal', 'parent', 'sibling', 'index', 'type'],
|
|
63
|
+
pathGroups: [
|
|
64
|
+
{ pattern: '@nestjs/**', group: 'external', position: 'before' },
|
|
65
|
+
{ pattern: '@nestia/**', group: 'external', position: 'before' },
|
|
66
|
+
{ pattern: '@angular/**', group: 'external', position: 'before' },
|
|
67
|
+
{ pattern: '@zerly/**', group: 'internal', position: 'before' },
|
|
68
|
+
],
|
|
69
|
+
pathGroupsExcludedImportTypes: ['builtin', 'type'],
|
|
70
|
+
'newlines-between': 'always',
|
|
71
|
+
alphabetize: { order: 'asc', caseInsensitive: true },
|
|
72
|
+
},
|
|
73
|
+
],
|
|
74
|
+
// Function structure rules
|
|
75
|
+
'lines-between-class-members': [
|
|
76
|
+
'error',
|
|
77
|
+
{
|
|
78
|
+
enforce: [
|
|
79
|
+
{ blankLine: 'always', next: 'method', prev: 'method' },
|
|
80
|
+
{ blankLine: 'always', next: 'method', prev: 'field' },
|
|
81
|
+
],
|
|
82
|
+
},
|
|
83
|
+
{ exceptAfterSingleLine: true },
|
|
84
|
+
],
|
|
85
|
+
'max-depth': ['warn', 4],
|
|
86
|
+
// General code quality
|
|
87
|
+
'no-alert': 'error',
|
|
88
|
+
'no-console': ['warn', { allow: ['warn', 'error'] }],
|
|
89
|
+
'no-debugger': 'error',
|
|
90
|
+
'no-duplicate-imports': 'off',
|
|
91
|
+
'no-useless-constructor': 'error',
|
|
92
|
+
'no-useless-return': 'error',
|
|
93
|
+
'no-var': 'error',
|
|
94
|
+
// Code formatting & padding
|
|
95
|
+
'padding-line-between-statements': [
|
|
96
|
+
'error',
|
|
97
|
+
{ blankLine: 'always', next: '*', prev: ['const', 'let', 'var'] },
|
|
98
|
+
{ blankLine: 'any', next: ['const', 'let', 'var'], prev: ['const', 'let', 'var'] },
|
|
99
|
+
{ blankLine: 'always', next: '*', prev: 'import' },
|
|
100
|
+
{ blankLine: 'any', next: 'import', prev: 'import' },
|
|
101
|
+
{ blankLine: 'always', next: 'function', prev: '*' },
|
|
102
|
+
{ blankLine: 'always', next: 'class', prev: '*' },
|
|
103
|
+
{ blankLine: 'always', next: 'export', prev: '*' },
|
|
104
|
+
{ blankLine: 'always', next: '*', prev: 'block-like' },
|
|
105
|
+
],
|
|
106
|
+
'prefer-arrow-callback': 'error',
|
|
107
|
+
'prefer-arrow/prefer-arrow-functions': [
|
|
108
|
+
'error',
|
|
109
|
+
{
|
|
110
|
+
classPropertiesAllowed: false,
|
|
111
|
+
disallowPrototype: true,
|
|
112
|
+
singleReturnOnly: false,
|
|
113
|
+
},
|
|
114
|
+
],
|
|
115
|
+
'prefer-const': 'error',
|
|
116
|
+
'prefer-template': 'error',
|
|
117
|
+
// Prettier integration
|
|
118
|
+
'prettier/prettier': 'error',
|
|
119
|
+
// Node.js — prefer explicit node: protocol for builtins
|
|
120
|
+
'unicorn/prefer-node-protocol': 'error',
|
|
121
|
+
// Error handling quality
|
|
122
|
+
'unicorn/error-message': 'error',
|
|
123
|
+
'unicorn/throw-new-error': 'error',
|
|
124
|
+
'unicorn/prefer-optional-catch-binding': 'error',
|
|
125
|
+
// Cleaner code patterns
|
|
126
|
+
'unicorn/no-typeof-undefined': 'error',
|
|
127
|
+
'unicorn/no-useless-promise-resolve-reject': 'error',
|
|
128
|
+
'unicorn/prefer-export-from': ['error', { ignoreUsedVariables: true }],
|
|
129
|
+
// Security — catch common backend vulnerabilities
|
|
130
|
+
'security/detect-unsafe-regex': 'error',
|
|
131
|
+
'security/detect-eval-with-expression': 'error',
|
|
132
|
+
'security/detect-bidi-characters': 'error',
|
|
133
|
+
'security/detect-new-buffer': 'warn',
|
|
134
|
+
'security/detect-buffer-noassert': 'warn',
|
|
135
|
+
'security/detect-possible-timing-attacks': 'warn',
|
|
136
|
+
'security/detect-pseudoRandomBytes': 'warn',
|
|
137
|
+
// Too noisy / not applicable for TypeScript projects
|
|
138
|
+
'security/detect-object-injection': 'off',
|
|
139
|
+
'security/detect-non-literal-fs-filename': 'off',
|
|
140
|
+
'security/detect-non-literal-require': 'off',
|
|
141
|
+
'security/detect-non-literal-regexp': 'off',
|
|
142
|
+
'security/detect-no-csrf-before-method-override': 'off',
|
|
143
|
+
'security/detect-child-process': 'off',
|
|
144
|
+
// Prevent accidentally committed secrets (API keys, tokens, etc.)
|
|
145
|
+
'no-secrets/no-secrets': ['error', { tolerance: 4.5 }],
|
|
146
|
+
},
|
|
147
|
+
};
|
|
148
|
+
export { default as eslintConfigPrettier } from 'eslint-config-prettier';
|
|
149
|
+
//# sourceMappingURL=base.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base.js","sourceRoot":"","sources":["../../../../../libs/eslint-config/src/configs/base.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Linter } from 'eslint';
|
|
2
|
+
/**
|
|
3
|
+
* JSDoc validation for TypeScript files.
|
|
4
|
+
*
|
|
5
|
+
* Only validates existing JSDoc — does not require it everywhere.
|
|
6
|
+
* TypeScript handles types, so no `@param`/`@returns` type annotations needed.
|
|
7
|
+
*/
|
|
8
|
+
export declare const jsdocConfig: Linter.Config;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import jsdoc from 'eslint-plugin-jsdoc';
|
|
2
|
+
/**
|
|
3
|
+
* JSDoc validation for TypeScript files.
|
|
4
|
+
*
|
|
5
|
+
* Only validates existing JSDoc — does not require it everywhere.
|
|
6
|
+
* TypeScript handles types, so no `@param`/`@returns` type annotations needed.
|
|
7
|
+
*/
|
|
8
|
+
export const jsdocConfig = {
|
|
9
|
+
...jsdoc.configs['flat/recommended-typescript'],
|
|
10
|
+
files: ['**/*.ts', '**/*.tsx'],
|
|
11
|
+
rules: {
|
|
12
|
+
...jsdoc.configs['flat/recommended-typescript'].rules,
|
|
13
|
+
// --- Formatting & correctness (keep active) ---
|
|
14
|
+
'jsdoc/check-access': 'warn',
|
|
15
|
+
'jsdoc/check-alignment': 'warn',
|
|
16
|
+
'jsdoc/check-param-names': 'warn',
|
|
17
|
+
'jsdoc/check-tag-names': ['warn', { definedTags: ['final'] }],
|
|
18
|
+
'jsdoc/empty-tags': 'warn',
|
|
19
|
+
'jsdoc/multiline-blocks': 'warn',
|
|
20
|
+
'jsdoc/no-multi-asterisks': 'warn',
|
|
21
|
+
'jsdoc/tag-lines': 'warn',
|
|
22
|
+
// TypeScript handles types — never duplicate them in JSDoc
|
|
23
|
+
'jsdoc/no-types': 'error',
|
|
24
|
+
'jsdoc/no-defaults': 'warn',
|
|
25
|
+
// --- Do not require JSDoc on every declaration ---
|
|
26
|
+
// JSDoc is encouraged, not mandatory
|
|
27
|
+
'jsdoc/require-jsdoc': 'off',
|
|
28
|
+
'jsdoc/require-param': 'off',
|
|
29
|
+
'jsdoc/require-param-description': 'off',
|
|
30
|
+
'jsdoc/require-returns': 'off',
|
|
31
|
+
'jsdoc/require-returns-description': 'off',
|
|
32
|
+
'jsdoc/require-property': 'off',
|
|
33
|
+
'jsdoc/require-property-description': 'off',
|
|
34
|
+
'jsdoc/require-yields': 'off',
|
|
35
|
+
'jsdoc/require-yields-check': 'off',
|
|
36
|
+
'jsdoc/require-yields-type': 'off',
|
|
37
|
+
'jsdoc/require-throws-type': 'off',
|
|
38
|
+
'jsdoc/require-next-type': 'off',
|
|
39
|
+
'jsdoc/check-types': 'off',
|
|
40
|
+
'jsdoc/check-values': 'off',
|
|
41
|
+
'jsdoc/valid-types': 'off',
|
|
42
|
+
// TypeScript type-system rules handled by @typescript-eslint
|
|
43
|
+
'jsdoc/ts-no-empty-object-type': 'off',
|
|
44
|
+
'jsdoc/reject-any-type': 'off',
|
|
45
|
+
'jsdoc/reject-function-type': 'off',
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
//# sourceMappingURL=jsdoc.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jsdoc.js","sourceRoot":"","sources":["../../../../../libs/eslint-config/src/configs/jsdoc.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,qBAAqB,CAAC;AAIxC;;;;;GAKG;AACH,MAAM,CAAC,MAAM,WAAW,GAAkB;IACxC,GAAG,KAAK,CAAC,OAAO,CAAC,6BAA6B,CAAC;IAC/C,KAAK,EAAE,CAAC,SAAS,EAAE,UAAU,CAAC;IAC9B,KAAK,EAAE;QACL,GAAG,KAAK,CAAC,OAAO,CAAC,6BAA6B,CAAC,CAAC,KAAK;QAErD,iDAAiD;QACjD,oBAAoB,EAAE,MAAM;QAC5B,uBAAuB,EAAE,MAAM;QAC/B,yBAAyB,EAAE,MAAM;QACjC,uBAAuB,EAAE,CAAC,MAAM,EAAE,EAAE,WAAW,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;QAC7D,kBAAkB,EAAE,MAAM;QAC1B,wBAAwB,EAAE,MAAM;QAChC,0BAA0B,EAAE,MAAM;QAClC,iBAAiB,EAAE,MAAM;QAEzB,2DAA2D;QAC3D,gBAAgB,EAAE,OAAO;QACzB,mBAAmB,EAAE,MAAM;QAE3B,oDAAoD;QACpD,qCAAqC;QACrC,qBAAqB,EAAE,KAAK;QAC5B,qBAAqB,EAAE,KAAK;QAC5B,iCAAiC,EAAE,KAAK;QACxC,uBAAuB,EAAE,KAAK;QAC9B,mCAAmC,EAAE,KAAK;QAC1C,wBAAwB,EAAE,KAAK;QAC/B,oCAAoC,EAAE,KAAK;QAC3C,sBAAsB,EAAE,KAAK;QAC7B,4BAA4B,EAAE,KAAK;QACnC,2BAA2B,EAAE,KAAK;QAClC,2BAA2B,EAAE,KAAK;QAClC,yBAAyB,EAAE,KAAK;QAChC,mBAAmB,EAAE,KAAK;QAC1B,oBAAoB,EAAE,KAAK;QAC3B,mBAAmB,EAAE,KAAK;QAE1B,6DAA6D;QAC7D,+BAA+B,EAAE,KAAK;QACtC,uBAAuB,EAAE,KAAK;QAC9B,4BAA4B,EAAE,KAAK;KACpC;CACF,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type ITypescriptConfigOptions } from './typescript.js';
|
|
2
|
+
import type { Linter } from 'eslint';
|
|
3
|
+
/**
|
|
4
|
+
* Full NestJS preset: TypeScript + RxJS + sonarjs + JSDoc + prettier.
|
|
5
|
+
*
|
|
6
|
+
* Pass `tsconfigRootDir: import.meta.dirname` from the consumer's root ESLint config.
|
|
7
|
+
* @example
|
|
8
|
+
* ```js
|
|
9
|
+
* // eslint.config.mjs
|
|
10
|
+
* import { defineNestjsConfig } from '@zerly/eslint-config';
|
|
11
|
+
*
|
|
12
|
+
* export default [
|
|
13
|
+
* ...nxConfigs,
|
|
14
|
+
* ...defineNestjsConfig({ tsconfigRootDir: import.meta.dirname }),
|
|
15
|
+
* ];
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
export declare const defineNestjsConfig: (options: ITypescriptConfigOptions) => Linter.Config[];
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import eslintConfigPrettier from 'eslint-config-prettier';
|
|
2
|
+
import tseslint from 'typescript-eslint';
|
|
3
|
+
import { baseConfig, ignoresConfig, sonarjsConfig } from './base.js';
|
|
4
|
+
import { jsdocConfig } from './jsdoc.js';
|
|
5
|
+
import { typescriptConfig } from './typescript.js';
|
|
6
|
+
/** Override to disable naming rules in jest config files. */
|
|
7
|
+
const jestOverride = {
|
|
8
|
+
files: ['jest.config.*'],
|
|
9
|
+
rules: {
|
|
10
|
+
'@typescript-eslint/naming-convention': 'off',
|
|
11
|
+
camelcase: 'off',
|
|
12
|
+
},
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Full NestJS preset: TypeScript + RxJS + sonarjs + JSDoc + prettier.
|
|
16
|
+
*
|
|
17
|
+
* Pass `tsconfigRootDir: import.meta.dirname` from the consumer's root ESLint config.
|
|
18
|
+
* @example
|
|
19
|
+
* ```js
|
|
20
|
+
* // eslint.config.mjs
|
|
21
|
+
* import { defineNestjsConfig } from '@zerly/eslint-config';
|
|
22
|
+
*
|
|
23
|
+
* export default [
|
|
24
|
+
* ...nxConfigs,
|
|
25
|
+
* ...defineNestjsConfig({ tsconfigRootDir: import.meta.dirname }),
|
|
26
|
+
* ];
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
export const defineNestjsConfig = (options) => [
|
|
30
|
+
...tseslint.configs.strict,
|
|
31
|
+
sonarjsConfig,
|
|
32
|
+
ignoresConfig,
|
|
33
|
+
baseConfig,
|
|
34
|
+
typescriptConfig(options),
|
|
35
|
+
jsdocConfig,
|
|
36
|
+
jestOverride,
|
|
37
|
+
// `typescript-eslint/recommended` has no `files` restriction and enables this rule globally.
|
|
38
|
+
// jsonc-eslint-parser wraps JSON root in an ExpressionStatement, so we suppress it for JSON.
|
|
39
|
+
{ files: ['**/*.json'], rules: { '@typescript-eslint/no-unused-expressions': 'off' } },
|
|
40
|
+
// Must be last — disables ESLint rules that conflict with Prettier formatting
|
|
41
|
+
eslintConfigPrettier,
|
|
42
|
+
];
|
|
43
|
+
//# sourceMappingURL=nestjs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nestjs.js","sourceRoot":"","sources":["../../../../../libs/eslint-config/src/configs/nestjs.ts"],"names":[],"mappings":"AAAA,OAAO,oBAAoB,MAAM,wBAAwB,CAAC;AAC1D,OAAO,QAAQ,MAAM,mBAAmB,CAAC;AAEzC,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AACrE,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,EAAE,gBAAgB,EAAiC,MAAM,iBAAiB,CAAC;AAIlF,6DAA6D;AAC7D,MAAM,YAAY,GAAkB;IAClC,KAAK,EAAE,CAAC,eAAe,CAAC;IACxB,KAAK,EAAE;QACL,sCAAsC,EAAE,KAAK;QAC7C,SAAS,EAAE,KAAK;KACjB;CACF,CAAC;AAEF;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,OAAiC,EAAmB,EAAE,CAAC;IACxF,GAAG,QAAQ,CAAC,OAAO,CAAC,MAAM;IAC1B,aAAa;IACb,aAAa;IACb,UAAU;IACV,gBAAgB,CAAC,OAAO,CAAC;IACzB,WAAW;IACX,YAAY;IACZ,6FAA6F;IAC7F,6FAA6F;IAC7F,EAAE,KAAK,EAAE,CAAC,WAAW,CAAC,EAAE,KAAK,EAAE,EAAE,0CAA0C,EAAE,KAAK,EAAE,EAAE;IACtF,8EAA8E;IAC9E,oBAAoB;CACrB,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Linter } from 'eslint';
|
|
2
|
+
export interface ITypescriptConfigOptions {
|
|
3
|
+
/** Absolute path to the directory containing `tsconfig.base.json`. Pass `import.meta.dirname`. */
|
|
4
|
+
tsconfigRootDir: string;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Type-aware TypeScript rules.
|
|
8
|
+
*
|
|
9
|
+
* Requires `tsconfigRootDir` so that `@typescript-eslint` rules can access
|
|
10
|
+
* the TypeScript compiler for type information.
|
|
11
|
+
*/
|
|
12
|
+
export declare const typescriptConfig: (options: ITypescriptConfigOptions) => Linter.Config;
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import rxjsX from 'eslint-plugin-rxjs-x';
|
|
2
|
+
import unusedImports from 'eslint-plugin-unused-imports';
|
|
3
|
+
import tseslint from 'typescript-eslint';
|
|
4
|
+
/**
|
|
5
|
+
* Type-aware TypeScript rules.
|
|
6
|
+
*
|
|
7
|
+
* Requires `tsconfigRootDir` so that `@typescript-eslint` rules can access
|
|
8
|
+
* the TypeScript compiler for type information.
|
|
9
|
+
*/
|
|
10
|
+
export const typescriptConfig = (options) => ({
|
|
11
|
+
files: ['**/*.ts', '**/*.tsx'],
|
|
12
|
+
languageOptions: {
|
|
13
|
+
parser: tseslint.parser,
|
|
14
|
+
parserOptions: {
|
|
15
|
+
project: './tsconfig.base.json',
|
|
16
|
+
tsconfigRootDir: options.tsconfigRootDir,
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
plugins: {
|
|
20
|
+
'rxjs-x': rxjsX,
|
|
21
|
+
'unused-imports': unusedImports,
|
|
22
|
+
},
|
|
23
|
+
rules: {
|
|
24
|
+
'@typescript-eslint/array-type': ['error', { default: 'array' }],
|
|
25
|
+
'@typescript-eslint/consistent-type-definitions': ['error', 'interface'],
|
|
26
|
+
'@typescript-eslint/explicit-function-return-type': [
|
|
27
|
+
'error',
|
|
28
|
+
{
|
|
29
|
+
allowConciseArrowFunctionExpressionsStartingWithVoid: false,
|
|
30
|
+
allowDirectConstAssertionInArrowFunctions: true,
|
|
31
|
+
allowExpressions: false,
|
|
32
|
+
allowHigherOrderFunctions: true,
|
|
33
|
+
allowTypedFunctionExpressions: true,
|
|
34
|
+
},
|
|
35
|
+
],
|
|
36
|
+
'@typescript-eslint/explicit-member-accessibility': [
|
|
37
|
+
'error',
|
|
38
|
+
{
|
|
39
|
+
accessibility: 'explicit',
|
|
40
|
+
overrides: {
|
|
41
|
+
accessors: 'explicit',
|
|
42
|
+
constructors: 'explicit',
|
|
43
|
+
methods: 'explicit',
|
|
44
|
+
parameterProperties: 'off',
|
|
45
|
+
properties: 'explicit',
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
],
|
|
49
|
+
'@typescript-eslint/explicit-module-boundary-types': 'error',
|
|
50
|
+
'@typescript-eslint/member-ordering': [
|
|
51
|
+
'error',
|
|
52
|
+
{
|
|
53
|
+
default: [
|
|
54
|
+
'public-static-field',
|
|
55
|
+
'protected-static-field',
|
|
56
|
+
'private-static-field',
|
|
57
|
+
'public-instance-field',
|
|
58
|
+
'protected-instance-field',
|
|
59
|
+
'private-instance-field',
|
|
60
|
+
'public-abstract-field',
|
|
61
|
+
'protected-abstract-field',
|
|
62
|
+
'public-constructor',
|
|
63
|
+
'protected-constructor',
|
|
64
|
+
'private-constructor',
|
|
65
|
+
'public-static-method',
|
|
66
|
+
'protected-static-method',
|
|
67
|
+
'private-static-method',
|
|
68
|
+
'public-instance-method',
|
|
69
|
+
'protected-instance-method',
|
|
70
|
+
'private-instance-method',
|
|
71
|
+
'public-abstract-method',
|
|
72
|
+
'protected-abstract-method',
|
|
73
|
+
],
|
|
74
|
+
},
|
|
75
|
+
],
|
|
76
|
+
'@typescript-eslint/method-signature-style': ['error', 'method'],
|
|
77
|
+
'@typescript-eslint/naming-convention': [
|
|
78
|
+
'error',
|
|
79
|
+
// 1. Constants (UPPER_CASE), standard variables (camelCase), or "Enum-as-Const" (PascalCase)
|
|
80
|
+
{
|
|
81
|
+
selector: 'variable',
|
|
82
|
+
modifiers: ['const'],
|
|
83
|
+
format: ['UPPER_CASE', 'camelCase', 'PascalCase'],
|
|
84
|
+
filter: {
|
|
85
|
+
match: true,
|
|
86
|
+
regex: '^[A-Z][A-Z0-9_]*(_TOKEN|_KEY|_CONFIG)?$|^[a-z][a-zA-Z0-9]*$|^[A-Z][a-zA-Z0-9]*$',
|
|
87
|
+
},
|
|
88
|
+
},
|
|
89
|
+
// 2. Other variables (non-const) — only camelCase
|
|
90
|
+
{ selector: 'variable', format: ['camelCase'] },
|
|
91
|
+
// 3. Functions and parameters — camelCase
|
|
92
|
+
{ selector: 'function', format: ['camelCase'] },
|
|
93
|
+
{ selector: 'parameter', format: ['camelCase'], leadingUnderscore: 'allow' },
|
|
94
|
+
// 4. Classes, interfaces, types, enums — PascalCase
|
|
95
|
+
{ selector: 'typeLike', format: ['PascalCase'] },
|
|
96
|
+
{ selector: 'enumMember', format: ['PascalCase', 'UPPER_CASE'] },
|
|
97
|
+
{ selector: 'interface', format: ['PascalCase'], prefix: ['I'] },
|
|
98
|
+
// 5. Object properties — allow everything (for HTTP headers, enum-objects, etc.)
|
|
99
|
+
{ selector: 'objectLiteralProperty', format: null },
|
|
100
|
+
// 6. Class methods and accessors — camelCase
|
|
101
|
+
{
|
|
102
|
+
selector: 'memberLike',
|
|
103
|
+
modifiers: ['private'],
|
|
104
|
+
format: ['camelCase'],
|
|
105
|
+
leadingUnderscore: 'allow',
|
|
106
|
+
},
|
|
107
|
+
{ selector: 'memberLike', format: ['camelCase'] },
|
|
108
|
+
],
|
|
109
|
+
'max-params': 'off',
|
|
110
|
+
'@typescript-eslint/no-confusing-void-expression': 'error',
|
|
111
|
+
// Warn on usage of APIs marked @deprecated in TSDoc/JSDoc
|
|
112
|
+
'@typescript-eslint/no-deprecated': 'warn',
|
|
113
|
+
'@typescript-eslint/no-explicit-any': 'error',
|
|
114
|
+
// Catch unhandled promises — critical for NestJS async lifecycle methods
|
|
115
|
+
'@typescript-eslint/no-floating-promises': ['error', { ignoreVoid: true, ignoreIIFE: true }],
|
|
116
|
+
// Catch async functions passed where sync is expected (e.g. void callbacks)
|
|
117
|
+
'@typescript-eslint/no-misused-promises': 'error',
|
|
118
|
+
'@typescript-eslint/no-namespace': 'off',
|
|
119
|
+
'@typescript-eslint/no-non-null-assertion': 'error',
|
|
120
|
+
'@typescript-eslint/no-redundant-type-constituents': 'error',
|
|
121
|
+
// Flags `foo as Foo` when foo is already Foo — catches redundant casts
|
|
122
|
+
'@typescript-eslint/no-unnecessary-type-assertion': 'error',
|
|
123
|
+
'@typescript-eslint/no-unnecessary-condition': 'error',
|
|
124
|
+
'@typescript-eslint/no-unused-vars': 'off',
|
|
125
|
+
// TS-aware replacement for the base no-useless-constructor
|
|
126
|
+
'@typescript-eslint/no-useless-constructor': 'error',
|
|
127
|
+
'@typescript-eslint/no-useless-empty-export': 'error',
|
|
128
|
+
'@typescript-eslint/prefer-nullish-coalescing': 'error',
|
|
129
|
+
'@typescript-eslint/prefer-optional-chain': 'error',
|
|
130
|
+
'@typescript-eslint/prefer-readonly': 'error',
|
|
131
|
+
'@typescript-eslint/prefer-string-starts-ends-with': 'error',
|
|
132
|
+
// In try/catch, `return await` is required — otherwise rejections escape the block
|
|
133
|
+
'@typescript-eslint/return-await': ['error', 'in-try-catch'],
|
|
134
|
+
// async function without any await is almost always a mistake
|
|
135
|
+
'@typescript-eslint/require-await': 'error',
|
|
136
|
+
'@typescript-eslint/switch-exhaustiveness-check': 'error',
|
|
137
|
+
'@typescript-eslint/no-empty-function': 'off',
|
|
138
|
+
'@typescript-eslint/no-invalid-void-type': 'off',
|
|
139
|
+
// NestJS uses empty @Module() classes, static-only utility classes (ConfigBuilder etc.),
|
|
140
|
+
// and decorated classes as a core pattern — allow all three
|
|
141
|
+
'@typescript-eslint/no-extraneous-class': [
|
|
142
|
+
'error',
|
|
143
|
+
{ allowEmpty: true, allowWithDecorator: true, allowStaticOnly: true },
|
|
144
|
+
],
|
|
145
|
+
// catch (err) in RxJS callbacks should be typed as unknown, not implicit any
|
|
146
|
+
'@typescript-eslint/use-unknown-in-catch-callback-variable': 'error',
|
|
147
|
+
// Disable base rules replaced by TS-aware equivalents
|
|
148
|
+
camelcase: 'off',
|
|
149
|
+
'no-duplicate-imports': 'off',
|
|
150
|
+
'no-shadow': 'off',
|
|
151
|
+
'no-unused-vars': 'off',
|
|
152
|
+
'no-useless-constructor': 'off',
|
|
153
|
+
// Prevent variable shadowing — catches subtle bugs in nested scopes and callbacks
|
|
154
|
+
'@typescript-eslint/no-shadow': 'error',
|
|
155
|
+
// Reject with proper Error objects, not strings or arbitrary values
|
|
156
|
+
'@typescript-eslint/prefer-promise-reject-errors': 'error',
|
|
157
|
+
'unused-imports/no-unused-imports': 'error',
|
|
158
|
+
'unused-imports/no-unused-vars': [
|
|
159
|
+
'error',
|
|
160
|
+
{
|
|
161
|
+
args: 'after-used',
|
|
162
|
+
argsIgnorePattern: '^_',
|
|
163
|
+
ignoreRestSiblings: true,
|
|
164
|
+
vars: 'all',
|
|
165
|
+
varsIgnorePattern: '^_',
|
|
166
|
+
},
|
|
167
|
+
],
|
|
168
|
+
// RxJS best practices
|
|
169
|
+
'rxjs-x/no-async-subscribe': 'error',
|
|
170
|
+
'rxjs-x/no-nested-subscribe': 'error',
|
|
171
|
+
'rxjs-x/no-unsafe-takeuntil': 'error',
|
|
172
|
+
'rxjs-x/no-internal': 'error',
|
|
173
|
+
'rxjs-x/no-ignored-error': 'warn',
|
|
174
|
+
'rxjs-x/no-floating-observables': 'warn',
|
|
175
|
+
},
|
|
176
|
+
});
|
|
177
|
+
//# sourceMappingURL=typescript.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"typescript.js","sourceRoot":"","sources":["../../../../../libs/eslint-config/src/configs/typescript.ts"],"names":[],"mappings":"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"}
|
package/src/index.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { defineNestjsConfig } from './configs/nestjs.js';
|
|
2
|
+
export { baseConfig, ignoresConfig, sonarjsConfig } from './configs/base.js';
|
|
3
|
+
export { jsdocConfig } from './configs/jsdoc.js';
|
|
4
|
+
export { typescriptConfig } from './configs/typescript.js';
|
|
5
|
+
export type { ITypescriptConfigOptions } from './configs/typescript.js';
|
package/src/index.js
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { defineNestjsConfig } from './configs/nestjs.js';
|
|
2
|
+
export { baseConfig, ignoresConfig, sonarjsConfig } from './configs/base.js';
|
|
3
|
+
export { jsdocConfig } from './configs/jsdoc.js';
|
|
4
|
+
export { typescriptConfig } from './configs/typescript.js';
|
|
5
|
+
//# sourceMappingURL=index.js.map
|
package/src/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../libs/eslint-config/src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAEzD,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAE7E,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC"}
|