eslint-plugin-barrel-rules 1.4.0 → 1.4.3
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 +1 -1
- package/README.md +1 -1
- package/dist/index.cjs +295 -32
- package/dist/index.d.cts +16 -17
- package/dist/index.d.ts +16 -17
- package/dist/index.js +298 -32
- package/package.json +8 -8
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.4.
|
|
6
|
+
<img src="https://img.shields.io/badge/version-1.4.3-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>
|
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.4.
|
|
6
|
+
<img src="https://img.shields.io/badge/version-1.4.3-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>
|
package/dist/index.cjs
CHANGED
|
@@ -30,7 +30,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
// src/index.ts
|
|
31
31
|
var index_exports = {};
|
|
32
32
|
__export(index_exports, {
|
|
33
|
-
|
|
33
|
+
rules: () => rules
|
|
34
34
|
});
|
|
35
35
|
module.exports = __toCommonJS(index_exports);
|
|
36
36
|
|
|
@@ -42,8 +42,8 @@ var import_resolve = __toESM(require("resolve"), 1);
|
|
|
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(path5, baseDir) {
|
|
46
|
+
const globResult = import_fast_glob.default.sync(path5, {
|
|
47
47
|
cwd: baseDir,
|
|
48
48
|
onlyDirectories: true,
|
|
49
49
|
absolute: true
|
|
@@ -106,33 +106,59 @@ var Alias = class {
|
|
|
106
106
|
}
|
|
107
107
|
};
|
|
108
108
|
|
|
109
|
-
// src/
|
|
109
|
+
// src/utils/constants.ts
|
|
110
110
|
var BARREL_ENTRY_POINT_FILE_NAMES = [
|
|
111
111
|
"index.ts",
|
|
112
|
+
// TypeScript entry
|
|
112
113
|
"index.tsx",
|
|
114
|
+
// React TypeScript entry
|
|
113
115
|
"index.js",
|
|
116
|
+
// JavaScript entry
|
|
114
117
|
"index.jsx",
|
|
118
|
+
// React JavaScript entry
|
|
115
119
|
"index.cjs",
|
|
116
|
-
|
|
117
|
-
"index.
|
|
120
|
+
// CommonJS entry
|
|
121
|
+
"index.mjs"
|
|
122
|
+
// ES Module entry
|
|
118
123
|
];
|
|
119
124
|
var RESOLVE_EXTENSIONS = [
|
|
120
125
|
".ts",
|
|
126
|
+
// TypeScript
|
|
121
127
|
".js",
|
|
128
|
+
// JavaScript
|
|
122
129
|
".tsx",
|
|
130
|
+
// React TypeScript
|
|
123
131
|
".jsx",
|
|
132
|
+
// React JavaScript
|
|
124
133
|
".json",
|
|
134
|
+
// JSON file
|
|
135
|
+
// Type declaration and transformed files
|
|
125
136
|
".d.js",
|
|
137
|
+
// JS file with type declarations (rare)
|
|
126
138
|
".d.ts",
|
|
139
|
+
// Type declaration file
|
|
140
|
+
// Various module systems
|
|
127
141
|
".mjs",
|
|
142
|
+
// ES Module
|
|
128
143
|
".cjs",
|
|
144
|
+
// CommonJS
|
|
145
|
+
// Module-related TypeScript extensions
|
|
129
146
|
".mts",
|
|
147
|
+
// ES Module TypeScript
|
|
130
148
|
".cts",
|
|
149
|
+
// CommonJS TypeScript
|
|
150
|
+
// Type declarations for module-related files
|
|
131
151
|
".d.mjs",
|
|
152
|
+
// Type declarations for ES Module
|
|
132
153
|
".d.cjs",
|
|
154
|
+
// Type declarations for CommonJS
|
|
133
155
|
".d.mts",
|
|
156
|
+
// Type declarations for ES Module TS
|
|
134
157
|
".d.cts"
|
|
158
|
+
// Type declarations for CommonJS TS
|
|
135
159
|
];
|
|
160
|
+
|
|
161
|
+
// src/rules/enforce-barrel-pattern.ts
|
|
136
162
|
var enforceBarrelPattern = {
|
|
137
163
|
meta: {
|
|
138
164
|
type: "problem",
|
|
@@ -265,23 +291,6 @@ var enforceBarrelPattern = {
|
|
|
265
291
|
var import_types2 = require("@typescript-eslint/types");
|
|
266
292
|
var import_path3 = __toESM(require("path"), 1);
|
|
267
293
|
var import_resolve2 = __toESM(require("resolve"), 1);
|
|
268
|
-
var RESOLVE_EXTENSIONS2 = [
|
|
269
|
-
".ts",
|
|
270
|
-
".js",
|
|
271
|
-
".tsx",
|
|
272
|
-
".jsx",
|
|
273
|
-
".json",
|
|
274
|
-
".d.js",
|
|
275
|
-
".d.ts",
|
|
276
|
-
".mjs",
|
|
277
|
-
".cjs",
|
|
278
|
-
".mts",
|
|
279
|
-
".cts",
|
|
280
|
-
".d.mjs",
|
|
281
|
-
".d.cjs",
|
|
282
|
-
".d.mts",
|
|
283
|
-
".d.cts"
|
|
284
|
-
];
|
|
285
294
|
var isolateBarrelFile = {
|
|
286
295
|
meta: {
|
|
287
296
|
type: "problem",
|
|
@@ -316,13 +325,13 @@ var isolateBarrelFile = {
|
|
|
316
325
|
create(context) {
|
|
317
326
|
const option = context.options[0];
|
|
318
327
|
const baseDir = option.baseDir;
|
|
319
|
-
const absoluteGlobalAllowPaths = option.globalAllowPaths.flatMap((
|
|
320
|
-
return Glob.resolvePath(
|
|
328
|
+
const absoluteGlobalAllowPaths = option.globalAllowPaths.flatMap((path5) => {
|
|
329
|
+
return Glob.resolvePath(path5, baseDir);
|
|
321
330
|
});
|
|
322
331
|
const absoluteIsolations = option.isolations.flatMap((isolation) => {
|
|
323
332
|
const isolationPaths = Glob.resolvePath(isolation.path, baseDir);
|
|
324
|
-
const allowedPaths = isolation.allowedPaths.flatMap((
|
|
325
|
-
return Glob.resolvePath(
|
|
333
|
+
const allowedPaths = isolation.allowedPaths.flatMap((path5) => {
|
|
334
|
+
return Glob.resolvePath(path5, baseDir);
|
|
326
335
|
});
|
|
327
336
|
return isolationPaths.map((isolationPath) => ({
|
|
328
337
|
isolationPath,
|
|
@@ -334,6 +343,9 @@ var isolateBarrelFile = {
|
|
|
334
343
|
//check only import declaration(ESM)
|
|
335
344
|
ImportDeclaration(node) {
|
|
336
345
|
const rawImportPath = node.source.value;
|
|
346
|
+
if (rawImportPath.includes("/node_modules/")) {
|
|
347
|
+
return;
|
|
348
|
+
}
|
|
337
349
|
const absoluteCurrentFilePath = context.getFilename();
|
|
338
350
|
let absoluteImportPath = null;
|
|
339
351
|
try {
|
|
@@ -343,13 +355,16 @@ var isolateBarrelFile = {
|
|
|
343
355
|
);
|
|
344
356
|
if (aliasResult.type === "success") {
|
|
345
357
|
absoluteImportPath = aliasResult.absolutePath;
|
|
358
|
+
if (absoluteImportPath.includes("/node_modules/")) {
|
|
359
|
+
return;
|
|
360
|
+
}
|
|
346
361
|
} else {
|
|
347
|
-
if (!rawImportPath.startsWith(".") && !rawImportPath.startsWith("/")
|
|
362
|
+
if (!rawImportPath.startsWith(".") && !rawImportPath.startsWith("/")) {
|
|
348
363
|
return;
|
|
349
364
|
}
|
|
350
365
|
absoluteImportPath = import_resolve2.default.sync(rawImportPath, {
|
|
351
366
|
basedir: import_path3.default.dirname(absoluteCurrentFilePath),
|
|
352
|
-
extensions:
|
|
367
|
+
extensions: RESOLVE_EXTENSIONS
|
|
353
368
|
});
|
|
354
369
|
}
|
|
355
370
|
} catch (e) {
|
|
@@ -432,11 +447,259 @@ var noWildcard = {
|
|
|
432
447
|
}
|
|
433
448
|
};
|
|
434
449
|
|
|
450
|
+
// src/rules/no-cycle.ts
|
|
451
|
+
var import_types4 = require("@typescript-eslint/types");
|
|
452
|
+
var import_path4 = __toESM(require("path"), 1);
|
|
453
|
+
var import_resolve3 = __toESM(require("resolve"), 1);
|
|
454
|
+
var importGraph = /* @__PURE__ */ new Map();
|
|
455
|
+
var fileToImports = /* @__PURE__ */ new Map();
|
|
456
|
+
var barrelExportsCache = /* @__PURE__ */ new Map();
|
|
457
|
+
function detectCycle(currentFile, visited, recStack, path5) {
|
|
458
|
+
visited.add(currentFile);
|
|
459
|
+
recStack.add(currentFile);
|
|
460
|
+
path5.push(currentFile);
|
|
461
|
+
const imports = importGraph.get(currentFile) || /* @__PURE__ */ new Set();
|
|
462
|
+
for (const importedFile of imports) {
|
|
463
|
+
if (!visited.has(importedFile)) {
|
|
464
|
+
const cycle = detectCycle(importedFile, visited, recStack, [...path5]);
|
|
465
|
+
if (cycle) {
|
|
466
|
+
return cycle;
|
|
467
|
+
}
|
|
468
|
+
} else if (recStack.has(importedFile)) {
|
|
469
|
+
const cycleStart = path5.indexOf(importedFile);
|
|
470
|
+
return [...path5.slice(cycleStart), importedFile];
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
recStack.delete(currentFile);
|
|
474
|
+
return null;
|
|
475
|
+
}
|
|
476
|
+
function isBarrelFile(filePath) {
|
|
477
|
+
const fileName = import_path4.default.basename(filePath);
|
|
478
|
+
return BARREL_ENTRY_POINT_FILE_NAMES.includes(
|
|
479
|
+
fileName
|
|
480
|
+
);
|
|
481
|
+
}
|
|
482
|
+
function getExportedModulesFromBarrel(barrelFileDir, sourceCode) {
|
|
483
|
+
const exportedModules = [];
|
|
484
|
+
const ast = sourceCode.ast;
|
|
485
|
+
for (const statement of ast.body) {
|
|
486
|
+
if (statement.type === "ExportNamedDeclaration" || statement.type === "ExportAllDeclaration") {
|
|
487
|
+
if (statement.source) {
|
|
488
|
+
const exportPath = statement.source.value;
|
|
489
|
+
try {
|
|
490
|
+
const resolvedPath = import_resolve3.default.sync(exportPath, {
|
|
491
|
+
basedir: barrelFileDir,
|
|
492
|
+
extensions: RESOLVE_EXTENSIONS
|
|
493
|
+
});
|
|
494
|
+
if (!exportedModules.includes(resolvedPath)) {
|
|
495
|
+
exportedModules.push(resolvedPath);
|
|
496
|
+
}
|
|
497
|
+
} catch (e) {
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
if (statement.type === "ImportDeclaration") {
|
|
502
|
+
if (statement.source) {
|
|
503
|
+
const importPath = statement.source.value;
|
|
504
|
+
if (importPath.startsWith(".") || importPath.startsWith("/")) {
|
|
505
|
+
try {
|
|
506
|
+
const resolvedPath = import_resolve3.default.sync(importPath, {
|
|
507
|
+
basedir: barrelFileDir,
|
|
508
|
+
extensions: RESOLVE_EXTENSIONS
|
|
509
|
+
});
|
|
510
|
+
if (!exportedModules.includes(resolvedPath)) {
|
|
511
|
+
exportedModules.push(resolvedPath);
|
|
512
|
+
}
|
|
513
|
+
} catch (e) {
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
return exportedModules;
|
|
520
|
+
}
|
|
521
|
+
var noCycle = {
|
|
522
|
+
meta: {
|
|
523
|
+
type: "problem",
|
|
524
|
+
docs: {
|
|
525
|
+
description: "Detect circular dependencies and enforce relative imports in barrel files."
|
|
526
|
+
},
|
|
527
|
+
schema: [],
|
|
528
|
+
messages: {
|
|
529
|
+
CircularDependency: "Circular dependency detected: {{cyclePath}}. This creates a dependency cycle that can cause runtime errors and make code harder to maintain.",
|
|
530
|
+
BarrelInternalImportDisallowed: "Barrel files (index.ts) must use relative imports (./ or ../) for internal modules. Importing via barrel file or absolute path is not allowed. Use relative path: '{{relativePath}}'",
|
|
531
|
+
TransformedAliasResolveFailed: "Transformed alias resolve failed. please check the alias config."
|
|
532
|
+
}
|
|
533
|
+
},
|
|
534
|
+
defaultOptions: [],
|
|
535
|
+
create(context) {
|
|
536
|
+
const absoluteCurrentFilePath = context.getFilename();
|
|
537
|
+
if (!importGraph.has(absoluteCurrentFilePath)) {
|
|
538
|
+
importGraph.set(absoluteCurrentFilePath, /* @__PURE__ */ new Set());
|
|
539
|
+
}
|
|
540
|
+
const currentImportsSet = importGraph.get(absoluteCurrentFilePath);
|
|
541
|
+
currentImportsSet.clear();
|
|
542
|
+
if (!fileToImports.has(absoluteCurrentFilePath)) {
|
|
543
|
+
fileToImports.set(absoluteCurrentFilePath, /* @__PURE__ */ new Set());
|
|
544
|
+
}
|
|
545
|
+
if (isBarrelFile(absoluteCurrentFilePath)) {
|
|
546
|
+
const barrelFileDir = import_path4.default.dirname(absoluteCurrentFilePath);
|
|
547
|
+
const sourceCode = context.getSourceCode();
|
|
548
|
+
const exportedModules = getExportedModulesFromBarrel(
|
|
549
|
+
barrelFileDir,
|
|
550
|
+
sourceCode
|
|
551
|
+
);
|
|
552
|
+
barrelExportsCache.set(absoluteCurrentFilePath, exportedModules);
|
|
553
|
+
}
|
|
554
|
+
function resolveImportPath(rawImportPath) {
|
|
555
|
+
try {
|
|
556
|
+
const aliasResult = Alias.resolvePath(
|
|
557
|
+
rawImportPath,
|
|
558
|
+
import_path4.default.dirname(absoluteCurrentFilePath)
|
|
559
|
+
);
|
|
560
|
+
if (aliasResult.type === "success") {
|
|
561
|
+
const resolvedPath = aliasResult.absolutePath;
|
|
562
|
+
try {
|
|
563
|
+
const fs = require("fs");
|
|
564
|
+
const stats = fs.statSync(resolvedPath);
|
|
565
|
+
if (stats.isDirectory()) {
|
|
566
|
+
return import_resolve3.default.sync("index", {
|
|
567
|
+
basedir: resolvedPath,
|
|
568
|
+
extensions: RESOLVE_EXTENSIONS
|
|
569
|
+
});
|
|
570
|
+
}
|
|
571
|
+
} catch (e) {
|
|
572
|
+
try {
|
|
573
|
+
return import_resolve3.default.sync(resolvedPath, {
|
|
574
|
+
basedir: import_path4.default.dirname(absoluteCurrentFilePath),
|
|
575
|
+
extensions: RESOLVE_EXTENSIONS
|
|
576
|
+
});
|
|
577
|
+
} catch (e2) {
|
|
578
|
+
return resolvedPath;
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
return resolvedPath;
|
|
582
|
+
} else {
|
|
583
|
+
if (!rawImportPath.startsWith(".") && !rawImportPath.startsWith("/") || rawImportPath.includes("/node_modules/")) {
|
|
584
|
+
return null;
|
|
585
|
+
}
|
|
586
|
+
return import_resolve3.default.sync(rawImportPath, {
|
|
587
|
+
basedir: import_path4.default.dirname(absoluteCurrentFilePath),
|
|
588
|
+
extensions: RESOLVE_EXTENSIONS
|
|
589
|
+
});
|
|
590
|
+
}
|
|
591
|
+
} catch (e) {
|
|
592
|
+
return null;
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
function checker(node) {
|
|
596
|
+
if (!node.source) {
|
|
597
|
+
return;
|
|
598
|
+
}
|
|
599
|
+
const rawImportPath = node.source.value;
|
|
600
|
+
const absoluteImportPath = resolveImportPath(rawImportPath);
|
|
601
|
+
if (!absoluteImportPath) {
|
|
602
|
+
return;
|
|
603
|
+
}
|
|
604
|
+
if (isBarrelFile(absoluteCurrentFilePath)) {
|
|
605
|
+
const barrelFileDir = import_path4.default.dirname(absoluteCurrentFilePath);
|
|
606
|
+
const isInternalModule = absoluteImportPath.startsWith(barrelFileDir + import_path4.default.sep) || absoluteImportPath === barrelFileDir;
|
|
607
|
+
if (isInternalModule) {
|
|
608
|
+
if (!rawImportPath.startsWith("./") && !rawImportPath.startsWith("../")) {
|
|
609
|
+
const relativePath = import_path4.default.relative(
|
|
610
|
+
barrelFileDir,
|
|
611
|
+
absoluteImportPath
|
|
612
|
+
);
|
|
613
|
+
const suggestedRelativePath = relativePath.startsWith(".") ? relativePath : `./${relativePath}`;
|
|
614
|
+
context.report({
|
|
615
|
+
node,
|
|
616
|
+
messageId: "BarrelInternalImportDisallowed",
|
|
617
|
+
data: {
|
|
618
|
+
relativePath: suggestedRelativePath.replace(/\\/g, "/")
|
|
619
|
+
}
|
|
620
|
+
});
|
|
621
|
+
return;
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
const isBarrelImportingInternal = isBarrelFile(absoluteCurrentFilePath) && absoluteImportPath.startsWith(
|
|
626
|
+
import_path4.default.dirname(absoluteCurrentFilePath) + import_path4.default.sep
|
|
627
|
+
);
|
|
628
|
+
const currentImports = importGraph.get(absoluteCurrentFilePath);
|
|
629
|
+
if (currentImports) {
|
|
630
|
+
currentImports.add(absoluteImportPath);
|
|
631
|
+
if (isBarrelFile(absoluteImportPath)) {
|
|
632
|
+
const exportedModules = barrelExportsCache.get(absoluteImportPath) || [];
|
|
633
|
+
for (const exportedModule of exportedModules) {
|
|
634
|
+
if (exportedModule !== absoluteCurrentFilePath) {
|
|
635
|
+
currentImports.add(exportedModule);
|
|
636
|
+
const exportedModuleImports = importGraph.get(exportedModule);
|
|
637
|
+
if (exportedModuleImports && exportedModuleImports.has(absoluteCurrentFilePath)) {
|
|
638
|
+
const cyclePath = `${absoluteCurrentFilePath} \u2192 ${absoluteImportPath} \u2192 ${exportedModule} \u2192 ${absoluteImportPath} \u2192 ${absoluteCurrentFilePath}`;
|
|
639
|
+
context.report({
|
|
640
|
+
node,
|
|
641
|
+
messageId: "CircularDependency",
|
|
642
|
+
data: {
|
|
643
|
+
cyclePath
|
|
644
|
+
}
|
|
645
|
+
});
|
|
646
|
+
return;
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
if (isBarrelImportingInternal) {
|
|
653
|
+
return;
|
|
654
|
+
}
|
|
655
|
+
const importedFileImports = importGraph.get(absoluteImportPath);
|
|
656
|
+
if (importedFileImports && importedFileImports.has(absoluteCurrentFilePath)) {
|
|
657
|
+
const cyclePath = `${absoluteCurrentFilePath} \u2192 ${absoluteImportPath} \u2192 ${absoluteCurrentFilePath}`;
|
|
658
|
+
context.report({
|
|
659
|
+
node,
|
|
660
|
+
messageId: "CircularDependency",
|
|
661
|
+
data: {
|
|
662
|
+
cyclePath
|
|
663
|
+
}
|
|
664
|
+
});
|
|
665
|
+
return;
|
|
666
|
+
}
|
|
667
|
+
const visited = /* @__PURE__ */ new Set();
|
|
668
|
+
const recStack = /* @__PURE__ */ new Set();
|
|
669
|
+
const cycle = detectCycle(absoluteCurrentFilePath, visited, recStack, []);
|
|
670
|
+
if (cycle && cycle.length > 0) {
|
|
671
|
+
const cyclePath = cycle.join(" \u2192 ");
|
|
672
|
+
context.report({
|
|
673
|
+
node,
|
|
674
|
+
messageId: "CircularDependency",
|
|
675
|
+
data: {
|
|
676
|
+
cyclePath
|
|
677
|
+
}
|
|
678
|
+
});
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
return {
|
|
682
|
+
ImportDeclaration(node) {
|
|
683
|
+
return checker(node);
|
|
684
|
+
},
|
|
685
|
+
ExportNamedDeclaration(node) {
|
|
686
|
+
return checker(node);
|
|
687
|
+
},
|
|
688
|
+
ExportAllDeclaration(node) {
|
|
689
|
+
return checker(node);
|
|
690
|
+
}
|
|
691
|
+
};
|
|
692
|
+
}
|
|
693
|
+
};
|
|
694
|
+
|
|
435
695
|
// src/index.ts
|
|
436
696
|
var rules = {
|
|
437
697
|
"enforce-barrel-pattern": enforceBarrelPattern,
|
|
438
698
|
"isolate-barrel-file": isolateBarrelFile,
|
|
439
|
-
"no-wildcard": noWildcard
|
|
699
|
+
"no-wildcard": noWildcard,
|
|
700
|
+
"no-cycle": noCycle
|
|
440
701
|
};
|
|
441
|
-
|
|
442
|
-
module.exports = {
|
|
702
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
703
|
+
0 && (module.exports = {
|
|
704
|
+
rules
|
|
705
|
+
});
|
package/dist/index.d.cts
CHANGED
|
@@ -1,21 +1,20 @@
|
|
|
1
1
|
import * as _typescript_eslint_utils_ts_eslint from '@typescript-eslint/utils/ts-eslint';
|
|
2
2
|
|
|
3
|
-
declare const
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
};
|
|
3
|
+
declare const rules: {
|
|
4
|
+
"enforce-barrel-pattern": _typescript_eslint_utils_ts_eslint.RuleModule<"DirectImportDisallowed" | "TransformedAliasResolveFailed" | "EmptyEslintConfig", {
|
|
5
|
+
paths: string[];
|
|
6
|
+
baseDir: string;
|
|
7
|
+
}[], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
|
|
8
|
+
"isolate-barrel-file": _typescript_eslint_utils_ts_eslint.RuleModule<"TransformedAliasResolveFailed" | "IsolatedBarrelImportDisallowed", {
|
|
9
|
+
isolations: {
|
|
10
|
+
path: string;
|
|
11
|
+
allowedPaths: string[];
|
|
12
|
+
}[];
|
|
13
|
+
baseDir: string;
|
|
14
|
+
globalAllowPaths: string[];
|
|
15
|
+
}[], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
|
|
16
|
+
"no-wildcard": _typescript_eslint_utils_ts_eslint.RuleModule<"NoWildcardImport" | "NoExportAll", [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
|
|
17
|
+
"no-cycle": _typescript_eslint_utils_ts_eslint.RuleModule<"TransformedAliasResolveFailed" | "CircularDependency" | "BarrelInternalImportDisallowed", [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
|
|
19
18
|
};
|
|
20
19
|
|
|
21
|
-
export {
|
|
20
|
+
export { rules };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,21 +1,20 @@
|
|
|
1
1
|
import * as _typescript_eslint_utils_ts_eslint from '@typescript-eslint/utils/ts-eslint';
|
|
2
2
|
|
|
3
|
-
declare const
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
};
|
|
3
|
+
declare const rules: {
|
|
4
|
+
"enforce-barrel-pattern": _typescript_eslint_utils_ts_eslint.RuleModule<"DirectImportDisallowed" | "TransformedAliasResolveFailed" | "EmptyEslintConfig", {
|
|
5
|
+
paths: string[];
|
|
6
|
+
baseDir: string;
|
|
7
|
+
}[], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
|
|
8
|
+
"isolate-barrel-file": _typescript_eslint_utils_ts_eslint.RuleModule<"TransformedAliasResolveFailed" | "IsolatedBarrelImportDisallowed", {
|
|
9
|
+
isolations: {
|
|
10
|
+
path: string;
|
|
11
|
+
allowedPaths: string[];
|
|
12
|
+
}[];
|
|
13
|
+
baseDir: string;
|
|
14
|
+
globalAllowPaths: string[];
|
|
15
|
+
}[], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
|
|
16
|
+
"no-wildcard": _typescript_eslint_utils_ts_eslint.RuleModule<"NoWildcardImport" | "NoExportAll", [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
|
|
17
|
+
"no-cycle": _typescript_eslint_utils_ts_eslint.RuleModule<"TransformedAliasResolveFailed" | "CircularDependency" | "BarrelInternalImportDisallowed", [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
|
|
19
18
|
};
|
|
20
19
|
|
|
21
|
-
export {
|
|
20
|
+
export { rules };
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
2
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
3
|
+
}) : x)(function(x) {
|
|
4
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
5
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
6
|
+
});
|
|
7
|
+
|
|
1
8
|
// src/rules/enforce-barrel-pattern.ts
|
|
2
9
|
import "@typescript-eslint/types";
|
|
3
10
|
import path2 from "path";
|
|
@@ -6,8 +13,8 @@ import resolve from "resolve";
|
|
|
6
13
|
// src/utils/glob.ts
|
|
7
14
|
import FastGlob from "fast-glob";
|
|
8
15
|
var Glob = class {
|
|
9
|
-
static resolvePath(
|
|
10
|
-
const globResult = FastGlob.sync(
|
|
16
|
+
static resolvePath(path5, baseDir) {
|
|
17
|
+
const globResult = FastGlob.sync(path5, {
|
|
11
18
|
cwd: baseDir,
|
|
12
19
|
onlyDirectories: true,
|
|
13
20
|
absolute: true
|
|
@@ -70,33 +77,59 @@ var Alias = class {
|
|
|
70
77
|
}
|
|
71
78
|
};
|
|
72
79
|
|
|
73
|
-
// src/
|
|
80
|
+
// src/utils/constants.ts
|
|
74
81
|
var BARREL_ENTRY_POINT_FILE_NAMES = [
|
|
75
82
|
"index.ts",
|
|
83
|
+
// TypeScript entry
|
|
76
84
|
"index.tsx",
|
|
85
|
+
// React TypeScript entry
|
|
77
86
|
"index.js",
|
|
87
|
+
// JavaScript entry
|
|
78
88
|
"index.jsx",
|
|
89
|
+
// React JavaScript entry
|
|
79
90
|
"index.cjs",
|
|
80
|
-
|
|
81
|
-
"index.
|
|
91
|
+
// CommonJS entry
|
|
92
|
+
"index.mjs"
|
|
93
|
+
// ES Module entry
|
|
82
94
|
];
|
|
83
95
|
var RESOLVE_EXTENSIONS = [
|
|
84
96
|
".ts",
|
|
97
|
+
// TypeScript
|
|
85
98
|
".js",
|
|
99
|
+
// JavaScript
|
|
86
100
|
".tsx",
|
|
101
|
+
// React TypeScript
|
|
87
102
|
".jsx",
|
|
103
|
+
// React JavaScript
|
|
88
104
|
".json",
|
|
105
|
+
// JSON file
|
|
106
|
+
// Type declaration and transformed files
|
|
89
107
|
".d.js",
|
|
108
|
+
// JS file with type declarations (rare)
|
|
90
109
|
".d.ts",
|
|
110
|
+
// Type declaration file
|
|
111
|
+
// Various module systems
|
|
91
112
|
".mjs",
|
|
113
|
+
// ES Module
|
|
92
114
|
".cjs",
|
|
115
|
+
// CommonJS
|
|
116
|
+
// Module-related TypeScript extensions
|
|
93
117
|
".mts",
|
|
118
|
+
// ES Module TypeScript
|
|
94
119
|
".cts",
|
|
120
|
+
// CommonJS TypeScript
|
|
121
|
+
// Type declarations for module-related files
|
|
95
122
|
".d.mjs",
|
|
123
|
+
// Type declarations for ES Module
|
|
96
124
|
".d.cjs",
|
|
125
|
+
// Type declarations for CommonJS
|
|
97
126
|
".d.mts",
|
|
127
|
+
// Type declarations for ES Module TS
|
|
98
128
|
".d.cts"
|
|
129
|
+
// Type declarations for CommonJS TS
|
|
99
130
|
];
|
|
131
|
+
|
|
132
|
+
// src/rules/enforce-barrel-pattern.ts
|
|
100
133
|
var enforceBarrelPattern = {
|
|
101
134
|
meta: {
|
|
102
135
|
type: "problem",
|
|
@@ -229,23 +262,6 @@ var enforceBarrelPattern = {
|
|
|
229
262
|
import "@typescript-eslint/types";
|
|
230
263
|
import path3 from "path";
|
|
231
264
|
import resolve2 from "resolve";
|
|
232
|
-
var RESOLVE_EXTENSIONS2 = [
|
|
233
|
-
".ts",
|
|
234
|
-
".js",
|
|
235
|
-
".tsx",
|
|
236
|
-
".jsx",
|
|
237
|
-
".json",
|
|
238
|
-
".d.js",
|
|
239
|
-
".d.ts",
|
|
240
|
-
".mjs",
|
|
241
|
-
".cjs",
|
|
242
|
-
".mts",
|
|
243
|
-
".cts",
|
|
244
|
-
".d.mjs",
|
|
245
|
-
".d.cjs",
|
|
246
|
-
".d.mts",
|
|
247
|
-
".d.cts"
|
|
248
|
-
];
|
|
249
265
|
var isolateBarrelFile = {
|
|
250
266
|
meta: {
|
|
251
267
|
type: "problem",
|
|
@@ -280,13 +296,13 @@ var isolateBarrelFile = {
|
|
|
280
296
|
create(context) {
|
|
281
297
|
const option = context.options[0];
|
|
282
298
|
const baseDir = option.baseDir;
|
|
283
|
-
const absoluteGlobalAllowPaths = option.globalAllowPaths.flatMap((
|
|
284
|
-
return Glob.resolvePath(
|
|
299
|
+
const absoluteGlobalAllowPaths = option.globalAllowPaths.flatMap((path5) => {
|
|
300
|
+
return Glob.resolvePath(path5, baseDir);
|
|
285
301
|
});
|
|
286
302
|
const absoluteIsolations = option.isolations.flatMap((isolation) => {
|
|
287
303
|
const isolationPaths = Glob.resolvePath(isolation.path, baseDir);
|
|
288
|
-
const allowedPaths = isolation.allowedPaths.flatMap((
|
|
289
|
-
return Glob.resolvePath(
|
|
304
|
+
const allowedPaths = isolation.allowedPaths.flatMap((path5) => {
|
|
305
|
+
return Glob.resolvePath(path5, baseDir);
|
|
290
306
|
});
|
|
291
307
|
return isolationPaths.map((isolationPath) => ({
|
|
292
308
|
isolationPath,
|
|
@@ -298,6 +314,9 @@ var isolateBarrelFile = {
|
|
|
298
314
|
//check only import declaration(ESM)
|
|
299
315
|
ImportDeclaration(node) {
|
|
300
316
|
const rawImportPath = node.source.value;
|
|
317
|
+
if (rawImportPath.includes("/node_modules/")) {
|
|
318
|
+
return;
|
|
319
|
+
}
|
|
301
320
|
const absoluteCurrentFilePath = context.getFilename();
|
|
302
321
|
let absoluteImportPath = null;
|
|
303
322
|
try {
|
|
@@ -307,13 +326,16 @@ var isolateBarrelFile = {
|
|
|
307
326
|
);
|
|
308
327
|
if (aliasResult.type === "success") {
|
|
309
328
|
absoluteImportPath = aliasResult.absolutePath;
|
|
329
|
+
if (absoluteImportPath.includes("/node_modules/")) {
|
|
330
|
+
return;
|
|
331
|
+
}
|
|
310
332
|
} else {
|
|
311
|
-
if (!rawImportPath.startsWith(".") && !rawImportPath.startsWith("/")
|
|
333
|
+
if (!rawImportPath.startsWith(".") && !rawImportPath.startsWith("/")) {
|
|
312
334
|
return;
|
|
313
335
|
}
|
|
314
336
|
absoluteImportPath = resolve2.sync(rawImportPath, {
|
|
315
337
|
basedir: path3.dirname(absoluteCurrentFilePath),
|
|
316
|
-
extensions:
|
|
338
|
+
extensions: RESOLVE_EXTENSIONS
|
|
317
339
|
});
|
|
318
340
|
}
|
|
319
341
|
} catch (e) {
|
|
@@ -396,14 +418,258 @@ var noWildcard = {
|
|
|
396
418
|
}
|
|
397
419
|
};
|
|
398
420
|
|
|
421
|
+
// src/rules/no-cycle.ts
|
|
422
|
+
import "@typescript-eslint/types";
|
|
423
|
+
import path4 from "path";
|
|
424
|
+
import resolve3 from "resolve";
|
|
425
|
+
var importGraph = /* @__PURE__ */ new Map();
|
|
426
|
+
var fileToImports = /* @__PURE__ */ new Map();
|
|
427
|
+
var barrelExportsCache = /* @__PURE__ */ new Map();
|
|
428
|
+
function detectCycle(currentFile, visited, recStack, path5) {
|
|
429
|
+
visited.add(currentFile);
|
|
430
|
+
recStack.add(currentFile);
|
|
431
|
+
path5.push(currentFile);
|
|
432
|
+
const imports = importGraph.get(currentFile) || /* @__PURE__ */ new Set();
|
|
433
|
+
for (const importedFile of imports) {
|
|
434
|
+
if (!visited.has(importedFile)) {
|
|
435
|
+
const cycle = detectCycle(importedFile, visited, recStack, [...path5]);
|
|
436
|
+
if (cycle) {
|
|
437
|
+
return cycle;
|
|
438
|
+
}
|
|
439
|
+
} else if (recStack.has(importedFile)) {
|
|
440
|
+
const cycleStart = path5.indexOf(importedFile);
|
|
441
|
+
return [...path5.slice(cycleStart), importedFile];
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
recStack.delete(currentFile);
|
|
445
|
+
return null;
|
|
446
|
+
}
|
|
447
|
+
function isBarrelFile(filePath) {
|
|
448
|
+
const fileName = path4.basename(filePath);
|
|
449
|
+
return BARREL_ENTRY_POINT_FILE_NAMES.includes(
|
|
450
|
+
fileName
|
|
451
|
+
);
|
|
452
|
+
}
|
|
453
|
+
function getExportedModulesFromBarrel(barrelFileDir, sourceCode) {
|
|
454
|
+
const exportedModules = [];
|
|
455
|
+
const ast = sourceCode.ast;
|
|
456
|
+
for (const statement of ast.body) {
|
|
457
|
+
if (statement.type === "ExportNamedDeclaration" || statement.type === "ExportAllDeclaration") {
|
|
458
|
+
if (statement.source) {
|
|
459
|
+
const exportPath = statement.source.value;
|
|
460
|
+
try {
|
|
461
|
+
const resolvedPath = resolve3.sync(exportPath, {
|
|
462
|
+
basedir: barrelFileDir,
|
|
463
|
+
extensions: RESOLVE_EXTENSIONS
|
|
464
|
+
});
|
|
465
|
+
if (!exportedModules.includes(resolvedPath)) {
|
|
466
|
+
exportedModules.push(resolvedPath);
|
|
467
|
+
}
|
|
468
|
+
} catch (e) {
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
if (statement.type === "ImportDeclaration") {
|
|
473
|
+
if (statement.source) {
|
|
474
|
+
const importPath = statement.source.value;
|
|
475
|
+
if (importPath.startsWith(".") || importPath.startsWith("/")) {
|
|
476
|
+
try {
|
|
477
|
+
const resolvedPath = resolve3.sync(importPath, {
|
|
478
|
+
basedir: barrelFileDir,
|
|
479
|
+
extensions: RESOLVE_EXTENSIONS
|
|
480
|
+
});
|
|
481
|
+
if (!exportedModules.includes(resolvedPath)) {
|
|
482
|
+
exportedModules.push(resolvedPath);
|
|
483
|
+
}
|
|
484
|
+
} catch (e) {
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
return exportedModules;
|
|
491
|
+
}
|
|
492
|
+
var noCycle = {
|
|
493
|
+
meta: {
|
|
494
|
+
type: "problem",
|
|
495
|
+
docs: {
|
|
496
|
+
description: "Detect circular dependencies and enforce relative imports in barrel files."
|
|
497
|
+
},
|
|
498
|
+
schema: [],
|
|
499
|
+
messages: {
|
|
500
|
+
CircularDependency: "Circular dependency detected: {{cyclePath}}. This creates a dependency cycle that can cause runtime errors and make code harder to maintain.",
|
|
501
|
+
BarrelInternalImportDisallowed: "Barrel files (index.ts) must use relative imports (./ or ../) for internal modules. Importing via barrel file or absolute path is not allowed. Use relative path: '{{relativePath}}'",
|
|
502
|
+
TransformedAliasResolveFailed: "Transformed alias resolve failed. please check the alias config."
|
|
503
|
+
}
|
|
504
|
+
},
|
|
505
|
+
defaultOptions: [],
|
|
506
|
+
create(context) {
|
|
507
|
+
const absoluteCurrentFilePath = context.getFilename();
|
|
508
|
+
if (!importGraph.has(absoluteCurrentFilePath)) {
|
|
509
|
+
importGraph.set(absoluteCurrentFilePath, /* @__PURE__ */ new Set());
|
|
510
|
+
}
|
|
511
|
+
const currentImportsSet = importGraph.get(absoluteCurrentFilePath);
|
|
512
|
+
currentImportsSet.clear();
|
|
513
|
+
if (!fileToImports.has(absoluteCurrentFilePath)) {
|
|
514
|
+
fileToImports.set(absoluteCurrentFilePath, /* @__PURE__ */ new Set());
|
|
515
|
+
}
|
|
516
|
+
if (isBarrelFile(absoluteCurrentFilePath)) {
|
|
517
|
+
const barrelFileDir = path4.dirname(absoluteCurrentFilePath);
|
|
518
|
+
const sourceCode = context.getSourceCode();
|
|
519
|
+
const exportedModules = getExportedModulesFromBarrel(
|
|
520
|
+
barrelFileDir,
|
|
521
|
+
sourceCode
|
|
522
|
+
);
|
|
523
|
+
barrelExportsCache.set(absoluteCurrentFilePath, exportedModules);
|
|
524
|
+
}
|
|
525
|
+
function resolveImportPath(rawImportPath) {
|
|
526
|
+
try {
|
|
527
|
+
const aliasResult = Alias.resolvePath(
|
|
528
|
+
rawImportPath,
|
|
529
|
+
path4.dirname(absoluteCurrentFilePath)
|
|
530
|
+
);
|
|
531
|
+
if (aliasResult.type === "success") {
|
|
532
|
+
const resolvedPath = aliasResult.absolutePath;
|
|
533
|
+
try {
|
|
534
|
+
const fs = __require("fs");
|
|
535
|
+
const stats = fs.statSync(resolvedPath);
|
|
536
|
+
if (stats.isDirectory()) {
|
|
537
|
+
return resolve3.sync("index", {
|
|
538
|
+
basedir: resolvedPath,
|
|
539
|
+
extensions: RESOLVE_EXTENSIONS
|
|
540
|
+
});
|
|
541
|
+
}
|
|
542
|
+
} catch (e) {
|
|
543
|
+
try {
|
|
544
|
+
return resolve3.sync(resolvedPath, {
|
|
545
|
+
basedir: path4.dirname(absoluteCurrentFilePath),
|
|
546
|
+
extensions: RESOLVE_EXTENSIONS
|
|
547
|
+
});
|
|
548
|
+
} catch (e2) {
|
|
549
|
+
return resolvedPath;
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
return resolvedPath;
|
|
553
|
+
} else {
|
|
554
|
+
if (!rawImportPath.startsWith(".") && !rawImportPath.startsWith("/") || rawImportPath.includes("/node_modules/")) {
|
|
555
|
+
return null;
|
|
556
|
+
}
|
|
557
|
+
return resolve3.sync(rawImportPath, {
|
|
558
|
+
basedir: path4.dirname(absoluteCurrentFilePath),
|
|
559
|
+
extensions: RESOLVE_EXTENSIONS
|
|
560
|
+
});
|
|
561
|
+
}
|
|
562
|
+
} catch (e) {
|
|
563
|
+
return null;
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
function checker(node) {
|
|
567
|
+
if (!node.source) {
|
|
568
|
+
return;
|
|
569
|
+
}
|
|
570
|
+
const rawImportPath = node.source.value;
|
|
571
|
+
const absoluteImportPath = resolveImportPath(rawImportPath);
|
|
572
|
+
if (!absoluteImportPath) {
|
|
573
|
+
return;
|
|
574
|
+
}
|
|
575
|
+
if (isBarrelFile(absoluteCurrentFilePath)) {
|
|
576
|
+
const barrelFileDir = path4.dirname(absoluteCurrentFilePath);
|
|
577
|
+
const isInternalModule = absoluteImportPath.startsWith(barrelFileDir + path4.sep) || absoluteImportPath === barrelFileDir;
|
|
578
|
+
if (isInternalModule) {
|
|
579
|
+
if (!rawImportPath.startsWith("./") && !rawImportPath.startsWith("../")) {
|
|
580
|
+
const relativePath = path4.relative(
|
|
581
|
+
barrelFileDir,
|
|
582
|
+
absoluteImportPath
|
|
583
|
+
);
|
|
584
|
+
const suggestedRelativePath = relativePath.startsWith(".") ? relativePath : `./${relativePath}`;
|
|
585
|
+
context.report({
|
|
586
|
+
node,
|
|
587
|
+
messageId: "BarrelInternalImportDisallowed",
|
|
588
|
+
data: {
|
|
589
|
+
relativePath: suggestedRelativePath.replace(/\\/g, "/")
|
|
590
|
+
}
|
|
591
|
+
});
|
|
592
|
+
return;
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
const isBarrelImportingInternal = isBarrelFile(absoluteCurrentFilePath) && absoluteImportPath.startsWith(
|
|
597
|
+
path4.dirname(absoluteCurrentFilePath) + path4.sep
|
|
598
|
+
);
|
|
599
|
+
const currentImports = importGraph.get(absoluteCurrentFilePath);
|
|
600
|
+
if (currentImports) {
|
|
601
|
+
currentImports.add(absoluteImportPath);
|
|
602
|
+
if (isBarrelFile(absoluteImportPath)) {
|
|
603
|
+
const exportedModules = barrelExportsCache.get(absoluteImportPath) || [];
|
|
604
|
+
for (const exportedModule of exportedModules) {
|
|
605
|
+
if (exportedModule !== absoluteCurrentFilePath) {
|
|
606
|
+
currentImports.add(exportedModule);
|
|
607
|
+
const exportedModuleImports = importGraph.get(exportedModule);
|
|
608
|
+
if (exportedModuleImports && exportedModuleImports.has(absoluteCurrentFilePath)) {
|
|
609
|
+
const cyclePath = `${absoluteCurrentFilePath} \u2192 ${absoluteImportPath} \u2192 ${exportedModule} \u2192 ${absoluteImportPath} \u2192 ${absoluteCurrentFilePath}`;
|
|
610
|
+
context.report({
|
|
611
|
+
node,
|
|
612
|
+
messageId: "CircularDependency",
|
|
613
|
+
data: {
|
|
614
|
+
cyclePath
|
|
615
|
+
}
|
|
616
|
+
});
|
|
617
|
+
return;
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
if (isBarrelImportingInternal) {
|
|
624
|
+
return;
|
|
625
|
+
}
|
|
626
|
+
const importedFileImports = importGraph.get(absoluteImportPath);
|
|
627
|
+
if (importedFileImports && importedFileImports.has(absoluteCurrentFilePath)) {
|
|
628
|
+
const cyclePath = `${absoluteCurrentFilePath} \u2192 ${absoluteImportPath} \u2192 ${absoluteCurrentFilePath}`;
|
|
629
|
+
context.report({
|
|
630
|
+
node,
|
|
631
|
+
messageId: "CircularDependency",
|
|
632
|
+
data: {
|
|
633
|
+
cyclePath
|
|
634
|
+
}
|
|
635
|
+
});
|
|
636
|
+
return;
|
|
637
|
+
}
|
|
638
|
+
const visited = /* @__PURE__ */ new Set();
|
|
639
|
+
const recStack = /* @__PURE__ */ new Set();
|
|
640
|
+
const cycle = detectCycle(absoluteCurrentFilePath, visited, recStack, []);
|
|
641
|
+
if (cycle && cycle.length > 0) {
|
|
642
|
+
const cyclePath = cycle.join(" \u2192 ");
|
|
643
|
+
context.report({
|
|
644
|
+
node,
|
|
645
|
+
messageId: "CircularDependency",
|
|
646
|
+
data: {
|
|
647
|
+
cyclePath
|
|
648
|
+
}
|
|
649
|
+
});
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
return {
|
|
653
|
+
ImportDeclaration(node) {
|
|
654
|
+
return checker(node);
|
|
655
|
+
},
|
|
656
|
+
ExportNamedDeclaration(node) {
|
|
657
|
+
return checker(node);
|
|
658
|
+
},
|
|
659
|
+
ExportAllDeclaration(node) {
|
|
660
|
+
return checker(node);
|
|
661
|
+
}
|
|
662
|
+
};
|
|
663
|
+
}
|
|
664
|
+
};
|
|
665
|
+
|
|
399
666
|
// src/index.ts
|
|
400
667
|
var rules = {
|
|
401
668
|
"enforce-barrel-pattern": enforceBarrelPattern,
|
|
402
669
|
"isolate-barrel-file": isolateBarrelFile,
|
|
403
|
-
"no-wildcard": noWildcard
|
|
670
|
+
"no-wildcard": noWildcard,
|
|
671
|
+
"no-cycle": noCycle
|
|
404
672
|
};
|
|
405
|
-
var index_default = { rules };
|
|
406
|
-
module.exports = { rules };
|
|
407
673
|
export {
|
|
408
|
-
|
|
674
|
+
rules
|
|
409
675
|
};
|
package/package.json
CHANGED
|
@@ -25,32 +25,32 @@
|
|
|
25
25
|
"isolated barrel module",
|
|
26
26
|
"no-wildcard"
|
|
27
27
|
],
|
|
28
|
-
"version": "1.4.
|
|
28
|
+
"version": "1.4.3",
|
|
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
34
|
"@typescript-eslint/types": "^8.46.2",
|
|
38
35
|
"@typescript-eslint/utils": "^8.36.0",
|
|
39
36
|
"fast-glob": "^3.3.3",
|
|
40
|
-
"jest": "^30.2.0",
|
|
41
37
|
"resolve": "^1.22.10",
|
|
42
|
-
"ts-jest": "^29.4.5",
|
|
43
38
|
"tsconfig-paths": "^4.2.0"
|
|
44
39
|
},
|
|
45
40
|
"devDependencies": {
|
|
41
|
+
"jest": "^30.2.0",
|
|
46
42
|
"@types/node": "^24.0.13",
|
|
47
43
|
"@types/resolve": "^1.20.6",
|
|
48
44
|
"tsup": "^8.5.0",
|
|
49
|
-
"typescript": "~5.8.3"
|
|
45
|
+
"typescript": "~5.8.3",
|
|
46
|
+
"@types/jest": "^30.0.0",
|
|
47
|
+
"@typescript-eslint/parser": "^8.46.2",
|
|
48
|
+
"@typescript-eslint/rule-tester": "^8.46.2",
|
|
49
|
+
"ts-jest": "^29.4.5"
|
|
50
50
|
},
|
|
51
51
|
"scripts": {
|
|
52
52
|
"lint": "eslint src/**/*.ts",
|
|
53
|
-
"build": "pnpm run test && tsup
|
|
53
|
+
"build": "pnpm run test && tsup",
|
|
54
54
|
"type-check": "tsc --noEmit",
|
|
55
55
|
"test": "jest",
|
|
56
56
|
"test:watch": "jest --watch",
|