eslint-plugin-barrel-rules 1.3.1 → 1.4.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 +2 -1
- package/README.md +2 -1
- package/dist/index.cjs +65 -58
- package/dist/index.js +65 -58
- package/package.json +2 -1
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.4.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>
|
|
@@ -282,6 +282,7 @@ import { SharedUtil } from "@shared/utils"; // allowedImportPaths에 "src/shared
|
|
|
282
282
|
- **잘못된 경로 설정 검증 기능** (OK)
|
|
283
283
|
- **와일드카드 import/export 제한 규칙** (OK)
|
|
284
284
|
- **지정한 Barrel 경로 격리** (OK)
|
|
285
|
+
- **빈 디렉토리 지원** (예: 'src/shares/\*'가 설정되어 있어도 shares 디렉토리가 비어있어도 됨) (OK)
|
|
285
286
|
|
|
286
287
|
---
|
|
287
288
|
|
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.4.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>
|
|
@@ -291,6 +291,7 @@ import { SharedUtil } from "@shared/utils"; // if "src/shared/*" is in allowedPa
|
|
|
291
291
|
- **Wrong Path Setup Validator** (OK)
|
|
292
292
|
- **Wildcard Import/Export Protection Rule** (OK)
|
|
293
293
|
- **Isolation Barrel Module** (OK)
|
|
294
|
+
- **Empty Directory Support** (e.g., 'src/shares/\*' can be configured even if the shares directory is empty) (OK)
|
|
294
295
|
|
|
295
296
|
---
|
|
296
297
|
|
package/dist/index.cjs
CHANGED
|
@@ -48,11 +48,6 @@ var Glob = class {
|
|
|
48
48
|
onlyDirectories: true,
|
|
49
49
|
absolute: true
|
|
50
50
|
});
|
|
51
|
-
if (globResult.length === 0) {
|
|
52
|
-
throw new Error(
|
|
53
|
-
`[Glob] In baseDir: ${baseDir}, path: ${path4}, any directory was not found`
|
|
54
|
-
);
|
|
55
|
-
}
|
|
56
51
|
return globResult;
|
|
57
52
|
}
|
|
58
53
|
};
|
|
@@ -190,66 +185,78 @@ var enforceBarrelPattern = {
|
|
|
190
185
|
const absoluteTargetPaths = option.paths.flatMap((_path) => {
|
|
191
186
|
return Glob.resolvePath(_path, baseDir);
|
|
192
187
|
});
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
)
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
absoluteImportPath = import_resolve.default.sync(rawImportPath, {
|
|
211
|
-
basedir: import_path2.default.dirname(absoluteCurrentFilePath),
|
|
212
|
-
extensions: RESOLVE_EXTENSIONS
|
|
213
|
-
});
|
|
188
|
+
function checker(node) {
|
|
189
|
+
if (!node.source) {
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
const rawImportPath = node.source.value;
|
|
193
|
+
const absoluteCurrentFilePath = context.getFilename();
|
|
194
|
+
let absoluteImportPath = null;
|
|
195
|
+
try {
|
|
196
|
+
const aliasResult = Alias.resolvePath(
|
|
197
|
+
rawImportPath,
|
|
198
|
+
import_path2.default.dirname(absoluteCurrentFilePath)
|
|
199
|
+
);
|
|
200
|
+
if (aliasResult.type === "success") {
|
|
201
|
+
absoluteImportPath = aliasResult.absolutePath;
|
|
202
|
+
} else {
|
|
203
|
+
if (!rawImportPath.startsWith(".") && !rawImportPath.startsWith("/") || rawImportPath.includes("/node_modules/")) {
|
|
204
|
+
return;
|
|
214
205
|
}
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
messageId: "TransformedAliasResolveFailed"
|
|
206
|
+
absoluteImportPath = import_resolve.default.sync(rawImportPath, {
|
|
207
|
+
basedir: import_path2.default.dirname(absoluteCurrentFilePath),
|
|
208
|
+
extensions: RESOLVE_EXTENSIONS
|
|
219
209
|
});
|
|
220
|
-
return;
|
|
221
210
|
}
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
211
|
+
} catch (e) {
|
|
212
|
+
context.report({
|
|
213
|
+
node,
|
|
214
|
+
messageId: "TransformedAliasResolveFailed"
|
|
215
|
+
});
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
{
|
|
219
|
+
let matchedLatestTargetPath = null;
|
|
220
|
+
const invalidDirectedImport = absoluteTargetPaths.some(
|
|
221
|
+
(absoluteTargetPath) => {
|
|
222
|
+
const targetPathEntryPoints = BARREL_ENTRY_POINT_FILE_NAMES.map(
|
|
223
|
+
(entry) => import_path2.default.resolve(absoluteTargetPath, entry)
|
|
224
|
+
);
|
|
225
|
+
const closedTargetPath = absoluteTargetPath + "/";
|
|
226
|
+
const targetPathEntryPointed = targetPathEntryPoints.includes(absoluteImportPath);
|
|
227
|
+
const importedEnforceBarrelFile = absoluteImportPath.startsWith(closedTargetPath);
|
|
228
|
+
const currentFileInEnforceBarrel = absoluteCurrentFilePath.startsWith(closedTargetPath);
|
|
229
|
+
const importedOutsideOfTargetPath = !currentFileInEnforceBarrel && importedEnforceBarrelFile;
|
|
230
|
+
const invalidImported = !targetPathEntryPointed && importedOutsideOfTargetPath;
|
|
231
|
+
if (invalidImported) {
|
|
232
|
+
matchedLatestTargetPath = absoluteTargetPath;
|
|
239
233
|
}
|
|
240
|
-
|
|
241
|
-
if (invalidDirectedImport) {
|
|
242
|
-
context.report({
|
|
243
|
-
node,
|
|
244
|
-
messageId: "DirectImportDisallowed",
|
|
245
|
-
data: {
|
|
246
|
-
rawImportPath,
|
|
247
|
-
matchedTargetPath: matchedLatestTargetPath
|
|
248
|
-
}
|
|
249
|
-
});
|
|
234
|
+
return invalidImported;
|
|
250
235
|
}
|
|
236
|
+
);
|
|
237
|
+
if (invalidDirectedImport) {
|
|
238
|
+
context.report({
|
|
239
|
+
node,
|
|
240
|
+
messageId: "DirectImportDisallowed",
|
|
241
|
+
data: {
|
|
242
|
+
rawImportPath,
|
|
243
|
+
matchedTargetPath: matchedLatestTargetPath
|
|
244
|
+
}
|
|
245
|
+
});
|
|
251
246
|
}
|
|
252
247
|
}
|
|
248
|
+
}
|
|
249
|
+
return {
|
|
250
|
+
ExportNamedDeclaration(node) {
|
|
251
|
+
return checker(node);
|
|
252
|
+
},
|
|
253
|
+
ExportAllDeclaration(node) {
|
|
254
|
+
return checker(node);
|
|
255
|
+
},
|
|
256
|
+
//check only import declaration(ESM)
|
|
257
|
+
ImportDeclaration(node) {
|
|
258
|
+
return checker(node);
|
|
259
|
+
}
|
|
253
260
|
};
|
|
254
261
|
}
|
|
255
262
|
};
|
package/dist/index.js
CHANGED
|
@@ -12,11 +12,6 @@ var Glob = class {
|
|
|
12
12
|
onlyDirectories: true,
|
|
13
13
|
absolute: true
|
|
14
14
|
});
|
|
15
|
-
if (globResult.length === 0) {
|
|
16
|
-
throw new Error(
|
|
17
|
-
`[Glob] In baseDir: ${baseDir}, path: ${path4}, any directory was not found`
|
|
18
|
-
);
|
|
19
|
-
}
|
|
20
15
|
return globResult;
|
|
21
16
|
}
|
|
22
17
|
};
|
|
@@ -154,66 +149,78 @@ var enforceBarrelPattern = {
|
|
|
154
149
|
const absoluteTargetPaths = option.paths.flatMap((_path) => {
|
|
155
150
|
return Glob.resolvePath(_path, baseDir);
|
|
156
151
|
});
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
)
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
absoluteImportPath = resolve.sync(rawImportPath, {
|
|
175
|
-
basedir: path2.dirname(absoluteCurrentFilePath),
|
|
176
|
-
extensions: RESOLVE_EXTENSIONS
|
|
177
|
-
});
|
|
152
|
+
function checker(node) {
|
|
153
|
+
if (!node.source) {
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
const rawImportPath = node.source.value;
|
|
157
|
+
const absoluteCurrentFilePath = context.getFilename();
|
|
158
|
+
let absoluteImportPath = null;
|
|
159
|
+
try {
|
|
160
|
+
const aliasResult = Alias.resolvePath(
|
|
161
|
+
rawImportPath,
|
|
162
|
+
path2.dirname(absoluteCurrentFilePath)
|
|
163
|
+
);
|
|
164
|
+
if (aliasResult.type === "success") {
|
|
165
|
+
absoluteImportPath = aliasResult.absolutePath;
|
|
166
|
+
} else {
|
|
167
|
+
if (!rawImportPath.startsWith(".") && !rawImportPath.startsWith("/") || rawImportPath.includes("/node_modules/")) {
|
|
168
|
+
return;
|
|
178
169
|
}
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
messageId: "TransformedAliasResolveFailed"
|
|
170
|
+
absoluteImportPath = resolve.sync(rawImportPath, {
|
|
171
|
+
basedir: path2.dirname(absoluteCurrentFilePath),
|
|
172
|
+
extensions: RESOLVE_EXTENSIONS
|
|
183
173
|
});
|
|
184
|
-
return;
|
|
185
174
|
}
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
175
|
+
} catch (e) {
|
|
176
|
+
context.report({
|
|
177
|
+
node,
|
|
178
|
+
messageId: "TransformedAliasResolveFailed"
|
|
179
|
+
});
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
{
|
|
183
|
+
let matchedLatestTargetPath = null;
|
|
184
|
+
const invalidDirectedImport = absoluteTargetPaths.some(
|
|
185
|
+
(absoluteTargetPath) => {
|
|
186
|
+
const targetPathEntryPoints = BARREL_ENTRY_POINT_FILE_NAMES.map(
|
|
187
|
+
(entry) => path2.resolve(absoluteTargetPath, entry)
|
|
188
|
+
);
|
|
189
|
+
const closedTargetPath = absoluteTargetPath + "/";
|
|
190
|
+
const targetPathEntryPointed = targetPathEntryPoints.includes(absoluteImportPath);
|
|
191
|
+
const importedEnforceBarrelFile = absoluteImportPath.startsWith(closedTargetPath);
|
|
192
|
+
const currentFileInEnforceBarrel = absoluteCurrentFilePath.startsWith(closedTargetPath);
|
|
193
|
+
const importedOutsideOfTargetPath = !currentFileInEnforceBarrel && importedEnforceBarrelFile;
|
|
194
|
+
const invalidImported = !targetPathEntryPointed && importedOutsideOfTargetPath;
|
|
195
|
+
if (invalidImported) {
|
|
196
|
+
matchedLatestTargetPath = absoluteTargetPath;
|
|
203
197
|
}
|
|
204
|
-
|
|
205
|
-
if (invalidDirectedImport) {
|
|
206
|
-
context.report({
|
|
207
|
-
node,
|
|
208
|
-
messageId: "DirectImportDisallowed",
|
|
209
|
-
data: {
|
|
210
|
-
rawImportPath,
|
|
211
|
-
matchedTargetPath: matchedLatestTargetPath
|
|
212
|
-
}
|
|
213
|
-
});
|
|
198
|
+
return invalidImported;
|
|
214
199
|
}
|
|
200
|
+
);
|
|
201
|
+
if (invalidDirectedImport) {
|
|
202
|
+
context.report({
|
|
203
|
+
node,
|
|
204
|
+
messageId: "DirectImportDisallowed",
|
|
205
|
+
data: {
|
|
206
|
+
rawImportPath,
|
|
207
|
+
matchedTargetPath: matchedLatestTargetPath
|
|
208
|
+
}
|
|
209
|
+
});
|
|
215
210
|
}
|
|
216
211
|
}
|
|
212
|
+
}
|
|
213
|
+
return {
|
|
214
|
+
ExportNamedDeclaration(node) {
|
|
215
|
+
return checker(node);
|
|
216
|
+
},
|
|
217
|
+
ExportAllDeclaration(node) {
|
|
218
|
+
return checker(node);
|
|
219
|
+
},
|
|
220
|
+
//check only import declaration(ESM)
|
|
221
|
+
ImportDeclaration(node) {
|
|
222
|
+
return checker(node);
|
|
223
|
+
}
|
|
217
224
|
};
|
|
218
225
|
}
|
|
219
226
|
};
|
package/package.json
CHANGED
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"isolated barrel module",
|
|
26
26
|
"no-wildcard"
|
|
27
27
|
],
|
|
28
|
-
"version": "1.
|
|
28
|
+
"version": "1.4.0",
|
|
29
29
|
"type": "module",
|
|
30
30
|
"main": "dist/index.cjs",
|
|
31
31
|
"module": "dist/index.js",
|
|
@@ -49,6 +49,7 @@
|
|
|
49
49
|
"typescript": "~5.8.3"
|
|
50
50
|
},
|
|
51
51
|
"scripts": {
|
|
52
|
+
"lint": "eslint src/**/*.ts",
|
|
52
53
|
"build": "pnpm run test && tsup src/index.ts --dts --format cjs,esm",
|
|
53
54
|
"type-check": "tsc --noEmit",
|
|
54
55
|
"test": "jest",
|