eslint-plugin-unslop 0.5.3 → 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 +35 -11
- package/dist/index.cjs +385 -228
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +385 -228
- 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: {
|
|
@@ -66,18 +66,42 @@ export default [unslop.configs.minimal]
|
|
|
66
66
|
|
|
67
67
|
## Architecture Settings
|
|
68
68
|
|
|
69
|
-
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:
|
|
70
85
|
|
|
71
86
|
```ts
|
|
72
87
|
{
|
|
73
|
-
imports?: string[] // module
|
|
74
|
-
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
|
|
75
90
|
entrypoints?: string[] // public files allowed for external and test imports
|
|
76
91
|
shared?: boolean // marks module as shared; enables no-false-sharing
|
|
77
92
|
}
|
|
78
93
|
```
|
|
79
94
|
|
|
80
|
-
|
|
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.
|
|
81
105
|
|
|
82
106
|
## Rules
|
|
83
107
|
|
|
@@ -87,10 +111,10 @@ Customs control for your modules: you declare which modules are allowed to impor
|
|
|
87
111
|
|
|
88
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:
|
|
89
113
|
|
|
90
|
-
- cross-module imports must arrive through the public gate (
|
|
114
|
+
- cross-module imports must arrive through the public gate (configured entrypoints)
|
|
91
115
|
- local cross-module namespace imports are forbidden (`import * as X from '<local-module>'`)
|
|
92
116
|
- same-module relative imports can only go one level deeper - no tunnelling into internals
|
|
93
|
-
- 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
|
|
94
118
|
|
|
95
119
|
Alias imports are resolved via `compilerOptions.paths` from `tsconfig.json`.
|
|
96
120
|
|
|
@@ -104,7 +128,7 @@ This rule only checks recognized test filenames (`*.test.*`, `*.spec.*`, `*.*-te
|
|
|
104
128
|
|
|
105
129
|
The customs declaration form for the other direction: what are you actually exporting from your module's public entrypoints?
|
|
106
130
|
|
|
107
|
-
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.
|
|
108
132
|
|
|
109
133
|
### `unslop/no-false-sharing`
|
|
110
134
|
|
|
@@ -117,7 +141,7 @@ settings: {
|
|
|
117
141
|
unslop: {
|
|
118
142
|
architecture: {
|
|
119
143
|
utils: { shared: true },
|
|
120
|
-
|
|
144
|
+
shared: { shared: true },
|
|
121
145
|
},
|
|
122
146
|
},
|
|
123
147
|
}
|
|
@@ -131,7 +155,7 @@ src/shared/index.ts
|
|
|
131
155
|
-> imported only by src/features/calendar/view.ts
|
|
132
156
|
-> error: symbol "formatDate" has 1 consumer group(s) (group: features/calendar)
|
|
133
157
|
|
|
134
|
-
src/shared/
|
|
158
|
+
src/shared/index.ts
|
|
135
159
|
export type LegacyOptions = ...
|
|
136
160
|
-> not imported by anyone
|
|
137
161
|
-> error: symbol "LegacyOptions" has 0 consumer group(s) (no consumers found)
|