@yasainet/eslint 0.1.0 → 0.1.2
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 +106 -0
- package/package.json +5 -1
- package/src/index.mjs +3 -0
- package/src/jsdoc.mjs +46 -0
- package/src/naming.mjs +16 -0
- package/src/plugins.mjs +3 -0
package/README.md
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# @yasainet/eslint
|
|
2
|
+
|
|
3
|
+
Shared ESLint configuration for Next.js projects with feature-based architecture.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```sh
|
|
8
|
+
npm install -D @yasainet/eslint eslint eslint-config-next
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
```js
|
|
14
|
+
// eslint.config.mjs
|
|
15
|
+
import { eslintConfig } from "@yasainet/eslint";
|
|
16
|
+
|
|
17
|
+
export default eslintConfig;
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Rules
|
|
21
|
+
|
|
22
|
+
### Base
|
|
23
|
+
|
|
24
|
+
Next.js recommended presets (core-web-vitals + typescript) with additional rules:
|
|
25
|
+
|
|
26
|
+
- `@typescript-eslint/consistent-type-imports` — enforce `type` imports
|
|
27
|
+
- `@typescript-eslint/no-unused-vars` — disallow unused variables (allows `_` prefix)
|
|
28
|
+
- `no-console` — warn on `console.*`
|
|
29
|
+
- `simple-import-sort` — auto-sort imports/exports
|
|
30
|
+
- `@stylistic/quotes` — enforce double quotes
|
|
31
|
+
- `react-you-might-not-need-an-effect` — detect unnecessary `useEffect`
|
|
32
|
+
|
|
33
|
+
### Naming
|
|
34
|
+
|
|
35
|
+
Enforces file naming conventions inside `features/`:
|
|
36
|
+
|
|
37
|
+
| Directory | Pattern | Example |
|
|
38
|
+
| --------------- | -------------------- | ------------------ |
|
|
39
|
+
| `domains/` | `{prefix}.domain.ts` | `server.domain.ts` |
|
|
40
|
+
| `repositories/` | `{prefix}.repo.ts` | `server.repo.ts` |
|
|
41
|
+
| `actions/` | `{prefix}.action.ts` | `server.action.ts` |
|
|
42
|
+
| `hooks/` | `use{Name}.ts` | `useAuth.ts` |
|
|
43
|
+
| `types/` | `{name}.type.ts` | `comic.type.ts` |
|
|
44
|
+
| `schemas/` | `{name}.schema.ts` | `comic.schema.ts` |
|
|
45
|
+
| `util/` | `{name}.util.ts` | `format.util.ts` |
|
|
46
|
+
| `constants/` | `{name}.constant.ts` | `api.constant.ts` |
|
|
47
|
+
|
|
48
|
+
Additionally:
|
|
49
|
+
|
|
50
|
+
- `features/**` — `.ts` only (components belong in `src/components/`)
|
|
51
|
+
- `components/**` — `.tsx` only (logic belongs in `src/features/`)
|
|
52
|
+
|
|
53
|
+
### Layers
|
|
54
|
+
|
|
55
|
+
Enforces dependency direction between layers:
|
|
56
|
+
|
|
57
|
+
```
|
|
58
|
+
hooks → actions → domains → repositories
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
- **Repositories** — cannot import domains/actions/hooks, no `try-catch` or `if`
|
|
62
|
+
- **Domains** — cannot import actions/hooks, no `try-catch`
|
|
63
|
+
- **Actions** — cannot import hooks, exports must start with `handle`
|
|
64
|
+
- **Hooks** — exports must start with `use`
|
|
65
|
+
|
|
66
|
+
Cross-feature imports within the same layer are prohibited.
|
|
67
|
+
|
|
68
|
+
### Cardinality
|
|
69
|
+
|
|
70
|
+
Each action can only import its matching domain:
|
|
71
|
+
|
|
72
|
+
- `server.action.ts` → `server.domain.ts`
|
|
73
|
+
- `client.action.ts` → `client.domain.ts`
|
|
74
|
+
- `admin.action.ts` → `admin.domain.ts`
|
|
75
|
+
|
|
76
|
+
### Directives
|
|
77
|
+
|
|
78
|
+
Enforces `"use server"` / `"use client"` directives:
|
|
79
|
+
|
|
80
|
+
- `server.action.ts` / `admin.action.ts` — must start with `"use server"`
|
|
81
|
+
- `client.action.ts` — must NOT have `"use server"`
|
|
82
|
+
- `hooks/*.ts` — must start with `"use client"`
|
|
83
|
+
|
|
84
|
+
### Imports
|
|
85
|
+
|
|
86
|
+
Each `{prefix}.repo.ts` can only import its corresponding lib (auto-generated from `src/lib/`):
|
|
87
|
+
|
|
88
|
+
- `server.repo.ts` → `@/lib/supabase/server`
|
|
89
|
+
- `client.repo.ts` → `@/lib/supabase/client`
|
|
90
|
+
|
|
91
|
+
## Release
|
|
92
|
+
|
|
93
|
+
1. Update `version` in `package.json`
|
|
94
|
+
2. Commit and push to `main`
|
|
95
|
+
3. Create and push a tag:
|
|
96
|
+
|
|
97
|
+
```sh
|
|
98
|
+
git tag v0.2.0
|
|
99
|
+
git push --tags
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
4. GitHub Actions will automatically publish to npm
|
|
103
|
+
|
|
104
|
+
## License
|
|
105
|
+
|
|
106
|
+
MIT
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yasainet/eslint",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "Shared ESLint configuration for Next.js projects with feature-based architecture",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -17,9 +17,13 @@
|
|
|
17
17
|
],
|
|
18
18
|
"author": "yasainet",
|
|
19
19
|
"license": "MIT",
|
|
20
|
+
"publishConfig": {
|
|
21
|
+
"access": "public"
|
|
22
|
+
},
|
|
20
23
|
"dependencies": {
|
|
21
24
|
"@stylistic/eslint-plugin": "^5.9.0",
|
|
22
25
|
"eslint-plugin-check-file": "^3.3.1",
|
|
26
|
+
"eslint-plugin-jsdoc": "^62.7.1",
|
|
23
27
|
"eslint-plugin-react-you-might-not-need-an-effect": "^0.5.6",
|
|
24
28
|
"eslint-plugin-simple-import-sort": "^12.1.1"
|
|
25
29
|
},
|
package/src/index.mjs
CHANGED
|
@@ -8,12 +8,14 @@
|
|
|
8
8
|
* - cardinality: Action-domain relationships
|
|
9
9
|
* - directives: "use server" / "use client" requirements
|
|
10
10
|
* - imports: Repository import restrictions (prefix → lib mapping)
|
|
11
|
+
* - jsdoc: JSDoc description requirements for exported functions
|
|
11
12
|
*/
|
|
12
13
|
|
|
13
14
|
import { baseConfigs, ignoresConfig, sharedRulesConfig } from "./base.mjs";
|
|
14
15
|
import { cardinalityConfigs } from "./cardinality.mjs";
|
|
15
16
|
import { directivesConfigs } from "./directives.mjs";
|
|
16
17
|
import { importsConfigs } from "./imports.mjs";
|
|
18
|
+
import { jsdocConfigs } from "./jsdoc.mjs";
|
|
17
19
|
import { layersConfigs } from "./layers.mjs";
|
|
18
20
|
import { namingConfigs } from "./naming.mjs";
|
|
19
21
|
|
|
@@ -30,4 +32,5 @@ export const eslintConfig = [
|
|
|
30
32
|
...cardinalityConfigs,
|
|
31
33
|
...directivesConfigs,
|
|
32
34
|
...importsConfigs,
|
|
35
|
+
...jsdocConfigs,
|
|
33
36
|
];
|
package/src/jsdoc.mjs
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview JSDoc configuration for the abstraction layer.
|
|
3
|
+
*
|
|
4
|
+
* Enforces a single rule: every exported function must have a description.
|
|
5
|
+
* Types are handled by TypeScript (machine layer), not JSDoc.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import jsdocPlugin from "eslint-plugin-jsdoc";
|
|
9
|
+
|
|
10
|
+
import { featuresGlob } from "./constants.mjs";
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* JSDoc configurations requiring descriptions on exported functions.
|
|
14
|
+
* @type {import("eslint").Linter.Config[]}
|
|
15
|
+
*/
|
|
16
|
+
export const jsdocConfigs = [
|
|
17
|
+
{
|
|
18
|
+
name: "jsdoc",
|
|
19
|
+
files: [...featuresGlob("**/*.ts"), "src/components/**/*.tsx"],
|
|
20
|
+
plugins: {
|
|
21
|
+
jsdoc: jsdocPlugin,
|
|
22
|
+
},
|
|
23
|
+
rules: {
|
|
24
|
+
"jsdoc/require-jsdoc": [
|
|
25
|
+
"warn",
|
|
26
|
+
{
|
|
27
|
+
publicOnly: true,
|
|
28
|
+
require: {
|
|
29
|
+
FunctionDeclaration: true,
|
|
30
|
+
ArrowFunctionExpression: true,
|
|
31
|
+
FunctionExpression: true,
|
|
32
|
+
},
|
|
33
|
+
checkGetters: false,
|
|
34
|
+
checkSetters: false,
|
|
35
|
+
checkConstructors: false,
|
|
36
|
+
},
|
|
37
|
+
],
|
|
38
|
+
"jsdoc/require-description": [
|
|
39
|
+
"warn",
|
|
40
|
+
{
|
|
41
|
+
contexts: ["any"],
|
|
42
|
+
},
|
|
43
|
+
],
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
];
|
package/src/naming.mjs
CHANGED
|
@@ -15,6 +15,10 @@
|
|
|
15
15
|
* - features/**: .ts only (no .tsx — components belong in src/components/)
|
|
16
16
|
* - components/**: .tsx only (no .ts — logic belongs in src/features/)
|
|
17
17
|
*
|
|
18
|
+
* Component naming:
|
|
19
|
+
* - components/ *.tsx: PascalCase (e.g., Button.tsx, AlertDialog.tsx)
|
|
20
|
+
* - components/shared/ui/ : excluded (shadcn/ui uses kebab-case)
|
|
21
|
+
*
|
|
18
22
|
* Valid prefixes are defined in PREFIX_LIB_MAPPING (constants.mjs).
|
|
19
23
|
*/
|
|
20
24
|
|
|
@@ -149,4 +153,16 @@ export const namingConfigs = [
|
|
|
149
153
|
],
|
|
150
154
|
},
|
|
151
155
|
},
|
|
156
|
+
{
|
|
157
|
+
name: "naming/components-pascal-case",
|
|
158
|
+
files: ["src/components/**/*.tsx"],
|
|
159
|
+
ignores: ["src/components/shared/ui/**"],
|
|
160
|
+
plugins: { "check-file": checkFile },
|
|
161
|
+
rules: {
|
|
162
|
+
"check-file/filename-naming-convention": [
|
|
163
|
+
"error",
|
|
164
|
+
{ "**/*.tsx": "PASCAL_CASE" },
|
|
165
|
+
],
|
|
166
|
+
},
|
|
167
|
+
},
|
|
152
168
|
];
|
package/src/plugins.mjs
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
import stylistic from "@stylistic/eslint-plugin";
|
|
6
6
|
import checkFile from "eslint-plugin-check-file";
|
|
7
|
+
import jsdocPlugin from "eslint-plugin-jsdoc";
|
|
7
8
|
import reactYouMightNotNeedAnEffect from "eslint-plugin-react-you-might-not-need-an-effect";
|
|
8
9
|
import simpleImportSortPlugin from "eslint-plugin-simple-import-sort";
|
|
9
10
|
|
|
@@ -14,12 +15,14 @@ import simpleImportSortPlugin from "eslint-plugin-simple-import-sort";
|
|
|
14
15
|
export const plugins = {
|
|
15
16
|
"@stylistic": stylistic,
|
|
16
17
|
"check-file": checkFile,
|
|
18
|
+
jsdoc: jsdocPlugin,
|
|
17
19
|
"react-you-might-not-need-an-effect": reactYouMightNotNeedAnEffect,
|
|
18
20
|
"simple-import-sort": simpleImportSortPlugin,
|
|
19
21
|
};
|
|
20
22
|
|
|
21
23
|
export {
|
|
22
24
|
checkFile,
|
|
25
|
+
jsdocPlugin,
|
|
23
26
|
reactYouMightNotNeedAnEffect,
|
|
24
27
|
simpleImportSortPlugin,
|
|
25
28
|
stylistic,
|