@boundaries/eslint-plugin 5.4.0 → 6.0.0-beta.1

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.
Files changed (64) hide show
  1. package/README.md +9 -9
  2. package/dist/Config/Config.d.ts +6 -3
  3. package/dist/Config/Config.js +18 -7
  4. package/dist/Config/Recommended.d.ts +1 -1
  5. package/dist/Config/Recommended.js +3 -2
  6. package/dist/Config/Strict.d.ts +1 -1
  7. package/dist/Config/Strict.js +2 -2
  8. package/dist/Debug/Debug.d.ts +34 -0
  9. package/dist/Debug/Debug.js +285 -0
  10. package/dist/Debug/index.d.ts +1 -0
  11. package/dist/{Support → Debug}/index.js +0 -1
  12. package/dist/Elements/Elements.d.ts +9 -7
  13. package/dist/Elements/Elements.js +12 -7
  14. package/dist/Elements/Elements.types.d.ts +1 -0
  15. package/dist/Messages/CustomMessages.d.ts +44 -0
  16. package/dist/Messages/CustomMessages.js +156 -0
  17. package/dist/Messages/CustomMessages.types.d.ts +25 -0
  18. package/dist/Messages/CustomMessages.types.js +2 -0
  19. package/dist/Messages/Messages.d.ts +42 -13
  20. package/dist/Messages/Messages.js +400 -177
  21. package/dist/Messages/index.d.ts +2 -0
  22. package/dist/Messages/index.js +2 -0
  23. package/dist/Public/Config.types.d.ts +2 -2
  24. package/dist/Public/Config.types.js +2 -2
  25. package/dist/Public/Rules.types.d.ts +5 -4
  26. package/dist/Public/Rules.types.js +5 -6
  27. package/dist/Public/Settings.types.d.ts +3 -2
  28. package/dist/Public/Settings.types.js +4 -3
  29. package/dist/Public/index.d.ts +1 -0
  30. package/dist/Rules/Dependencies.d.ts +59 -0
  31. package/dist/Rules/Dependencies.js +439 -0
  32. package/dist/Rules/EntryPoint.js +44 -94
  33. package/dist/Rules/External.js +93 -68
  34. package/dist/Rules/NoIgnored.js +4 -4
  35. package/dist/Rules/NoPrivate.js +18 -5
  36. package/dist/Rules/NoUnknown.js +5 -5
  37. package/dist/Rules/NoUnknownFiles.js +4 -3
  38. package/dist/Rules/Support/DependencyRule.d.ts +9 -1
  39. package/dist/Rules/Support/DependencyRule.js +15 -6
  40. package/dist/Rules/Support/DependencyRule.types.d.ts +1 -1
  41. package/dist/Rules/Support/Helpers.d.ts +6 -2
  42. package/dist/Rules/Support/Helpers.js +7 -31
  43. package/dist/Settings/Helpers.d.ts +83 -1
  44. package/dist/Settings/Helpers.js +197 -7
  45. package/dist/Settings/Settings.d.ts +19 -2
  46. package/dist/Settings/Settings.js +20 -10
  47. package/dist/Settings/Validations.d.ts +11958 -43
  48. package/dist/Settings/Validations.js +783 -157
  49. package/dist/Settings/index.d.ts +0 -1
  50. package/dist/Settings/index.js +0 -1
  51. package/dist/{Settings → Shared}/Settings.types.d.ts +137 -37
  52. package/dist/{Settings → Shared}/Settings.types.js +30 -6
  53. package/dist/{Support/Common.d.ts → Shared/TypeHelpers.d.ts} +18 -0
  54. package/dist/{Support/Common.js → Shared/TypeHelpers.js} +28 -1
  55. package/dist/Shared/index.d.ts +2 -0
  56. package/dist/Shared/index.js +18 -0
  57. package/dist/index.d.ts +1 -1
  58. package/dist/index.js +12 -10
  59. package/package.json +9 -8
  60. package/dist/Rules/ElementTypes.d.ts +0 -25
  61. package/dist/Rules/ElementTypes.js +0 -279
  62. package/dist/Support/Debug.d.ts +0 -5
  63. package/dist/Support/Debug.js +0 -54
  64. package/dist/Support/index.d.ts +0 -2
