eslint-plugin-unslop 0.2.1 → 0.2.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 +92 -23
- package/dist/index.cjs +1201 -1157
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1201 -1157
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -12,7 +12,7 @@ npm install --save-dev eslint-plugin-unslop
|
|
|
12
12
|
|
|
13
13
|
## Quick Start
|
|
14
14
|
|
|
15
|
-
The recommended config enables the
|
|
15
|
+
The recommended config enables the two most universal rules out of the box:
|
|
16
16
|
|
|
17
17
|
```js
|
|
18
18
|
// eslint.config.mjs
|
|
@@ -27,7 +27,6 @@ This turns on:
|
|
|
27
27
|
| --------------------------- | -------- | ------------------------------------------------------------------- |
|
|
28
28
|
| `unslop/no-special-unicode` | error | Catches smart quotes, invisible spaces, and other unicode impostors |
|
|
29
29
|
| `unslop/no-unicode-escape` | error | Prefers `"©"` over `"\u00A9"` |
|
|
30
|
-
| `unslop/no-deep-imports` | error | Prevents importing too deep within the same top-level folder |
|
|
31
30
|
|
|
32
31
|
The remaining rules need explicit configuration:
|
|
33
32
|
|
|
@@ -86,37 +85,55 @@ const copyright = '© 2025'
|
|
|
86
85
|
const arrow = '→'
|
|
87
86
|
```
|
|
88
87
|
|
|
89
|
-
### `unslop/
|
|
88
|
+
### `unslop/import-control`
|
|
90
89
|
|
|
91
|
-
|
|
90
|
+
Think of this as customs control for your modules — you declare which modules are allowed to import from which, and anything undeclared gets turned away at the border.
|
|
92
91
|
|
|
93
|
-
|
|
92
|
+
The rule reads from a shared policy in `settings.unslop.architecture`. It's deny-by-default for cross-module imports, which means forgetting to declare a dependency is a loud error rather than a silent free-for-all. It also enforces:
|
|
94
93
|
|
|
95
|
-
|
|
94
|
+
- cross-module imports must arrive through the public gate (`index.ts` or `types.ts`)
|
|
95
|
+
- same-module relative imports can only go one level deeper — no tunnelling into internals
|
|
96
|
+
- files that don't match any declared module are denied (fail-closed, not fail-silently)
|
|
96
97
|
|
|
97
|
-
####
|
|
98
|
+
#### Configuration
|
|
98
99
|
|
|
99
100
|
```js
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
| Option | Type | Default | Description |
|
|
104
|
-
| ------------ | -------- | ------------- | ----------------------------------------- |
|
|
105
|
-
| `sourceRoot` | `string` | auto-detected | Source directory relative to project root |
|
|
106
|
-
|
|
107
|
-
#### Examples
|
|
101
|
+
// eslint.config.mjs
|
|
102
|
+
import unslop from 'eslint-plugin-unslop'
|
|
108
103
|
|
|
109
|
-
|
|
104
|
+
export default [
|
|
105
|
+
{
|
|
106
|
+
settings: {
|
|
107
|
+
unslop: {
|
|
108
|
+
sourceRoot: 'src',
|
|
109
|
+
architecture: {
|
|
110
|
+
utils: { shared: true },
|
|
111
|
+
'repository/*': {
|
|
112
|
+
imports: ['utils', 'models/*'],
|
|
113
|
+
exports: ['^create\\w+Repo$', '^Repository[A-Z]\\w+$'],
|
|
114
|
+
},
|
|
115
|
+
'models/*': {
|
|
116
|
+
imports: ['utils'],
|
|
117
|
+
},
|
|
118
|
+
app: {
|
|
119
|
+
imports: ['*'],
|
|
120
|
+
},
|
|
121
|
+
},
|
|
122
|
+
},
|
|
123
|
+
},
|
|
124
|
+
rules: {
|
|
125
|
+
'unslop/import-control': 'error',
|
|
126
|
+
'unslop/export-control': 'error',
|
|
127
|
+
},
|
|
128
|
+
},
|
|
129
|
+
]
|
|
130
|
+
```
|
|
110
131
|
|
|
111
|
-
|
|
112
|
-
// File: src/features/auth/login.ts
|
|
132
|
+
### `unslop/export-control`
|
|
113
133
|
|
|
114
|
-
|
|
115
|
-
import { validate } from './validators/email.js'
|
|
134
|
+
The customs declaration form for the other direction: what are you actually exporting from your module's public entrypoints?
|
|
116
135
|
|
|
117
|
-
|
|
118
|
-
import { format } from './validators/internal/format.js'
|
|
119
|
-
```
|
|
136
|
+
When a module defines `exports` regex patterns in `settings.unslop.architecture`, every symbol exported from that module's `index.ts` or `types.ts` must match at least one pattern — otherwise it's stopped at the gate with an error at the export site. Modules without `exports` are waved through by default, so you can adopt this gradually.
|
|
120
137
|
|
|
121
138
|
### `unslop/no-false-sharing`
|
|
122
139
|
|
|
@@ -273,6 +290,58 @@ Yes, a fair amount of this was vibe-coded with LLM assistance — which is fitti
|
|
|
273
290
|
|
|
274
291
|
The project also dogfoods itself: `eslint-plugin-unslop` is linted using `eslint-plugin-unslop`.
|
|
275
292
|
|
|
293
|
+
## Maintainer: Main Branch Protection
|
|
294
|
+
|
|
295
|
+
This repository treats `main` as a protected branch with pull-request-only merges.
|
|
296
|
+
|
|
297
|
+
Baseline policy:
|
|
298
|
+
|
|
299
|
+
- Require pull requests before merge
|
|
300
|
+
- Require at least 1 approving review
|
|
301
|
+
- Dismiss stale approvals when new commits are pushed
|
|
302
|
+
- Require branch to be up to date before merge
|
|
303
|
+
- Require status check: `PR Gate`
|
|
304
|
+
- Apply restrictions to admins too (`enforce_admins`)
|
|
305
|
+
|
|
306
|
+
The required check is produced by `.github/workflows/test.yml` (workflow/job name: `PR Gate`) and runs:
|
|
307
|
+
|
|
308
|
+
1. `npm run verify`
|
|
309
|
+
2. `npm run test`
|
|
310
|
+
|
|
311
|
+
### Safe Workflow Renames
|
|
312
|
+
|
|
313
|
+
If you rename the workflow or job that produces `PR Gate`, update branch protection required checks immediately to match the new check context.
|
|
314
|
+
|
|
315
|
+
Recommended update command:
|
|
316
|
+
|
|
317
|
+
```bash
|
|
318
|
+
gh api -X PUT repos/skhoroshavin/eslint-plugin-unslop/branches/main/protection \
|
|
319
|
+
-H "Accept: application/vnd.github+json" \
|
|
320
|
+
-F 'required_status_checks[strict]=true' \
|
|
321
|
+
-F 'required_status_checks[contexts][]=PR Gate' \
|
|
322
|
+
-F 'enforce_admins=true' \
|
|
323
|
+
-F 'required_pull_request_reviews[dismiss_stale_reviews]=true' \
|
|
324
|
+
-F 'required_pull_request_reviews[require_code_owner_reviews]=false' \
|
|
325
|
+
-F 'required_pull_request_reviews[required_approving_review_count]=1' \
|
|
326
|
+
-F 'restrictions=null'
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
### Branch Protection Audit
|
|
330
|
+
|
|
331
|
+
Run these checks periodically:
|
|
332
|
+
|
|
333
|
+
```bash
|
|
334
|
+
gh api repos/skhoroshavin/eslint-plugin-unslop/branches/main/protection
|
|
335
|
+
gh run list --workflow "PR Gate" --limit 5
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
Expected audit outcomes:
|
|
339
|
+
|
|
340
|
+
- `required_status_checks.contexts` includes `PR Gate`
|
|
341
|
+
- `required_pull_request_reviews.required_approving_review_count` is `1` or greater
|
|
342
|
+
- `required_pull_request_reviews.dismiss_stale_reviews` is `true`
|
|
343
|
+
- `enforce_admins.enabled` is `true`
|
|
344
|
+
|
|
276
345
|
## Contributing
|
|
277
346
|
|
|
278
347
|
See [AGENTS.md](./AGENTS.md) for development setup and guidelines.
|