eslint-plugin-barrel-rules 1.4.2 → 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 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.2-blue.svg" alt="Version"/>
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.2-blue.svg" alt="Version"/>
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
@@ -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(path4, baseDir) {
46
- const globResult = import_fast_glob.default.sync(path4, {
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
@@ -325,13 +325,13 @@ var isolateBarrelFile = {
325
325
  create(context) {
326
326
  const option = context.options[0];
327
327
  const baseDir = option.baseDir;
328
- const absoluteGlobalAllowPaths = option.globalAllowPaths.flatMap((path4) => {
329
- return Glob.resolvePath(path4, baseDir);
328
+ const absoluteGlobalAllowPaths = option.globalAllowPaths.flatMap((path5) => {
329
+ return Glob.resolvePath(path5, baseDir);
330
330
  });
331
331
  const absoluteIsolations = option.isolations.flatMap((isolation) => {
332
332
  const isolationPaths = Glob.resolvePath(isolation.path, baseDir);
333
- const allowedPaths = isolation.allowedPaths.flatMap((path4) => {
334
- return Glob.resolvePath(path4, baseDir);
333
+ const allowedPaths = isolation.allowedPaths.flatMap((path5) => {
334
+ return Glob.resolvePath(path5, baseDir);
335
335
  });
336
336
  return isolationPaths.map((isolationPath) => ({
337
337
  isolationPath,
@@ -447,12 +447,257 @@ var noWildcard = {
447
447
  }
448
448
  };
449
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
+
450
695
  // src/index.ts
451
696
  var rules = {
452
697
  "enforce-barrel-pattern": enforceBarrelPattern,
453
698
  "isolate-barrel-file": isolateBarrelFile,
454
- "no-wildcard": noWildcard
455
- // "no-cycle": noCycle,
699
+ "no-wildcard": noWildcard,
700
+ "no-cycle": noCycle
456
701
  };
457
702
  // Annotate the CommonJS export names for ESM import in node:
458
703
  0 && (module.exports = {
package/dist/index.d.cts CHANGED
@@ -14,6 +14,7 @@ declare const rules: {
14
14
  globalAllowPaths: string[];
15
15
  }[], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
16
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>;
17
18
  };
18
19
 
19
20
  export { rules };
package/dist/index.d.ts CHANGED
@@ -14,6 +14,7 @@ declare const rules: {
14
14
  globalAllowPaths: string[];
15
15
  }[], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
16
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>;
17
18
  };
18
19
 
19
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(path4, baseDir) {
10
- const globResult = FastGlob.sync(path4, {
16
+ static resolvePath(path5, baseDir) {
17
+ const globResult = FastGlob.sync(path5, {
11
18
  cwd: baseDir,
12
19
  onlyDirectories: true,
13
20
  absolute: true
@@ -289,13 +296,13 @@ var isolateBarrelFile = {
289
296
  create(context) {
290
297
  const option = context.options[0];
291
298
  const baseDir = option.baseDir;
292
- const absoluteGlobalAllowPaths = option.globalAllowPaths.flatMap((path4) => {
293
- return Glob.resolvePath(path4, baseDir);
299
+ const absoluteGlobalAllowPaths = option.globalAllowPaths.flatMap((path5) => {
300
+ return Glob.resolvePath(path5, baseDir);
294
301
  });
295
302
  const absoluteIsolations = option.isolations.flatMap((isolation) => {
296
303
  const isolationPaths = Glob.resolvePath(isolation.path, baseDir);
297
- const allowedPaths = isolation.allowedPaths.flatMap((path4) => {
298
- return Glob.resolvePath(path4, baseDir);
304
+ const allowedPaths = isolation.allowedPaths.flatMap((path5) => {
305
+ return Glob.resolvePath(path5, baseDir);
299
306
  });
300
307
  return isolationPaths.map((isolationPath) => ({
301
308
  isolationPath,
@@ -411,12 +418,257 @@ var noWildcard = {
411
418
  }
412
419
  };
413
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
+
414
666
  // src/index.ts
415
667
  var rules = {
416
668
  "enforce-barrel-pattern": enforceBarrelPattern,
417
669
  "isolate-barrel-file": isolateBarrelFile,
418
- "no-wildcard": noWildcard
419
- // "no-cycle": noCycle,
670
+ "no-wildcard": noWildcard,
671
+ "no-cycle": noCycle
420
672
  };
421
673
  export {
422
674
  rules
package/package.json CHANGED
@@ -25,7 +25,7 @@
25
25
  "isolated barrel module",
26
26
  "no-wildcard"
27
27
  ],
28
- "version": "1.4.2",
28
+ "version": "1.4.3",
29
29
  "type": "module",
30
30
  "main": "dist/index.cjs",
31
31
  "module": "dist/index.js",