@@ -1,121 +1,71 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const elements_1 = require("@boundaries/elements");
4
- const Messages_1 = require("../Messages");
5
4
  const Settings_1 = require("../Settings");
6
- const ElementTypes_1 = require("./ElementTypes");
5
+ const Shared_1 = require("../Shared");
6
+ const Dependencies_1 = require("./Dependencies");
7
7
  const Support_1 = require("./Support");
8
- const { RULE_ENTRY_POINT } = Settings_1.SETTINGS;
9
- function errorMessage(ruleData, dependency) {
10
- const ruleReport = ruleData.ruleReport;
11
- if (!ruleReport) {
12
- return `No detailed rule report available. This is likely a bug in ${Settings_1.PLUGIN_NAME}. Please report it at ${Settings_1.PLUGIN_ISSUES_URL}`;
13
- }
14
- if (ruleReport.message) {
15
- return (0, Messages_1.customErrorMessage)(ruleReport.message, dependency);
16
- }
17
- if (ruleReport.isDefault) {
18
- return `No rule allows the entry point '${dependency.to.internalPath}' in dependencies ${(0, Messages_1.elementMessage)(dependency.to)}`;
19
- }
20
- return `The entry point '${dependency.to.internalPath}' is not allowed in ${(0, Messages_1.ruleElementMessage)(ruleReport.disallow, dependency.to.captured)}${(0, Messages_1.dependencyUsageKindMessage)(ruleReport.importKind, dependency, {
21
- prefix: " when importing ",
22
- suffix: "",
23
- })}. Disallowed in rule ${ruleReport.index + 1}`;
24
- }
25
- function modifyTemplates(templates) {
26
- if (!templates) {
27
- return undefined;
28
- }
8
+ const { RULE_ENTRY_POINT } = Shared_1.SETTINGS;
9
+ /**
10
+ * Adapts legacy template placeholders from `target` to `to` notation.
11
+ *
12
+ * @param templates - Legacy templates from rule options.
13
+ * @returns Normalized templates or `undefined` when not provided.
14
+ */
15
+ function modifyLegacyTemplates(templates) {
29
16
  const templatesArray = Array.isArray(templates) ? templates : [templates];
30
17
  return templatesArray.map((template) => template.replaceAll("${target.", "${to."));
31
18
  }
32
- function modifyRules(rules) {
19
+ /**
20
+ * Converts `entry-point` legacy rules to `dependencies` rule shape.
21
+ *
22
+ * @param rules - Entry-point rules as defined by user configuration.
23
+ * @returns Equivalent dependencies rules for shared evaluator.
24
+ */
25
+ function transformToDependenciesRules(rules) {
33
26
  const newRules = [];
34
- for (let i = 0; i < rules.length; i++) {
35
- const rule = rules[i];
27
+ for (const rule of rules) {
36
28
  const newTargets = (0, elements_1.normalizeElementsSelector)(rule.target);
37
- const ruleHasDisallow = !!rule.disallow;
38
- const ruleHasAllow = !!rule.allow;
39
- let internalPathPatterns = undefined;
40
- let allowPattern = undefined;
41
- let disallowPattern = undefined;
42
- if (ruleHasDisallow && ruleHasAllow) {
43
- // Workaround to support both allow and disallow in the same rule
44
- const toAdd = [
45
- {
46
- to: newTargets.map((target) => {
47
- return {
48
- ...target,
49
- internalPath: modifyTemplates(rule.allow),
50
- };
51
- }),
52
- allow: ["*"],
53
- importKind: rule.importKind,
54
- message: rule.message,
55
- originalRuleIndex: i,
56
- },
57
- {
58
- to: newTargets.map((target) => {
59
- return {
60
- ...target,
61
- internalPath: modifyTemplates(rule.disallow),
62
- };
63
- }),
64
- disallow: ["*"],
65
- importKind: rule.importKind,
66
- message: rule.message,
67
- originalRuleIndex: i,
68
- },
69
- ];
70
- newRules.push(...toAdd);
71
- }
72
- if (ruleHasDisallow) {
73
- internalPathPatterns = modifyTemplates(rule.disallow);
74
- disallowPattern = ["*"];
75
- }
76
- else if (ruleHasAllow) {
77
- internalPathPatterns = modifyTemplates(rule.allow);
78
- allowPattern = ["*"];
29
+ for (const target of newTargets) {
30
+ newRules.push({
31
+ to: target,
32
+ allow: rule.allow
33
+ ? { to: { internalPath: modifyLegacyTemplates(rule.allow) } }
34
+ : undefined,
35
+ disallow: rule.disallow
36
+ ? { to: { internalPath: modifyLegacyTemplates(rule.disallow) } }
37
+ : undefined,
38
+ importKind: rule.importKind,
39
+ message: rule.message,
40
+ });
79
41
  }
80
- newRules.push({
81
- to: newTargets.map((target) => {
82
- return {
83
- ...target,
84
- internalPath: internalPathPatterns,
85
- };
86
- }),
87
- allow: allowPattern,
88
- disallow: disallowPattern,
89
- importKind: rule.importKind,
90
- message: rule.message,
91
- // @ts-expect-error Workaround to support both allow and disallow in the same entry point rule
92
- originalRuleIndex: i,
93
- });
94
42
  }
95
43
  return newRules;
96
44
  }
97
45
  exports.default = (0, Support_1.dependencyRule)({
98
46
  ruleName: RULE_ENTRY_POINT,
99
- description: `Check entry point used for each element type`,
47
+ description: `Check elements entry point`,
100
48
  schema: (0, Settings_1.rulesOptionsSchema)({
101
49
  rulesMainKey: "target",
50
+ isLegacy: true,
102
51
  }),
103
52
  }, function ({ dependency, node, context, settings, options }) {
53
+ (0, Settings_1.warnMigrationToDependencies)(Shared_1.RULE_NAMES_MAP.ENTRY_POINT);
54
+ // Validate and warn about legacy selector syntax
55
+ (0, Settings_1.validateAndWarnRuleOptions)(options, Shared_1.RULE_NAMES_MAP.ENTRY_POINT, "target");
104
56
  if (!dependency.to.isIgnored &&
105
57
  dependency.to.type &&
106
58
  dependency.dependency.relationship.to !==
107
59
  elements_1.DEPENDENCY_RELATIONSHIPS_MAP.INTERNAL) {
108
- const adaptedRuleOptions = {
109
- ...options,
110
- rules: options && options.rules ? modifyRules(options.rules) : [],
111
- };
112
- const ruleData = (0, ElementTypes_1.elementRulesAllowDependency)(dependency, settings, adaptedRuleOptions);
113
- if (!ruleData.result) {
114
- context.report({
115
- message: errorMessage(ruleData, dependency),
116
- node: node,
117
- });
118
- }
60
+ const rules = transformToDependenciesRules(options?.rules ?? []);
61
+ (0, Dependencies_1.evaluateRulesAndReport)({
62
+ rules,
63
+ settings,
64
+ context,
65
+ node,
66
+ options,
67
+ dependency,
68
+ });
119
69
  }
120
70
  }, {
121
71
  validateRules: { onlyMainKey: true, mainKey: "target" },
@@ -1,72 +1,103 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const elements_1 = require("@boundaries/elements");
4
- const Messages_1 = require("../Messages");
5
4
  const Settings_1 = require("../Settings");
6
- const Support_1 = require("../Support");
7
- const ElementTypes_1 = require("./ElementTypes");
8
- const Support_2 = require("./Support");
9
- const { RULE_EXTERNAL } = Settings_1.SETTINGS;
10
- function getErrorReportMessage(report) {
11
- if (report.path) {
12
- return report.path;
13
- }
14
- return report.specifiers && report.specifiers.length > 0
15
- ? report.specifiers.join(", ")
16
- : undefined;
5
+ const Shared_1 = require("../Shared");
6
+ const Dependencies_1 = require("./Dependencies");
7
+ const Support_1 = require("./Support");
8
+ const { RULE_EXTERNAL } = Shared_1.SETTINGS;
9
+ /**
10
+ * Type guard for external selectors using tuple syntax with options.
11
+ *
12
+ * @param selector - External library selector from rule options.
13
+ * @returns `true` when selector is `[module, options]`.
14
+ */
15
+ function isExternalLibrarySelectorWithOptions(selector) {
16
+ return ((0, Shared_1.isArray)(selector) &&
17
+ selector.length === 2 &&
18
+ (0, Shared_1.isString)(selector[0]) &&
19
+ (0, Shared_1.isObject)(selector[1]));
17
20
  }
18
- function errorMessage(ruleData, dependency) {
19
- const ruleReport = ruleData.ruleReport;
20
- if (!ruleReport) {
21
- return `No detailed rule report available. This is likely a bug in ${Settings_1.PLUGIN_NAME}. Please report it at ${Settings_1.PLUGIN_ISSUES_URL}`;
22
- }
23
- if (ruleReport.message) {
24
- return (0, Messages_1.customErrorMessage)(ruleReport.message, dependency, {
25
- specifiers: ruleData.report?.specifiers && ruleData.report?.specifiers.length > 0
26
- ? ruleData.report?.specifiers?.join(", ")
27
- : undefined,
28
- path: ruleData.report?.path,
29
- });
30
- }
31
- if (ruleReport.isDefault) {
32
- return `No rule allows the usage of external module '${dependency.to.baseSource}' in elements ${(0, Messages_1.elementMessage)(dependency.from)}`;
33
- }
34
- const fileReport = `is not allowed in ${(0, Messages_1.ruleElementMessage)(ruleReport.element, dependency.from.captured)}. Disallowed in rule ${ruleReport.index + 1}`;
35
- if ((ruleData.report?.specifiers && ruleData.report?.specifiers.length > 0) ||
36
- ruleData.report?.path) {
37
- return `Usage of ${(0, Messages_1.dependencyUsageKindMessage)(ruleReport.importKind, dependency)}'${getErrorReportMessage(ruleData.report)}' from external module '${dependency.to.baseSource}' ${fileReport}`;
38
- }
39
- return `Usage of ${(0, Messages_1.dependencyUsageKindMessage)(ruleReport.importKind, dependency, {
40
- suffix: " from ",
41
- })}external module '${dependency.to.baseSource}' ${fileReport}`;
21
+ /**
22
+ * Builds a dependency selector from a legacy external selector using tuple syntax with options.
23
+ * @param selector The external library selector in legacy format with options.
24
+ * @returns The corresponding dependency selector compatible with `dependencies` rule evaluator.
25
+ */
26
+ function buildSelectorFromLegacySelectorWithOptions(selector) {
27
+ const moduleSelector = selector[0];
28
+ const selectorOptions = selector[1];
29
+ const hasPathSelector = !(0, Shared_1.isNullish)(selectorOptions.path);
30
+ return {
31
+ to: {
32
+ origin: [elements_1.ELEMENT_ORIGINS_MAP.EXTERNAL, elements_1.ELEMENT_ORIGINS_MAP.CORE],
33
+ ...(hasPathSelector ? { internalPath: selectorOptions.path } : {}),
34
+ },
35
+ dependency: {
36
+ module: moduleSelector,
37
+ ...(selectorOptions.specifiers
38
+ ? {
39
+ specifiers: selectorOptions.specifiers,
40
+ }
41
+ : {}),
42
+ },
43
+ };
42
44
  }
45
+ /**
46
+ * Transforms legacy external selectors into dependency selectors.
47
+ *
48
+ * @param selectors - External selector(s) from legacy rule format.
49
+ * @returns Dependency selector(s) compatible with `dependencies` rule evaluator.
50
+ */
43
51
  function modifySelectors(selectors) {
44
52
  const originsToMatch = [
45
53
  elements_1.ELEMENT_ORIGINS_MAP.EXTERNAL,
46
54
  elements_1.ELEMENT_ORIGINS_MAP.CORE,
47
55
  ];
48
- if ((0, Support_1.isString)(selectors)) {
49
- return [{ baseSource: selectors, origin: originsToMatch }];
56
+ if (isExternalLibrarySelectorWithOptions(selectors)) {
57
+ return buildSelectorFromLegacySelectorWithOptions(selectors);
50
58
  }
51
- return selectors.map((selector) => {
52
- if ((0, Support_1.isArray)(selector)) {
53
- return {
59
+ if ((0, Shared_1.isString)(selectors)) {
60
+ return {
61
+ to: {
54
62
  origin: originsToMatch,
55
- baseSource: selector[0],
56
- specifiers: selector[1].specifiers,
57
- internalPath: selector[1].path,
58
- };
63
+ },
64
+ dependency: {
65
+ module: selectors,
66
+ },
67
+ };
68
+ }
69
+ return selectors.map((selector) => {
70
+ if (isExternalLibrarySelectorWithOptions(selector)) {
71
+ return buildSelectorFromLegacySelectorWithOptions(selector);
59
72
  }
60
73
  return {
61
- origin: originsToMatch,
62
- baseSource: selector,
74
+ to: { origin: originsToMatch },
75
+ dependency: {
76
+ module: selector,
77
+ },
63
78
  };
64
79
  });
65
80
  }
66
- exports.default = (0, Support_2.dependencyRule)({
81
+ /**
82
+ * Converts `external` legacy rules to `dependencies` rule shape.
83
+ *
84
+ * @param rules - External rules as configured by the user.
85
+ * @returns Equivalent dependencies rules consumed by shared evaluator.
86
+ */
87
+ function transformToDependenciesRules(rules) {
88
+ return rules.map((rule) => ({
89
+ from: rule.from,
90
+ allow: rule.allow ? modifySelectors(rule.allow) : undefined,
91
+ disallow: rule.disallow ? modifySelectors(rule.disallow) : undefined,
92
+ importKind: rule.importKind,
93
+ message: rule.message,
94
+ }));
95
+ }
96
+ exports.default = (0, Support_1.dependencyRule)({
67
97
  ruleName: RULE_EXTERNAL,
68
- description: `Check allowed external dependencies by element type`,
98
+ description: `Check dependencies to external and core libraries`,
69
99
  schema: (0, Settings_1.rulesOptionsSchema)({
100
+ isLegacy: true,
70
101
  targetMatcherOptions: {
71
102
  type: "object",
72
103
  properties: {
@@ -77,7 +108,7 @@ exports.default = (0, Support_2.dependencyRule)({
77
108
  },
78
109
  },
79
110
  path: {
80
- oneOf: [
111
+ anyOf: [
81
112
  {
82
113
  type: "string",
83
114
  },
@@ -94,26 +125,20 @@ exports.default = (0, Support_2.dependencyRule)({
94
125
  },
95
126
  }),
96
127
  }, function ({ dependency, node, context, settings, options }) {
128
+ (0, Settings_1.warnMigrationToDependencies)(Shared_1.RULE_NAMES_MAP.EXTERNAL);
129
+ // Validate and warn about legacy selector syntax
130
+ (0, Settings_1.validateAndWarnRuleOptions)(options, Shared_1.RULE_NAMES_MAP.EXTERNAL, "from");
97
131
  if ((0, elements_1.isExternalDependencyElement)(dependency.to) ||
98
132
  (0, elements_1.isCoreDependencyElement)(dependency.to)) {
99
- const adaptedRuleOptions = {
100
- ...options,
101
- // @ts-expect-error TODO: Fix type
102
- rules: options && options.rules
103
- ? options.rules.map((rule) => ({
104
- ...rule,
105
- allow: rule.allow && modifySelectors(rule.allow),
106
- disallow: rule.disallow && modifySelectors(rule.disallow),
107
- }))
108
- : [],
109
- };
110
- const ruleData = (0, ElementTypes_1.elementRulesAllowDependency)(dependency, settings, adaptedRuleOptions);
111
- if (!ruleData.result) {
112
- context.report({
113
- message: errorMessage(ruleData, dependency),
114
- node: node,
115
- });
116
- }
133
+ const rules = transformToDependenciesRules(options?.rules ?? []);
134
+ (0, Dependencies_1.evaluateRulesAndReport)({
135
+ rules,
136
+ settings,
137
+ context,
138
+ node,
139
+ options,
140
+ dependency,
141
+ });
117
142
  }
118
143
  }, {
119
144
  validateRules: { onlyMainKey: true },
@@ -1,16 +1,16 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- const Settings_1 = require("../Settings");
3
+ const Shared_1 = require("../Shared");
4
4
  const Support_1 = require("./Support");
5
- const { RULE_NO_IGNORED } = Settings_1.SETTINGS;
5
+ const { RULE_NO_IGNORED } = Shared_1.SETTINGS;
6
6
  exports.default = (0, Support_1.dependencyRule)({
7
7
  schema: [],
8
8
  ruleName: RULE_NO_IGNORED,
9
- description: `Prevent importing ignored files from recognized elements`,
9
+ description: `Prevent dependencies to ignored files from recognized elements`,
10
10
  }, function ({ dependency, node, context }) {
11
11
  if (dependency.to.isIgnored) {
12
12
  context.report({
13
- message: `Importing ignored files is not allowed`,
13
+ message: `Dependencies to ignored files are not allowed`,
14
14
  node: node,
15
15
  });
16
16
  }
@@ -3,18 +3,30 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const elements_1 = require("@boundaries/elements");
4
4
  const Messages_1 = require("../Messages");
5
5
  const Settings_1 = require("../Settings");
6
+ const Shared_1 = require("../Shared");
6
7
  const Support_1 = require("./Support");
7
- const { RULE_NO_PRIVATE } = Settings_1.SETTINGS;
8
+ const { RULE_NO_PRIVATE } = Shared_1.SETTINGS;
9
+ /**
10
+ * Builds the user-facing error message for private dependency violations.
11
+ *
12
+ * @param dependency - Described dependency that triggered the violation.
13
+ * @param options - Optional rule options with custom message template.
14
+ * @returns Final error message reported by ESLint.
15
+ */
8
16
  function errorMessage(dependency, options) {
9
17
  if (options?.message) {
10
18
  return (0, Messages_1.customErrorMessage)(options.message, dependency);
11
19
  }
12
- // @ts-expect-error could not be defined. TODO: I have to decide whether to unify properties in all elements, or to use type guards
13
- return `Dependency is private of element ${(0, Messages_1.elementMessage)(dependency.to.parents?.[0])}`;
20
+ const privateParent = dependency.to.parents?.[0];
21
+ /* istanbul ignore next - Defensive: This should not happen */
22
+ if (!privateParent) {
23
+ return `Not able to create a message for this violation. Please report this at: ${Shared_1.PLUGIN_ISSUES_URL}`;
24
+ }
25
+ return `Dependency is private of ${(0, Messages_1.elementDescriptionMessage)(privateParent, ["type", "category", "captured"], { singleElement: true })}`;
14
26
  }
15
27
  exports.default = (0, Support_1.dependencyRule)({
16
28
  ruleName: RULE_NO_PRIVATE,
17
- description: `Prevent importing private elements of another element`,
29
+ description: `Prevent dependencies to private elements`,
18
30
  schema: [
19
31
  {
20
32
  type: "object",
@@ -30,8 +42,9 @@ exports.default = (0, Support_1.dependencyRule)({
30
42
  },
31
43
  ],
32
44
  }, function ({ dependency, node, context, options }) {
45
+ (0, Settings_1.warnMigrationToDependencies)(Shared_1.RULE_NAMES_MAP.NO_PRIVATE);
33
46
  if (!dependency.to.isIgnored &&
34
- (0, elements_1.isLocalDependencyElement)(dependency.to) &&
47
+ (0, elements_1.isLocalElement)(dependency.to) &&
35
48
  dependency.to.type &&
36
49
  dependency.to.parents.length &&
37
50
  dependency.dependency.relationship.to !==
@@ -1,19 +1,19 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const elements_1 = require("@boundaries/elements");
4
- const Settings_1 = require("../Settings");
4
+ const Shared_1 = require("../Shared");
5
5
  const Support_1 = require("./Support");
6
- const { RULE_NO_UNKNOWN } = Settings_1.SETTINGS;
6
+ const { RULE_NO_UNKNOWN } = Shared_1.SETTINGS;
7
7
  exports.default = (0, Support_1.dependencyRule)({
8
8
  schema: [],
9
9
  ruleName: RULE_NO_UNKNOWN,
10
- description: `Prevent importing unknown elements from the known ones`,
10
+ description: `Prevent dependencies to unknown elements`,
11
11
  }, function ({ dependency, node, context }) {
12
12
  if (!dependency.to.isIgnored &&
13
- (0, elements_1.isLocalDependencyElement)(dependency.to) &&
13
+ (0, elements_1.isLocalElement)(dependency.to) &&
14
14
  dependency.to.isUnknown) {
15
15
  context.report({
16
- message: `Importing unknown elements is not allowed`,
16
+ message: `Dependencies to unknown elements are not allowed`,
17
17
  node: node,
18
18
  });
19
19
  }
@@ -2,13 +2,14 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const Elements_1 = require("../Elements");
4
4
  const Settings_1 = require("../Settings");
5
+ const Shared_1 = require("../Shared");
5
6
  const Support_1 = require("./Support");
6
- const { RULE_NO_UNKNOWN_FILES } = Settings_1.SETTINGS;
7
+ const { RULE_NO_UNKNOWN_FILES } = Shared_1.SETTINGS;
7
8
  const noUnknownFilesRule = {
8
9
  ...(0, Support_1.meta)({
9
10
  ruleName: RULE_NO_UNKNOWN_FILES,
10
11
  schema: [],
11
- description: `Prevent creating files not recognized as any of the element types`,
12
+ description: `Prevent creating files not recognized by any element patterns`,
12
13
  }),
13
14
  create: function (context) {
14
15
  const settings = (0, Settings_1.getSettings)(context);
@@ -19,7 +20,7 @@ const noUnknownFilesRule = {
19
20
  return {
20
21
  Program: (node) => {
21
22
  context.report({
22
- message: `File is not of any known element type`,
23
+ message: `File does not match any element pattern`,
23
24
  node: node,
24
25
  });
25
26
  },
@@ -1,4 +1,12 @@
1
1
  import type { Rule } from "eslint";
2
- import type { RuleOptionsWithRules, RuleMetaDefinition } from "../../Settings";
2
+ import type { RuleOptionsWithRules, RuleMetaDefinition } from "../../Shared";
3
3
  import type { DependencyRuleRunner, DependencyRuleOptions } from "./DependencyRule.types";
4
+ /**
5
+ * Creates a rule module that evaluates dependency nodes using shared matcher logic.
6
+ *
7
+ * @param ruleMeta - Metadata used to build ESLint rule `meta` information.
8
+ * @param rule - Rule runner invoked for each described dependency.
9
+ * @param ruleOptions - Optional behavior flags for validation and rule shape.
10
+ * @returns ESLint rule module ready to be exported by concrete rules.
11
+ */
4
12
  export declare function dependencyRule<Options extends RuleOptionsWithRules>(ruleMeta: RuleMetaDefinition, rule: DependencyRuleRunner<Options>, ruleOptions?: DependencyRuleOptions): Rule.RuleModule;
@@ -1,11 +1,20 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.dependencyRule = dependencyRule;
4
+ const Debug_1 = require("../../Debug");
4
5
  const Elements_1 = require("../../Elements");
5
6
  const Settings_1 = require("../../Settings");
6
- const Support_1 = require("../../Support");
7
+ const Shared_1 = require("../../Shared");
7
8
  const Helpers_1 = require("./Helpers");
8
- const { ADDITIONAL_DEPENDENCY_NODES } = Settings_1.SETTINGS;
9
+ const { ADDITIONAL_DEPENDENCY_NODES } = Shared_1.SETTINGS;
10
+ /**
11
+ * Creates a rule module that evaluates dependency nodes using shared matcher logic.
12
+ *
13
+ * @param ruleMeta - Metadata used to build ESLint rule `meta` information.
14
+ * @param rule - Rule runner invoked for each described dependency.
15
+ * @param ruleOptions - Optional behavior flags for validation and rule shape.
16
+ * @returns ESLint rule module ready to be exported by concrete rules.
17
+ */
9
18
  function dependencyRule(ruleMeta, rule, ruleOptions = {}) {
10
19
  return {
11
20
  ...(0, Helpers_1.meta)(ruleMeta),
@@ -16,14 +25,14 @@ function dependencyRule(ruleMeta, rule, ruleOptions = {}) {
16
25
  if (ruleOptions.validate !== false && !options) {
17
26
  return {};
18
27
  }
19
- // TODO: Remove this check when allowing to select by any other property
20
- if (file.isIgnored || !file.type) {
28
+ if (file.isIgnored || file.isUnknown) {
21
29
  return {};
22
30
  }
23
31
  return settings.dependencyNodes.reduce((visitors, { selector, kind, name }) => {
24
32
  visitors[selector] = (node) => {
25
- if (!(0, Support_1.isString)(node.value)) {
26
- (0, Support_1.warnOnce)(`Dependency node is not a Literal, skipping node. Please check your ${ADDITIONAL_DEPENDENCY_NODES} setting.`);
33
+ /* istanbul ignore next - Defensive check */
34
+ if (!(0, Shared_1.isString)(node.value)) {
35
+ (0, Debug_1.warnOnce)(`Dependency node value is not a string, skipping node.`, `Please check your ${ADDITIONAL_DEPENDENCY_NODES} setting. ${(0, Settings_1.moreInfoSettingsLink)()}`);
27
36
  return;
28
37
  }
29
38
  const dependency = (0, Elements_1.dependencyDescription)({
@@ -1,7 +1,7 @@
1
1
  import type { DependencyDescription } from "@boundaries/elements";
2
2
  import type { Rule } from "eslint";
3
3
  import type { EslintLiteralNode } from "../../Elements";
4
- import type { ValidateRulesOptions, SettingsNormalized } from "../../Settings";
4
+ import type { ValidateRulesOptions, SettingsNormalized } from "../../Shared";
5
5
  export type DependencyRuleRunner<Options> = (options: {
6
6
  dependency: DependencyDescription;
7
7
  options?: Options;
@@ -1,8 +1,12 @@
1
1
  import type { Rule } from "eslint";
2
- import type { RuleMetaDefinition } from "../../Settings";
2
+ import type { RuleMetaDefinition } from "../../Shared";
3
3
  /**
4
4
  * Returns the meta object for an ESLint rule.
5
- * @param param0 The rule metadata definition.
5
+ * @param options The rule metadata definition.
6
+ * @param options.description The description of the rule.
7
+ * @param options.schema The JSON schema for rule options validation.
8
+ * @param options.ruleName The name of the rule.
9
+ * @param options.type The type of the rule (problem, suggestion, or layout).
6
10
  * @returns The meta object for the ESLint rule.
7
11
  */
8
12
  export declare function meta({ description, schema, ruleName, type, }: RuleMetaDefinition): Pick<Rule.RuleModule, "meta">;
@@ -2,46 +2,22 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.meta = meta;
4
4
  const Settings_1 = require("../../Settings");
5
- /**
6
- * Removes the plugin namespace from a rule name.
7
- * @param ruleName The name of the rule.
8
- * @returns The rule name without the plugin namespace.
9
- */
10
- function removePluginNamespace(ruleName) {
11
- return ruleName.replace(`${Settings_1.PLUGIN_NAME}/`, "");
12
- }
13
- /**
14
- * Adapts the rule name to be used in a URL.
15
- * @param ruleName The name of the rule.
16
- * @returns The adapted rule name for URL usage.
17
- */
18
- function adaptRuleNameToUrl(ruleName) {
19
- // NOTE: Urls are already prepared for the next major release where "element-types" rule will be renamed to "dependencies", so no 301 redirect will be needed then.
20
- if (ruleName === "element-types") {
21
- return "dependencies";
22
- }
23
- return ruleName;
24
- }
25
- /**
26
- * Returns the documentation URL for an ESLint rule.
27
- * @param ruleName The name of the rule.
28
- * @returns The documentation URL for the ESLint rule.
29
- */
30
- function docsUrl(ruleName) {
31
- return `${Settings_1.WEBSITE_URL}/docs/rules/${adaptRuleNameToUrl(removePluginNamespace(ruleName))}/`;
32
- }
33
5
  /**
34
6
  * Returns the meta object for an ESLint rule.
35
- * @param param0 The rule metadata definition.
7
+ * @param options The rule metadata definition.
8
+ * @param options.description The description of the rule.
9
+ * @param options.schema The JSON schema for rule options validation.
10
+ * @param options.ruleName The name of the rule.
11
+ * @param options.type The type of the rule (problem, suggestion, or layout).
36
12
  * @returns The meta object for the ESLint rule.
37
13
  */
38
- function meta({ description, schema = [], ruleName, type, }) {
14
+ function meta({ description, schema, ruleName, type, }) {
39
15
  return {
40
16
  meta: {
41
17
  // TODO: Consider changing default to "suggestion" in a future major release, because most rules are not fixing code issues, but only suggesting best practices.
42
18
  type: type || "problem",
43
19
  docs: {
44
- url: docsUrl(ruleName),
20
+ url: (0, Settings_1.ruleDocsUrl)(ruleName),
45
21
  description,
46
22
  category: "dependencies",
47
23
  },