eslint-plugin-unslop 0.5.2 → 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 +44 -12
- package/dist/index.cjs +438 -216
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +438 -216
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -26,10 +26,10 @@ export default [
|
|
|
26
26
|
architecture: {
|
|
27
27
|
utils: { shared: true },
|
|
28
28
|
'repository/*': {
|
|
29
|
-
imports: ['utils', 'models
|
|
29
|
+
imports: ['utils', 'models/+'],
|
|
30
30
|
exports: ['^create\\w+Repo$', '^Repository[A-Z]\\w+$'],
|
|
31
31
|
},
|
|
32
|
-
|
|
32
|
+
models: {
|
|
33
33
|
imports: ['utils'],
|
|
34
34
|
},
|
|
35
35
|
app: {
|
|
@@ -42,11 +42,12 @@ export default [
|
|
|
42
42
|
]
|
|
43
43
|
```
|
|
44
44
|
|
|
45
|
-
Architecture rules (`import-control`, `export-control`, `no-false-sharing`, `no-single-use-constants`) require a reachable `tsconfig.json`. Set `compilerOptions.rootDir`, and if you use aliases, configure `compilerOptions.paths`.
|
|
45
|
+
Architecture rules (`import-control`, `no-whitebox-testing`, `export-control`, `no-false-sharing`, `no-single-use-constants`) require a reachable `tsconfig.json`. Set `compilerOptions.rootDir`, and if you use aliases, configure `compilerOptions.paths`.
|
|
46
46
|
|
|
47
47
|
| Rule | What it does |
|
|
48
48
|
| -------------------------------- | ---------------------------------------------------------------------- |
|
|
49
49
|
| `unslop/import-control` | Enforces module boundaries and forbids local namespace imports |
|
|
50
|
+
| `unslop/no-whitebox-testing` | Keeps tests on module entrypoints instead of same-folder internals |
|
|
50
51
|
| `unslop/export-control` | Restricts export patterns and forbids `export *` in module entrypoints |
|
|
51
52
|
| `unslop/no-false-sharing` | Flags shared entrypoint symbols with fewer than two consumer groups |
|
|
52
53
|
| `unslop/no-single-use-constants` | Flags module-scope constants used once or never across the project |
|
|
@@ -65,17 +66,42 @@ export default [unslop.configs.minimal]
|
|
|
65
66
|
|
|
66
67
|
## Architecture Settings
|
|
67
68
|
|
|
68
|
-
All architecture rules read from `settings.unslop.architecture`. Each
|
|
69
|
+
All architecture rules read from `settings.unslop.architecture`. Each file first resolves to a canonical module path equal to its containing directory relative to the source root from `tsconfig.json`.
|
|
70
|
+
|
|
71
|
+
- `src/index.ts` -> `.`
|
|
72
|
+
- `src/models/index.ts` -> `models`
|
|
73
|
+
- `src/models/user/index.ts` -> `models/user`
|
|
74
|
+
- `src/models/user/internal.ts` -> `models/user`
|
|
75
|
+
|
|
76
|
+
Architecture keys are directory-shaped subtree selectors:
|
|
77
|
+
|
|
78
|
+
- `.` matches the source-root module
|
|
79
|
+
- `models` owns `models` and everything below it
|
|
80
|
+
- `models/*` owns each direct child subtree under `models`, such as `models/user` and `models/user/internal`
|
|
81
|
+
|
|
82
|
+
File-shaped keys like `index.ts` or `rules/public.ts` are not supported.
|
|
83
|
+
|
|
84
|
+
Each value is a policy object:
|
|
69
85
|
|
|
70
86
|
```ts
|
|
71
87
|
{
|
|
72
|
-
imports?: string[] // module
|
|
73
|
-
exports?: string[] // regex patterns symbols exported from
|
|
88
|
+
imports?: string[] // exact module, direct child via /*, self-or-child via /+, or '*' for all
|
|
89
|
+
exports?: string[] // regex patterns symbols exported from entrypoints must match
|
|
90
|
+
entrypoints?: string[] // public files allowed for external and test imports
|
|
74
91
|
shared?: boolean // marks module as shared; enables no-false-sharing
|
|
75
92
|
}
|
|
76
93
|
```
|
|
77
94
|
|
|
78
|
-
|
|
95
|
+
Architecture keys and import allowlists use different matching rules:
|
|
96
|
+
|
|
97
|
+
- keys assign ownership to subtrees
|
|
98
|
+
- `imports: ['models']` allows only the exact `models` module
|
|
99
|
+
- `imports: ['models/*']` allows only direct children like `models/user`
|
|
100
|
+
- `imports: ['models/+']` allows `models` and direct children like `models/user`
|
|
101
|
+
|
|
102
|
+
When multiple keys cover the same canonical module path, the winner is chosen by nearest owner first, then exact named path over wildcard path at the same depth, then longer selector path, then declaration order. Unmatched canonical module paths become anonymous modules with empty `imports`, empty `exports`, `shared: false`, and default `entrypoints: ['index.ts']`.
|
|
103
|
+
|
|
104
|
+
All architecture rules take no options. Policy comes entirely from this shared settings block.
|
|
79
105
|
|
|
80
106
|
## Rules
|
|
81
107
|
|
|
@@ -85,18 +111,24 @@ Customs control for your modules: you declare which modules are allowed to impor
|
|
|
85
111
|
|
|
86
112
|
Deny-by-default for cross-module imports, so forgetting to declare a dependency is a loud error rather than a silent free-for-all. It also enforces:
|
|
87
113
|
|
|
88
|
-
- cross-module imports must arrive through the public gate (
|
|
114
|
+
- cross-module imports must arrive through the public gate (configured entrypoints)
|
|
89
115
|
- local cross-module namespace imports are forbidden (`import * as X from '<local-module>'`)
|
|
90
116
|
- same-module relative imports can only go one level deeper - no tunnelling into internals
|
|
91
|
-
- files that don't match any declared module are denied
|
|
117
|
+
- files that don't match any declared module become anonymous modules and are denied by default
|
|
92
118
|
|
|
93
119
|
Alias imports are resolved via `compilerOptions.paths` from `tsconfig.json`.
|
|
94
120
|
|
|
121
|
+
### `unslop/no-whitebox-testing`
|
|
122
|
+
|
|
123
|
+
Keeps test files black-boxed. When a recognized test file lives beside a module's implementation, it must import that module through its public entrypoint (`.`, `./index`, or a configured `entrypoints` file) instead of reaching into sibling files like `./model.ts`.
|
|
124
|
+
|
|
125
|
+
This rule only checks recognized test filenames (`*.test.*`, `*.spec.*`, `*.*-test.*`, `*.*-spec.*`). Child submodule imports and cross-module imports are left to `unslop/import-control`.
|
|
126
|
+
|
|
95
127
|
### `unslop/export-control`
|
|
96
128
|
|
|
97
129
|
The customs declaration form for the other direction: what are you actually exporting from your module's public entrypoints?
|
|
98
130
|
|
|
99
|
-
When a module defines `exports` regex patterns, every symbol exported from its
|
|
131
|
+
When a module defines `exports` regex patterns, every symbol exported from its entrypoints must match at least one pattern - otherwise it's stopped at the gate. Modules without `exports` are waved through by default, so you can adopt this gradually. Regardless of module policy, `export * from ...` is rejected in public entrypoints so symbol provenance stays explicit.
|
|
100
132
|
|
|
101
133
|
### `unslop/no-false-sharing`
|
|
102
134
|
|
|
@@ -109,7 +141,7 @@ settings: {
|
|
|
109
141
|
unslop: {
|
|
110
142
|
architecture: {
|
|
111
143
|
utils: { shared: true },
|
|
112
|
-
|
|
144
|
+
shared: { shared: true },
|
|
113
145
|
},
|
|
114
146
|
},
|
|
115
147
|
}
|
|
@@ -123,7 +155,7 @@ src/shared/index.ts
|
|
|
123
155
|
-> imported only by src/features/calendar/view.ts
|
|
124
156
|
-> error: symbol "formatDate" has 1 consumer group(s) (group: features/calendar)
|
|
125
157
|
|
|
126
|
-
src/shared/
|
|
158
|
+
src/shared/index.ts
|
|
127
159
|
export type LegacyOptions = ...
|
|
128
160
|
-> not imported by anyone
|
|
129
161
|
-> error: symbol "LegacyOptions" has 0 consumer group(s) (no consumers found)
|