eslint-plugin-barrel-rules 1.2.0 → 1.3.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.ko.md +78 -41
- package/README.md +83 -40
- package/dist/index.cjs +151 -43
- package/dist/index.d.cts +9 -3
- package/dist/index.d.ts +9 -3
- package/dist/index.js +151 -43
- package/package.json +11 -2
package/README.ko.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
# **Advanced Barrel Pattern Enforcement for JavaScript/TypeScript Projects**
|
|
4
4
|
|
|
5
5
|
<div align="center">
|
|
6
|
-
<img src="https://img.shields.io/badge/version-1.
|
|
6
|
+
<img src="https://img.shields.io/badge/version-1.3.0-blue.svg" alt="Version"/>
|
|
7
7
|
<img src="https://img.shields.io/badge/License-MIT-yellow.svg" alt="License"/>
|
|
8
8
|
<img src="https://img.shields.io/badge/PRs-welcome-brightgreen.svg" alt="PRs Welcome"/>
|
|
9
9
|
</div>
|
|
@@ -58,11 +58,7 @@ JavaScript/TypeScript 프로젝트에서 Barrel Pattern(배럴 패턴)을 강제
|
|
|
58
58
|
`import ... from "../domains/foo/components/Bar"`는 차단)
|
|
59
59
|
|
|
60
60
|
- **Isolation Barrel Module**
|
|
61
|
-
지정한 barrel path 외부의 모듈이 내부 파일을 직접 import하지 못하도록 막을 수 있습니다.
|
|
62
|
-
`isolated: true` 옵션을 사용하면 같은 barrel path 내부에서는 자유롭게 import가 가능하고,
|
|
63
|
-
외부에서는 해당 barrel path로의 import가 모두 차단됩니다. (barrel(index) 파일을 통한 접근도 불가)
|
|
64
|
-
만약 특정 공유 import 경로만 허용하고 싶다면 `allowedImportPaths` 옵션을 사용할 수 있습니다.
|
|
65
|
-
이를 통해 각 모듈의 경계를 엄격하게 보호하고, 모듈의 독립성을 유지할 수 있습니다.
|
|
61
|
+
지정한 barrel path 외부의 모듈이 내부 파일을 직접 import하지 못하도록 막을 수 있습니다.
|
|
66
62
|
|
|
67
63
|
- **와일드카드 import/export 방지**
|
|
68
64
|
`import * as foo from "module"` 또는 `export * from "./module"`과 같은 와일드카드(네임스페이스) import/export를 금지합니다.
|
|
@@ -75,17 +71,13 @@ JavaScript/TypeScript 프로젝트에서 Barrel Pattern(배럴 패턴)을 강제
|
|
|
75
71
|
|
|
76
72
|
## 규칙(Rules)
|
|
77
73
|
|
|
78
|
-
1. **enforce-barrel-pattern**
|
|
74
|
+
1. **enforce-barrel-pattern** (isolate 옵션이 제거되었습니다.)
|
|
79
75
|
모듈 import 시 barrel 패턴을 강제합니다.
|
|
80
76
|
지정한 barrel 파일(예: index.ts)로만 import를 허용하고, 내부 모듈에 대한 직접 접근을 차단합니다.
|
|
81
|
-
`isolated: true` 옵션을 사용하면 같은 barrel path 내부 파일끼리만 import가 가능하며, 외부에서의 import는 barrel 파일을 통한 접근도 모두 차단됩니다.
|
|
82
|
-
`allowedImportPaths` 옵션을 사용하면 특정 공유 import 경로만 예외적으로 허용할 수 있습니다.
|
|
83
77
|
|
|
84
78
|
- **옵션:**
|
|
85
79
|
- `paths`: barrel 패턴을 적용할 디렉토리 목록(`baseDir` 기준 상대경로)
|
|
86
|
-
- `baseDir
|
|
87
|
-
- `isolated` (선택): `true`일 경우, barrel path 외부에서의 모든 import를 차단합니다(barrel 파일 통한 접근 포함). 같은 barrel path 내부 또는 `allowedImportPaths`만 허용.
|
|
88
|
-
- `allowedImportPaths` (선택): isolation 모드에서도 직접 import를 허용할 경로 배열
|
|
80
|
+
- `baseDir`: `paths` 기준이 되는 베이스 디렉토리 (기본값: ESLint 실행 디렉토리)
|
|
89
81
|
|
|
90
82
|
2. **no-wildcard**
|
|
91
83
|
`import * as foo from "module"` 또는 `export * from "./module"`과 같은 와일드카드(네임스페이스) import/export를 금지합니다.
|
|
@@ -93,6 +85,14 @@ JavaScript/TypeScript 프로젝트에서 Barrel Pattern(배럴 패턴)을 강제
|
|
|
93
85
|
두 룰을 함께 적용하면 모듈 경계를 엄격하게 지킬 수 있을 뿐만 아니라,
|
|
94
86
|
트리쉐이킹을 통한 성능 향상과 코드 추적 및 유지보수의 용이성까지 모두 얻을 수 있습니다.
|
|
95
87
|
|
|
88
|
+
3. **isolate-barrel-file** (isolated 기능을 새로운 룰로 제작했습니다.)
|
|
89
|
+
모듈 import 시 barrel 패턴을 강제합니다.
|
|
90
|
+
지정한 barrel 파일(예: index.ts)로만 import를 허용하고, 내부 모듈에 대한 직접 접근을 차단합니다.
|
|
91
|
+
- **옵션:**
|
|
92
|
+
- `isolations(Array<{ path: string, allowedPaths: string[] }>)`: `path`와 `allowedPaths`로 구성된 isolation을 추가할 수 있습니다.
|
|
93
|
+
- `baseDir`: `paths` 기준이 되는 베이스 디렉토리 (기본값: ESLint 실행 디렉토리)
|
|
94
|
+
- `globalAllowedPaths` : 모든 isolations에 공통적으로 허용할 경로를 지정합니다(node_modules ... etc)
|
|
95
|
+
|
|
96
96
|
---
|
|
97
97
|
|
|
98
98
|
## 설치
|
|
@@ -118,23 +118,43 @@ module.exports = {
|
|
|
118
118
|
parser: "@typescript-eslint/parser",
|
|
119
119
|
plugins: ["@typescript-eslint", "barrel-rules"],
|
|
120
120
|
rules: {
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
121
|
+
|
|
122
|
+
//barrel-file 캡슐화
|
|
123
|
+
"barrel-rules/enforce-barrel-pattern": [
|
|
124
|
+
"error",
|
|
125
|
+
{
|
|
126
|
+
// encapsulation barrel file
|
|
127
|
+
paths: ["src/pages/*", "src/features/*", "src/entities/*"],
|
|
128
|
+
baseDir: __dirname,
|
|
129
|
+
},
|
|
130
|
+
],
|
|
131
|
+
|
|
132
|
+
//barrel file내부에서 외부 모듈 사용 제한
|
|
133
|
+
"barrel-rules/isolate-barrel-file": [
|
|
134
|
+
"error",
|
|
135
|
+
{
|
|
136
|
+
//isolation options
|
|
137
|
+
isolations: [
|
|
138
|
+
{
|
|
139
|
+
path: "src/pages/*",
|
|
140
|
+
allowedPaths: ["src/features/*", "src/entities/*"],
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
path: "src/features/*",
|
|
144
|
+
allowedPaths: ["src/entities/*"],
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
path: "src/entities/*",
|
|
148
|
+
allowedPaths: [],
|
|
149
|
+
},
|
|
150
|
+
],
|
|
151
|
+
baseDir: __dirname,
|
|
152
|
+
globalAllowPaths: ["src/shares/*", "node_modules/*"],
|
|
153
|
+
},
|
|
154
|
+
],
|
|
155
|
+
|
|
156
|
+
// "*"를 사용한 불 분명한 import/export 방지
|
|
157
|
+
"barrel-rules/no-wildcard": ["error"],
|
|
138
158
|
},
|
|
139
159
|
};
|
|
140
160
|
```
|
|
@@ -172,22 +192,41 @@ export default tseslint.config([
|
|
|
172
192
|
},
|
|
173
193
|
// barrel-rules에 대한 설정만 추가하면 됩니다.
|
|
174
194
|
rules: {
|
|
195
|
+
//barrel-file 캡슐화
|
|
175
196
|
"barrel-rules/enforce-barrel-pattern": [
|
|
176
197
|
"error",
|
|
177
198
|
{
|
|
178
|
-
//
|
|
179
|
-
paths: ["src/
|
|
180
|
-
// (옵션) 설정하지 않으면 기본값은 ESLint를 실행한 위치(작업 디렉토리)입니다.
|
|
181
|
-
// 예: `npx eslint .`처럼 실행하면, 실행 시점의 현재 디렉토리가 기본값이 됩니다.
|
|
199
|
+
// encapsulation barrel file
|
|
200
|
+
paths: ["src/pages/*", "src/features/*", "src/entities/*"],
|
|
182
201
|
baseDir: __dirname,
|
|
183
|
-
// isolation 모드 활성화: barrel path 외부에서의 모든 import를 차단합니다.
|
|
184
|
-
isolated: true,
|
|
185
|
-
// "shared" 디렉토리만 직접 import를 허용합니다.
|
|
186
|
-
// 필요에 따라 이 배열에 "node_modules/*" 등 원하는 경로를 자유롭게 추가할 수 있습니다.
|
|
187
|
-
allowedImportPaths: ["src/typescript/shared", "node_modules/*"],
|
|
188
202
|
},
|
|
189
203
|
],
|
|
190
|
-
|
|
204
|
+
|
|
205
|
+
//barrel file내부에서 외부 모듈 사용 제한
|
|
206
|
+
"barrel-rules/isolate-barrel-file": [
|
|
207
|
+
"error",
|
|
208
|
+
{
|
|
209
|
+
//isolation options
|
|
210
|
+
isolations: [
|
|
211
|
+
{
|
|
212
|
+
path: "src/pages/*",
|
|
213
|
+
allowedPaths: ["src/features/*", "src/entities/*"],
|
|
214
|
+
},
|
|
215
|
+
{
|
|
216
|
+
path: "src/features/*",
|
|
217
|
+
allowedPaths: ["src/entities/*"],
|
|
218
|
+
},
|
|
219
|
+
{
|
|
220
|
+
path: "src/entities/*",
|
|
221
|
+
allowedPaths: [],
|
|
222
|
+
},
|
|
223
|
+
],
|
|
224
|
+
baseDir: __dirname,
|
|
225
|
+
globalAllowPaths: ["src/shares/*", "node_modules/*"],
|
|
226
|
+
},
|
|
227
|
+
],
|
|
228
|
+
|
|
229
|
+
// "*"를 사용한 불 분명한 import/export 방지
|
|
191
230
|
"barrel-rules/no-wildcard": ["error"],
|
|
192
231
|
},
|
|
193
232
|
},
|
|
@@ -218,8 +257,6 @@ file(src / domains / foo / index.ts);
|
|
|
218
257
|
// ❌ 격리된 barrel로의 외부 import 차단 (alias 사용해도 차단)
|
|
219
258
|
// barrel 외부에서 접근 (bar의 경로는 src/domains/bar/)
|
|
220
259
|
import { Test } from "@domains/bar/components/Test";
|
|
221
|
-
// 또는
|
|
222
|
-
import { Test } from "../domains/bar";
|
|
223
260
|
|
|
224
261
|
// ✅ 같은 barrel 내부에서의 import는 허용 (alias 지원)
|
|
225
262
|
import { Hook } from "@domains/foo/hooks/useTest"; // 같은 barrel 내부에서
|
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
# **Advanced Barrel Pattern Enforcement for JavaScript/TypeScript Projects**
|
|
4
4
|
|
|
5
5
|
<div align="center">
|
|
6
|
-
<img src="https://img.shields.io/badge/version-1.
|
|
6
|
+
<img src="https://img.shields.io/badge/version-1.3.0-blue.svg" alt="Version"/>
|
|
7
7
|
<img src="https://img.shields.io/badge/License-MIT-yellow.svg" alt="License"/>
|
|
8
8
|
<img src="https://img.shields.io/badge/PRs-welcome-brightgreen.svg" alt="PRs Welcome"/>
|
|
9
9
|
</div>
|
|
@@ -60,10 +60,9 @@ Direct imports from internal files are blocked, maximizing
|
|
|
60
60
|
|
|
61
61
|
- **Isolation Barrel Module**
|
|
62
62
|
You can prevent modules outside the specified barrel path from directly importing internal files.
|
|
63
|
-
By enabling `
|
|
63
|
+
By enabling `isolate-barrel-file`, only files within the same barrel path can freely import each other.
|
|
64
64
|
Any import from outside the enforced barrel path is completely blocked, even if it tries to import via the barrel (index) file.
|
|
65
|
-
If you want to allow specific shared imports, you can use the `
|
|
66
|
-
This helps you strictly protect your module boundaries and keep each module truly independent.
|
|
65
|
+
If you want to allow specific shared imports, you can use the `allowedPaths` or `globalAllowedPaths` option.
|
|
67
66
|
|
|
68
67
|
- **Prevent Wildcard Import/Export**
|
|
69
68
|
Disallows wildcard (namespace) imports and exports such as `import * as foo from "module"` or `export * from "./module"`.
|
|
@@ -76,17 +75,13 @@ Direct imports from internal files are blocked, maximizing
|
|
|
76
75
|
|
|
77
76
|
## Rules
|
|
78
77
|
|
|
79
|
-
1. **enforce-barrel-pattern**
|
|
78
|
+
1. **enforce-barrel-pattern** (Isolation is exracted as new rule :))
|
|
80
79
|
Enforces the barrel pattern for module imports.
|
|
81
80
|
Only allows imports from designated barrel files and prevents direct access to internal modules.
|
|
82
|
-
When `isolated: true` is set, only files within the same barrel path can import each other, and any import from outside the barrel path is completely blocked (even via the barrel file).
|
|
83
|
-
You can allow specific shared import paths by using the `allowedImportPaths` option.
|
|
84
81
|
|
|
85
82
|
- **Options:**
|
|
86
83
|
- `paths`: The directories to be protected by the barrel pattern (relative to `baseDir`).
|
|
87
|
-
- `baseDir
|
|
88
|
-
- `isolated` (optional): If `true`, blocks all imports from outside the barrel path, even via the barrel file. Only allows imports within the same barrel path or from `allowedImportPaths`.
|
|
89
|
-
- `allowedImportPaths` (optional): Array of paths that are allowed to be imported directly, even in isolation mode.
|
|
84
|
+
- `baseDir`: The base directory for resolving `paths`. Defaults to the ESLint execution directory.
|
|
90
85
|
|
|
91
86
|
2. **no-wildcard**
|
|
92
87
|
Disallows wildcard (namespace) imports such as `import * as foo from "module"` or `export * from "./module"`.
|
|
@@ -94,6 +89,14 @@ Direct imports from internal files are blocked, maximizing
|
|
|
94
89
|
Using both rules together not only enforces strict module boundaries,
|
|
95
90
|
but also improves performance through better tree-shaking and makes code tracing and maintenance much easier.
|
|
96
91
|
|
|
92
|
+
3. **isolate-barrel-file** (New Rules!!!)
|
|
93
|
+
Only files within the same barrel path can import each other, and any import from outside the barrel path is completely blocked (even via the barrel file).
|
|
94
|
+
You can allow specific shared import paths by using the `allowedPaths` option.
|
|
95
|
+
- **Options:**
|
|
96
|
+
- `isolations(Array<{ path: string, allowedPaths: string[] }>)`: If you set isolation path, blocks all imports from outside the barrel path, even via the barrel file. Only allows imports within the same barrel path or from `allowedPaths` or `globalAllowedPaths`.
|
|
97
|
+
- `baseDir`: The base directory for resolving `paths`. Defaults to the ESLint execution directory.
|
|
98
|
+
- `globalAllowedPaths` : Array of paths that are allowed to be imported directly, even in isolation mode.
|
|
99
|
+
|
|
97
100
|
---
|
|
98
101
|
|
|
99
102
|
## Install
|
|
@@ -119,23 +122,44 @@ module.exports = {
|
|
|
119
122
|
parser: "@typescript-eslint/parser",
|
|
120
123
|
plugins: ["@typescript-eslint", "barrel-rules"],
|
|
121
124
|
rules: {
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
125
|
+
|
|
126
|
+
//enforce barrel capsuling
|
|
127
|
+
"barrel-rules/enforce-barrel-pattern": [
|
|
128
|
+
"error",
|
|
129
|
+
{
|
|
130
|
+
// encapsulation barrel file
|
|
131
|
+
paths: ["src/pages/*", "src/features/*", "src/entities/*"],
|
|
132
|
+
baseDir: __dirname,
|
|
133
|
+
},
|
|
134
|
+
],
|
|
135
|
+
|
|
136
|
+
//protect barrel file from outside module
|
|
137
|
+
"barrel-rules/isolate-barrel-file": [
|
|
138
|
+
"error",
|
|
139
|
+
{
|
|
140
|
+
//isolation options
|
|
141
|
+
isolations: [
|
|
142
|
+
{
|
|
143
|
+
path: "src/pages/*",
|
|
144
|
+
allowedPaths: ["src/features/*", "src/entities/*"],
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
path: "src/features/*",
|
|
148
|
+
allowedPaths: ["src/entities/*"],
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
path: "src/entities/*",
|
|
152
|
+
allowedPaths: [],
|
|
153
|
+
},
|
|
154
|
+
],
|
|
155
|
+
baseDir: __dirname,
|
|
156
|
+
globalAllowPaths: ["src/shares/*", "node_modules/*"],
|
|
157
|
+
},
|
|
158
|
+
],
|
|
159
|
+
|
|
160
|
+
// protect wildcard import/export
|
|
161
|
+
"barrel-rules/no-wildcard": ["error"],
|
|
162
|
+
|
|
139
163
|
},
|
|
140
164
|
};
|
|
141
165
|
```
|
|
@@ -173,23 +197,44 @@ export default tseslint.config([
|
|
|
173
197
|
},
|
|
174
198
|
//just set your setting for barrel-rules
|
|
175
199
|
rules: {
|
|
200
|
+
|
|
201
|
+
//enforce barrel capsuling
|
|
176
202
|
"barrel-rules/enforce-barrel-pattern": [
|
|
177
203
|
"error",
|
|
178
204
|
{
|
|
179
|
-
//
|
|
180
|
-
paths: ["src/
|
|
181
|
-
// Optional config. The default value is the directory where ESLint is executed.
|
|
182
|
-
// For example, if you run `npx eslint .`, the default will be the current working directory at the time of execution.
|
|
205
|
+
// encapsulation barrel file
|
|
206
|
+
paths: ["src/pages/*", "src/features/*", "src/entities/*"],
|
|
183
207
|
baseDir: __dirname,
|
|
184
|
-
// Enable isolation mode: block all imports from outside the barrel path
|
|
185
|
-
isolated: true,
|
|
186
|
-
// Allow direct imports only from the "shared" directory.
|
|
187
|
-
// You can customize this array as needed, e.g., add "node_modules/*" or any other path you want to allow.
|
|
188
|
-
allowedImportPaths: ["src/typescript/shared", "node_modules/*"],
|
|
189
208
|
},
|
|
190
209
|
],
|
|
191
|
-
|
|
210
|
+
|
|
211
|
+
//protect barrel file from outside module
|
|
212
|
+
"barrel-rules/isolate-barrel-file": [
|
|
213
|
+
"error",
|
|
214
|
+
{
|
|
215
|
+
//isolation options
|
|
216
|
+
isolations: [
|
|
217
|
+
{
|
|
218
|
+
path: "src/pages/*",
|
|
219
|
+
allowedPaths: ["src/features/*", "src/entities/*"],
|
|
220
|
+
},
|
|
221
|
+
{
|
|
222
|
+
path: "src/features/*",
|
|
223
|
+
allowedPaths: ["src/entities/*"],
|
|
224
|
+
},
|
|
225
|
+
{
|
|
226
|
+
path: "src/entities/*",
|
|
227
|
+
allowedPaths: [],
|
|
228
|
+
},
|
|
229
|
+
],
|
|
230
|
+
baseDir: __dirname,
|
|
231
|
+
globalAllowPaths: ["src/shares/*", "node_modules/*"],
|
|
232
|
+
},
|
|
233
|
+
],
|
|
234
|
+
|
|
235
|
+
// protect wildcard import/export
|
|
192
236
|
"barrel-rules/no-wildcard": ["error"],
|
|
237
|
+
|
|
193
238
|
},
|
|
194
239
|
},
|
|
195
240
|
]);
|
|
@@ -219,15 +264,13 @@ file(src / domains / foo / index.ts);
|
|
|
219
264
|
// ❌ External import to isolated barrel is blocked (even with alias)
|
|
220
265
|
// from outside barrel (bar's path is src/domains/bar/)
|
|
221
266
|
import { Test } from "@domains/bar/components/Test";
|
|
222
|
-
// or
|
|
223
|
-
import { Test } from "../domains/bar";
|
|
224
267
|
|
|
225
268
|
// ✅ Internal imports within same barrel are allowed (alias supported)
|
|
226
269
|
import { Hook } from "@domains/foo/hooks/useTest"; // from inside same barrel
|
|
227
270
|
import { Utils } from "./utils/helper"; // from inside same barrel
|
|
228
271
|
|
|
229
272
|
// ✅ Allowed import paths are permitted (alias supported)
|
|
230
|
-
import { SharedUtil } from "@
|
|
273
|
+
import { SharedUtil } from "@shared/utils"; // if "src/shared/*" is in allowedPaths or globalAllowedPaths
|
|
231
274
|
```
|
|
232
275
|
|
|
233
276
|
---
|
package/dist/index.cjs
CHANGED
|
@@ -35,22 +35,22 @@ __export(index_exports, {
|
|
|
35
35
|
module.exports = __toCommonJS(index_exports);
|
|
36
36
|
|
|
37
37
|
// src/rules/enforce-barrel-pattern.ts
|
|
38
|
-
var
|
|
38
|
+
var import_types = require("@typescript-eslint/types");
|
|
39
39
|
var import_path2 = __toESM(require("path"), 1);
|
|
40
40
|
var import_resolve = __toESM(require("resolve"), 1);
|
|
41
41
|
|
|
42
42
|
// src/utils/glob.ts
|
|
43
43
|
var import_fast_glob = __toESM(require("fast-glob"), 1);
|
|
44
44
|
var Glob = class {
|
|
45
|
-
static resolvePath(
|
|
46
|
-
const globResult = import_fast_glob.default.sync(
|
|
45
|
+
static resolvePath(path4, baseDir) {
|
|
46
|
+
const globResult = import_fast_glob.default.sync(path4, {
|
|
47
47
|
cwd: baseDir,
|
|
48
48
|
onlyDirectories: true,
|
|
49
49
|
absolute: true
|
|
50
50
|
});
|
|
51
51
|
if (globResult.length === 0) {
|
|
52
52
|
throw new Error(
|
|
53
|
-
`[Glob] In baseDir: ${baseDir}, path: ${
|
|
53
|
+
`[Glob] In baseDir: ${baseDir}, path: ${path4}, any directory was not found`
|
|
54
54
|
);
|
|
55
55
|
}
|
|
56
56
|
return globResult;
|
|
@@ -142,37 +142,47 @@ var enforceBarrelPattern = {
|
|
|
142
142
|
type: "object",
|
|
143
143
|
properties: {
|
|
144
144
|
paths: { type: "array", items: { type: "string" } },
|
|
145
|
-
baseDir: { type: "string" }
|
|
146
|
-
isolated: { type: "boolean" },
|
|
147
|
-
allowedImportPaths: { type: "array", items: { type: "string" } }
|
|
145
|
+
baseDir: { type: "string" }
|
|
148
146
|
},
|
|
149
|
-
required: ["paths"],
|
|
147
|
+
required: ["paths", "baseDir"],
|
|
150
148
|
additionalProperties: false
|
|
151
149
|
}
|
|
152
150
|
],
|
|
153
151
|
messages: {
|
|
152
|
+
TransformedAliasResolveFailed: "Transformed alias resolve failed. please check the alias config.",
|
|
154
153
|
DirectImportDisallowed: "Please import from '{{matchedTargetPath}}'. Direct access to '{{rawImportPath}}' is not allowed. You must use the barrel pattern and only consume APIs exposed externally. This is to ensure encapsulation of internal logic and maintain module boundaries.",
|
|
155
|
-
|
|
154
|
+
EmptyEslintConfig: "Please set the eslint config '{{property}}' to the eslint config. if you want to use this rule, please set the eslint config."
|
|
156
155
|
}
|
|
157
156
|
},
|
|
158
157
|
//default options(baseDir is current working directory. almost user execute eslint in project root)
|
|
159
158
|
defaultOptions: [
|
|
160
159
|
{
|
|
161
160
|
paths: [],
|
|
162
|
-
baseDir: process.cwd()
|
|
163
|
-
isolated: false,
|
|
164
|
-
allowedImportPaths: []
|
|
161
|
+
baseDir: process.cwd()
|
|
165
162
|
}
|
|
166
163
|
],
|
|
167
164
|
create(context) {
|
|
168
165
|
const option = context.options[0];
|
|
166
|
+
if (!option) {
|
|
167
|
+
return {
|
|
168
|
+
Program(node) {
|
|
169
|
+
const option2 = context.options[0];
|
|
170
|
+
if (!option2) {
|
|
171
|
+
return context.report({
|
|
172
|
+
node,
|
|
173
|
+
messageId: "EmptyEslintConfig",
|
|
174
|
+
data: {
|
|
175
|
+
property: "{ path: Array<string>, baseDir: string }"
|
|
176
|
+
}
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
};
|
|
181
|
+
}
|
|
169
182
|
const baseDir = option.baseDir;
|
|
170
183
|
const absoluteTargetPaths = option.paths.flatMap((_path) => {
|
|
171
184
|
return Glob.resolvePath(_path, baseDir);
|
|
172
185
|
});
|
|
173
|
-
const allowedImportPaths = option.allowedImportPaths.flatMap((_path) => {
|
|
174
|
-
return Glob.resolvePath(_path, baseDir);
|
|
175
|
-
});
|
|
176
186
|
return {
|
|
177
187
|
//check only import declaration(ESM)
|
|
178
188
|
ImportDeclaration(node) {
|
|
@@ -193,6 +203,10 @@ var enforceBarrelPattern = {
|
|
|
193
203
|
});
|
|
194
204
|
}
|
|
195
205
|
} catch (e) {
|
|
206
|
+
context.report({
|
|
207
|
+
node,
|
|
208
|
+
messageId: "TransformedAliasResolveFailed"
|
|
209
|
+
});
|
|
196
210
|
return;
|
|
197
211
|
}
|
|
198
212
|
{
|
|
@@ -225,34 +239,127 @@ var enforceBarrelPattern = {
|
|
|
225
239
|
});
|
|
226
240
|
}
|
|
227
241
|
}
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
242
|
+
}
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
};
|
|
246
|
+
|
|
247
|
+
// src/rules/isolate-barrel-file.ts
|
|
248
|
+
var import_types2 = require("@typescript-eslint/types");
|
|
249
|
+
var import_path3 = __toESM(require("path"), 1);
|
|
250
|
+
var import_resolve2 = __toESM(require("resolve"), 1);
|
|
251
|
+
var RESOLVE_EXTENSIONS2 = [
|
|
252
|
+
".ts",
|
|
253
|
+
".tsx",
|
|
254
|
+
".js",
|
|
255
|
+
".jsx",
|
|
256
|
+
".d.ts",
|
|
257
|
+
".mjs",
|
|
258
|
+
".cjs"
|
|
259
|
+
];
|
|
260
|
+
var isolateBarrelFile = {
|
|
261
|
+
meta: {
|
|
262
|
+
type: "problem",
|
|
263
|
+
docs: {
|
|
264
|
+
description: "Isolate barrel file is not allowed to import outside of the barrel file"
|
|
265
|
+
},
|
|
266
|
+
schema: [
|
|
267
|
+
{
|
|
268
|
+
type: "object",
|
|
269
|
+
properties: {
|
|
270
|
+
isolations: { type: "array", items: { type: "object" } },
|
|
271
|
+
baseDir: { type: "string" },
|
|
272
|
+
globalAllowPaths: { type: "array", items: { type: "string" } }
|
|
273
|
+
},
|
|
274
|
+
required: ["isolations", "baseDir", "globalAllowPaths"],
|
|
275
|
+
additionalProperties: false
|
|
276
|
+
}
|
|
277
|
+
],
|
|
278
|
+
messages: {
|
|
279
|
+
TransformedAliasResolveFailed: "Transformed alias resolve failed. please check the alias config.",
|
|
280
|
+
IsolatedBarrelImportDisallowed: "This barrel file is isolated. external import is not allowed. if you want to import outside of the barrel file, please add 'allowedPath' to the plugin options."
|
|
281
|
+
}
|
|
282
|
+
},
|
|
283
|
+
//default options(baseDir is current working directory. almost user execute eslint in project root)
|
|
284
|
+
defaultOptions: [
|
|
285
|
+
{
|
|
286
|
+
isolations: [],
|
|
287
|
+
baseDir: process.cwd(),
|
|
288
|
+
globalAllowPaths: []
|
|
289
|
+
}
|
|
290
|
+
],
|
|
291
|
+
create(context) {
|
|
292
|
+
const option = context.options[0];
|
|
293
|
+
const baseDir = option.baseDir;
|
|
294
|
+
const absoluteGlobalAllowPaths = option.globalAllowPaths.flatMap((path4) => {
|
|
295
|
+
return Glob.resolvePath(path4, baseDir);
|
|
296
|
+
});
|
|
297
|
+
const absoluteIsolations = option.isolations.flatMap((isolation) => {
|
|
298
|
+
const isolationPaths = Glob.resolvePath(isolation.path, baseDir);
|
|
299
|
+
const allowedPaths = isolation.allowedPaths.flatMap((path4) => {
|
|
300
|
+
return Glob.resolvePath(path4, baseDir);
|
|
301
|
+
});
|
|
302
|
+
return isolationPaths.map((isolationPath) => ({
|
|
303
|
+
isolationPath,
|
|
304
|
+
//self isolatedPath also allowed to be imported
|
|
305
|
+
allowedPaths: [...allowedPaths, isolationPath]
|
|
306
|
+
}));
|
|
307
|
+
});
|
|
308
|
+
return {
|
|
309
|
+
//check only import declaration(ESM)
|
|
310
|
+
ImportDeclaration(node) {
|
|
311
|
+
const rawImportPath = node.source.value;
|
|
312
|
+
const absoluteCurrentFilePath = context.getFilename();
|
|
313
|
+
let absoluteImportPath = null;
|
|
314
|
+
try {
|
|
315
|
+
const aliasResult = Alias.resolvePath(
|
|
316
|
+
rawImportPath,
|
|
317
|
+
import_path3.default.dirname(absoluteCurrentFilePath)
|
|
318
|
+
);
|
|
319
|
+
if (aliasResult.type === "success") {
|
|
320
|
+
absoluteImportPath = aliasResult.absolutePath;
|
|
321
|
+
} else {
|
|
322
|
+
absoluteImportPath = import_resolve2.default.sync(rawImportPath, {
|
|
323
|
+
basedir: import_path3.default.dirname(absoluteCurrentFilePath),
|
|
324
|
+
extensions: RESOLVE_EXTENSIONS2
|
|
325
|
+
});
|
|
255
326
|
}
|
|
327
|
+
} catch (e) {
|
|
328
|
+
context.report({
|
|
329
|
+
node,
|
|
330
|
+
messageId: "TransformedAliasResolveFailed"
|
|
331
|
+
});
|
|
332
|
+
return;
|
|
333
|
+
}
|
|
334
|
+
const isolationIndex = absoluteIsolations.findIndex((isolation) => {
|
|
335
|
+
const absoluteIsolationPath = isolation.isolationPath;
|
|
336
|
+
const closedIsolationPath = absoluteIsolationPath + "/";
|
|
337
|
+
return absoluteCurrentFilePath.startsWith(closedIsolationPath);
|
|
338
|
+
});
|
|
339
|
+
const matchedIsolation = absoluteIsolations[isolationIndex];
|
|
340
|
+
if (!matchedIsolation) return;
|
|
341
|
+
const isAllowedImport = matchedIsolation.allowedPaths.some(
|
|
342
|
+
(allowedPath) => {
|
|
343
|
+
const same = absoluteImportPath === allowedPath;
|
|
344
|
+
const closedAllowedPath = allowedPath + "/";
|
|
345
|
+
const sub = absoluteImportPath.startsWith(closedAllowedPath);
|
|
346
|
+
return same || sub;
|
|
347
|
+
}
|
|
348
|
+
);
|
|
349
|
+
const isGlobalAllowedImport = absoluteGlobalAllowPaths.some(
|
|
350
|
+
(allowedPath) => {
|
|
351
|
+
const same = absoluteImportPath === allowedPath;
|
|
352
|
+
const closedAllowedPath = allowedPath + "/";
|
|
353
|
+
const sub = absoluteImportPath.startsWith(closedAllowedPath);
|
|
354
|
+
return same || sub;
|
|
355
|
+
}
|
|
356
|
+
);
|
|
357
|
+
const allowedImport = isAllowedImport || isGlobalAllowedImport;
|
|
358
|
+
if (!allowedImport) {
|
|
359
|
+
context.report({
|
|
360
|
+
node,
|
|
361
|
+
messageId: "IsolatedBarrelImportDisallowed"
|
|
362
|
+
});
|
|
256
363
|
}
|
|
257
364
|
}
|
|
258
365
|
};
|
|
@@ -260,7 +367,7 @@ var enforceBarrelPattern = {
|
|
|
260
367
|
};
|
|
261
368
|
|
|
262
369
|
// src/rules/no-wildcard.ts
|
|
263
|
-
var
|
|
370
|
+
var import_types3 = require("@typescript-eslint/types");
|
|
264
371
|
var noWildcard = {
|
|
265
372
|
meta: {
|
|
266
373
|
type: "problem",
|
|
@@ -300,6 +407,7 @@ var noWildcard = {
|
|
|
300
407
|
// src/index.ts
|
|
301
408
|
var rules = {
|
|
302
409
|
"enforce-barrel-pattern": enforceBarrelPattern,
|
|
410
|
+
"isolate-barrel-file": isolateBarrelFile,
|
|
303
411
|
"no-wildcard": noWildcard
|
|
304
412
|
};
|
|
305
413
|
var index_default = { rules };
|
package/dist/index.d.cts
CHANGED
|
@@ -2,11 +2,17 @@ import * as _typescript_eslint_utils_ts_eslint from '@typescript-eslint/utils/ts
|
|
|
2
2
|
|
|
3
3
|
declare const _default: {
|
|
4
4
|
rules: {
|
|
5
|
-
"enforce-barrel-pattern": _typescript_eslint_utils_ts_eslint.RuleModule<"DirectImportDisallowed" | "
|
|
5
|
+
"enforce-barrel-pattern": _typescript_eslint_utils_ts_eslint.RuleModule<"DirectImportDisallowed" | "TransformedAliasResolveFailed" | "EmptyEslintConfig", {
|
|
6
6
|
paths: string[];
|
|
7
7
|
baseDir: string;
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
}[], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
|
|
9
|
+
"isolate-barrel-file": _typescript_eslint_utils_ts_eslint.RuleModule<"TransformedAliasResolveFailed" | "IsolatedBarrelImportDisallowed", {
|
|
10
|
+
isolations: {
|
|
11
|
+
path: string;
|
|
12
|
+
allowedPaths: string[];
|
|
13
|
+
}[];
|
|
14
|
+
baseDir: string;
|
|
15
|
+
globalAllowPaths: string[];
|
|
10
16
|
}[], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
|
|
11
17
|
"no-wildcard": _typescript_eslint_utils_ts_eslint.RuleModule<"NoWildcardImport" | "NoExportAll", [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
|
|
12
18
|
};
|
package/dist/index.d.ts
CHANGED
|
@@ -2,11 +2,17 @@ import * as _typescript_eslint_utils_ts_eslint from '@typescript-eslint/utils/ts
|
|
|
2
2
|
|
|
3
3
|
declare const _default: {
|
|
4
4
|
rules: {
|
|
5
|
-
"enforce-barrel-pattern": _typescript_eslint_utils_ts_eslint.RuleModule<"DirectImportDisallowed" | "
|
|
5
|
+
"enforce-barrel-pattern": _typescript_eslint_utils_ts_eslint.RuleModule<"DirectImportDisallowed" | "TransformedAliasResolveFailed" | "EmptyEslintConfig", {
|
|
6
6
|
paths: string[];
|
|
7
7
|
baseDir: string;
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
}[], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
|
|
9
|
+
"isolate-barrel-file": _typescript_eslint_utils_ts_eslint.RuleModule<"TransformedAliasResolveFailed" | "IsolatedBarrelImportDisallowed", {
|
|
10
|
+
isolations: {
|
|
11
|
+
path: string;
|
|
12
|
+
allowedPaths: string[];
|
|
13
|
+
}[];
|
|
14
|
+
baseDir: string;
|
|
15
|
+
globalAllowPaths: string[];
|
|
10
16
|
}[], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
|
|
11
17
|
"no-wildcard": _typescript_eslint_utils_ts_eslint.RuleModule<"NoWildcardImport" | "NoExportAll", [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
|
|
12
18
|
};
|
package/dist/index.js
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
// src/rules/enforce-barrel-pattern.ts
|
|
2
|
-
import "@typescript-eslint/
|
|
2
|
+
import "@typescript-eslint/types";
|
|
3
3
|
import path2 from "path";
|
|
4
4
|
import resolve from "resolve";
|
|
5
5
|
|
|
6
6
|
// src/utils/glob.ts
|
|
7
7
|
import FastGlob from "fast-glob";
|
|
8
8
|
var Glob = class {
|
|
9
|
-
static resolvePath(
|
|
10
|
-
const globResult = FastGlob.sync(
|
|
9
|
+
static resolvePath(path4, baseDir) {
|
|
10
|
+
const globResult = FastGlob.sync(path4, {
|
|
11
11
|
cwd: baseDir,
|
|
12
12
|
onlyDirectories: true,
|
|
13
13
|
absolute: true
|
|
14
14
|
});
|
|
15
15
|
if (globResult.length === 0) {
|
|
16
16
|
throw new Error(
|
|
17
|
-
`[Glob] In baseDir: ${baseDir}, path: ${
|
|
17
|
+
`[Glob] In baseDir: ${baseDir}, path: ${path4}, any directory was not found`
|
|
18
18
|
);
|
|
19
19
|
}
|
|
20
20
|
return globResult;
|
|
@@ -106,37 +106,47 @@ var enforceBarrelPattern = {
|
|
|
106
106
|
type: "object",
|
|
107
107
|
properties: {
|
|
108
108
|
paths: { type: "array", items: { type: "string" } },
|
|
109
|
-
baseDir: { type: "string" }
|
|
110
|
-
isolated: { type: "boolean" },
|
|
111
|
-
allowedImportPaths: { type: "array", items: { type: "string" } }
|
|
109
|
+
baseDir: { type: "string" }
|
|
112
110
|
},
|
|
113
|
-
required: ["paths"],
|
|
111
|
+
required: ["paths", "baseDir"],
|
|
114
112
|
additionalProperties: false
|
|
115
113
|
}
|
|
116
114
|
],
|
|
117
115
|
messages: {
|
|
116
|
+
TransformedAliasResolveFailed: "Transformed alias resolve failed. please check the alias config.",
|
|
118
117
|
DirectImportDisallowed: "Please import from '{{matchedTargetPath}}'. Direct access to '{{rawImportPath}}' is not allowed. You must use the barrel pattern and only consume APIs exposed externally. This is to ensure encapsulation of internal logic and maintain module boundaries.",
|
|
119
|
-
|
|
118
|
+
EmptyEslintConfig: "Please set the eslint config '{{property}}' to the eslint config. if you want to use this rule, please set the eslint config."
|
|
120
119
|
}
|
|
121
120
|
},
|
|
122
121
|
//default options(baseDir is current working directory. almost user execute eslint in project root)
|
|
123
122
|
defaultOptions: [
|
|
124
123
|
{
|
|
125
124
|
paths: [],
|
|
126
|
-
baseDir: process.cwd()
|
|
127
|
-
isolated: false,
|
|
128
|
-
allowedImportPaths: []
|
|
125
|
+
baseDir: process.cwd()
|
|
129
126
|
}
|
|
130
127
|
],
|
|
131
128
|
create(context) {
|
|
132
129
|
const option = context.options[0];
|
|
130
|
+
if (!option) {
|
|
131
|
+
return {
|
|
132
|
+
Program(node) {
|
|
133
|
+
const option2 = context.options[0];
|
|
134
|
+
if (!option2) {
|
|
135
|
+
return context.report({
|
|
136
|
+
node,
|
|
137
|
+
messageId: "EmptyEslintConfig",
|
|
138
|
+
data: {
|
|
139
|
+
property: "{ path: Array<string>, baseDir: string }"
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
|
+
}
|
|
133
146
|
const baseDir = option.baseDir;
|
|
134
147
|
const absoluteTargetPaths = option.paths.flatMap((_path) => {
|
|
135
148
|
return Glob.resolvePath(_path, baseDir);
|
|
136
149
|
});
|
|
137
|
-
const allowedImportPaths = option.allowedImportPaths.flatMap((_path) => {
|
|
138
|
-
return Glob.resolvePath(_path, baseDir);
|
|
139
|
-
});
|
|
140
150
|
return {
|
|
141
151
|
//check only import declaration(ESM)
|
|
142
152
|
ImportDeclaration(node) {
|
|
@@ -157,6 +167,10 @@ var enforceBarrelPattern = {
|
|
|
157
167
|
});
|
|
158
168
|
}
|
|
159
169
|
} catch (e) {
|
|
170
|
+
context.report({
|
|
171
|
+
node,
|
|
172
|
+
messageId: "TransformedAliasResolveFailed"
|
|
173
|
+
});
|
|
160
174
|
return;
|
|
161
175
|
}
|
|
162
176
|
{
|
|
@@ -189,34 +203,127 @@ var enforceBarrelPattern = {
|
|
|
189
203
|
});
|
|
190
204
|
}
|
|
191
205
|
}
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
206
|
+
}
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
};
|
|
210
|
+
|
|
211
|
+
// src/rules/isolate-barrel-file.ts
|
|
212
|
+
import "@typescript-eslint/types";
|
|
213
|
+
import path3 from "path";
|
|
214
|
+
import resolve2 from "resolve";
|
|
215
|
+
var RESOLVE_EXTENSIONS2 = [
|
|
216
|
+
".ts",
|
|
217
|
+
".tsx",
|
|
218
|
+
".js",
|
|
219
|
+
".jsx",
|
|
220
|
+
".d.ts",
|
|
221
|
+
".mjs",
|
|
222
|
+
".cjs"
|
|
223
|
+
];
|
|
224
|
+
var isolateBarrelFile = {
|
|
225
|
+
meta: {
|
|
226
|
+
type: "problem",
|
|
227
|
+
docs: {
|
|
228
|
+
description: "Isolate barrel file is not allowed to import outside of the barrel file"
|
|
229
|
+
},
|
|
230
|
+
schema: [
|
|
231
|
+
{
|
|
232
|
+
type: "object",
|
|
233
|
+
properties: {
|
|
234
|
+
isolations: { type: "array", items: { type: "object" } },
|
|
235
|
+
baseDir: { type: "string" },
|
|
236
|
+
globalAllowPaths: { type: "array", items: { type: "string" } }
|
|
237
|
+
},
|
|
238
|
+
required: ["isolations", "baseDir", "globalAllowPaths"],
|
|
239
|
+
additionalProperties: false
|
|
240
|
+
}
|
|
241
|
+
],
|
|
242
|
+
messages: {
|
|
243
|
+
TransformedAliasResolveFailed: "Transformed alias resolve failed. please check the alias config.",
|
|
244
|
+
IsolatedBarrelImportDisallowed: "This barrel file is isolated. external import is not allowed. if you want to import outside of the barrel file, please add 'allowedPath' to the plugin options."
|
|
245
|
+
}
|
|
246
|
+
},
|
|
247
|
+
//default options(baseDir is current working directory. almost user execute eslint in project root)
|
|
248
|
+
defaultOptions: [
|
|
249
|
+
{
|
|
250
|
+
isolations: [],
|
|
251
|
+
baseDir: process.cwd(),
|
|
252
|
+
globalAllowPaths: []
|
|
253
|
+
}
|
|
254
|
+
],
|
|
255
|
+
create(context) {
|
|
256
|
+
const option = context.options[0];
|
|
257
|
+
const baseDir = option.baseDir;
|
|
258
|
+
const absoluteGlobalAllowPaths = option.globalAllowPaths.flatMap((path4) => {
|
|
259
|
+
return Glob.resolvePath(path4, baseDir);
|
|
260
|
+
});
|
|
261
|
+
const absoluteIsolations = option.isolations.flatMap((isolation) => {
|
|
262
|
+
const isolationPaths = Glob.resolvePath(isolation.path, baseDir);
|
|
263
|
+
const allowedPaths = isolation.allowedPaths.flatMap((path4) => {
|
|
264
|
+
return Glob.resolvePath(path4, baseDir);
|
|
265
|
+
});
|
|
266
|
+
return isolationPaths.map((isolationPath) => ({
|
|
267
|
+
isolationPath,
|
|
268
|
+
//self isolatedPath also allowed to be imported
|
|
269
|
+
allowedPaths: [...allowedPaths, isolationPath]
|
|
270
|
+
}));
|
|
271
|
+
});
|
|
272
|
+
return {
|
|
273
|
+
//check only import declaration(ESM)
|
|
274
|
+
ImportDeclaration(node) {
|
|
275
|
+
const rawImportPath = node.source.value;
|
|
276
|
+
const absoluteCurrentFilePath = context.getFilename();
|
|
277
|
+
let absoluteImportPath = null;
|
|
278
|
+
try {
|
|
279
|
+
const aliasResult = Alias.resolvePath(
|
|
280
|
+
rawImportPath,
|
|
281
|
+
path3.dirname(absoluteCurrentFilePath)
|
|
282
|
+
);
|
|
283
|
+
if (aliasResult.type === "success") {
|
|
284
|
+
absoluteImportPath = aliasResult.absolutePath;
|
|
285
|
+
} else {
|
|
286
|
+
absoluteImportPath = resolve2.sync(rawImportPath, {
|
|
287
|
+
basedir: path3.dirname(absoluteCurrentFilePath),
|
|
288
|
+
extensions: RESOLVE_EXTENSIONS2
|
|
289
|
+
});
|
|
219
290
|
}
|
|
291
|
+
} catch (e) {
|
|
292
|
+
context.report({
|
|
293
|
+
node,
|
|
294
|
+
messageId: "TransformedAliasResolveFailed"
|
|
295
|
+
});
|
|
296
|
+
return;
|
|
297
|
+
}
|
|
298
|
+
const isolationIndex = absoluteIsolations.findIndex((isolation) => {
|
|
299
|
+
const absoluteIsolationPath = isolation.isolationPath;
|
|
300
|
+
const closedIsolationPath = absoluteIsolationPath + "/";
|
|
301
|
+
return absoluteCurrentFilePath.startsWith(closedIsolationPath);
|
|
302
|
+
});
|
|
303
|
+
const matchedIsolation = absoluteIsolations[isolationIndex];
|
|
304
|
+
if (!matchedIsolation) return;
|
|
305
|
+
const isAllowedImport = matchedIsolation.allowedPaths.some(
|
|
306
|
+
(allowedPath) => {
|
|
307
|
+
const same = absoluteImportPath === allowedPath;
|
|
308
|
+
const closedAllowedPath = allowedPath + "/";
|
|
309
|
+
const sub = absoluteImportPath.startsWith(closedAllowedPath);
|
|
310
|
+
return same || sub;
|
|
311
|
+
}
|
|
312
|
+
);
|
|
313
|
+
const isGlobalAllowedImport = absoluteGlobalAllowPaths.some(
|
|
314
|
+
(allowedPath) => {
|
|
315
|
+
const same = absoluteImportPath === allowedPath;
|
|
316
|
+
const closedAllowedPath = allowedPath + "/";
|
|
317
|
+
const sub = absoluteImportPath.startsWith(closedAllowedPath);
|
|
318
|
+
return same || sub;
|
|
319
|
+
}
|
|
320
|
+
);
|
|
321
|
+
const allowedImport = isAllowedImport || isGlobalAllowedImport;
|
|
322
|
+
if (!allowedImport) {
|
|
323
|
+
context.report({
|
|
324
|
+
node,
|
|
325
|
+
messageId: "IsolatedBarrelImportDisallowed"
|
|
326
|
+
});
|
|
220
327
|
}
|
|
221
328
|
}
|
|
222
329
|
};
|
|
@@ -224,7 +331,7 @@ var enforceBarrelPattern = {
|
|
|
224
331
|
};
|
|
225
332
|
|
|
226
333
|
// src/rules/no-wildcard.ts
|
|
227
|
-
import "@typescript-eslint/
|
|
334
|
+
import "@typescript-eslint/types";
|
|
228
335
|
var noWildcard = {
|
|
229
336
|
meta: {
|
|
230
337
|
type: "problem",
|
|
@@ -264,6 +371,7 @@ var noWildcard = {
|
|
|
264
371
|
// src/index.ts
|
|
265
372
|
var rules = {
|
|
266
373
|
"enforce-barrel-pattern": enforceBarrelPattern,
|
|
374
|
+
"isolate-barrel-file": isolateBarrelFile,
|
|
267
375
|
"no-wildcard": noWildcard
|
|
268
376
|
};
|
|
269
377
|
var index_default = { rules };
|
package/package.json
CHANGED
|
@@ -25,15 +25,21 @@
|
|
|
25
25
|
"isolated barrel module",
|
|
26
26
|
"no-wildcard"
|
|
27
27
|
],
|
|
28
|
-
"version": "1.
|
|
28
|
+
"version": "1.3.0",
|
|
29
29
|
"type": "module",
|
|
30
30
|
"main": "dist/index.cjs",
|
|
31
31
|
"module": "dist/index.js",
|
|
32
32
|
"types": "dist/index.d.ts",
|
|
33
33
|
"dependencies": {
|
|
34
|
+
"@types/jest": "^30.0.0",
|
|
35
|
+
"@typescript-eslint/parser": "^8.46.2",
|
|
36
|
+
"@typescript-eslint/rule-tester": "^8.46.2",
|
|
37
|
+
"@typescript-eslint/types": "^8.46.2",
|
|
34
38
|
"@typescript-eslint/utils": "^8.36.0",
|
|
35
39
|
"fast-glob": "^3.3.3",
|
|
40
|
+
"jest": "^30.2.0",
|
|
36
41
|
"resolve": "^1.22.10",
|
|
42
|
+
"ts-jest": "^29.4.5",
|
|
37
43
|
"tsconfig-paths": "^4.2.0"
|
|
38
44
|
},
|
|
39
45
|
"devDependencies": {
|
|
@@ -43,8 +49,11 @@
|
|
|
43
49
|
"typescript": "~5.8.3"
|
|
44
50
|
},
|
|
45
51
|
"scripts": {
|
|
46
|
-
"build": "tsup src/index.ts --dts --format cjs,esm",
|
|
52
|
+
"build": "pnpm run test && tsup src/index.ts --dts --format cjs,esm",
|
|
47
53
|
"type-check": "tsc --noEmit",
|
|
54
|
+
"test": "jest",
|
|
55
|
+
"test:watch": "jest --watch",
|
|
56
|
+
"test:coverage": "jest --coverage",
|
|
48
57
|
"release": "pnpm run build && pnpm publish --access=public"
|
|
49
58
|
}
|
|
50
59
|
}
|