@boundaries/eslint-plugin 5.2.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 (67) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +798 -0
  3. package/dist/Config/Config.d.ts +40 -0
  4. package/dist/Config/Config.js +119 -0
  5. package/dist/Config/Recommended.d.ts +10 -0
  6. package/dist/Config/Recommended.js +36 -0
  7. package/dist/Config/Strict.d.ts +8 -0
  8. package/dist/Config/Strict.js +26 -0
  9. package/dist/Elements/Elements.d.ts +43 -0
  10. package/dist/Elements/Elements.js +107 -0
  11. package/dist/Elements/Elements.types.d.ts +5 -0
  12. package/dist/Elements/Elements.types.js +2 -0
  13. package/dist/Elements/index.d.ts +2 -0
  14. package/dist/Elements/index.js +18 -0
  15. package/dist/Messages/Messages.d.ts +14 -0
  16. package/dist/Messages/Messages.js +204 -0
  17. package/dist/Messages/index.d.ts +1 -0
  18. package/dist/Messages/index.js +17 -0
  19. package/dist/Public/Config.types.d.ts +2 -0
  20. package/dist/Public/Config.types.js +5 -0
  21. package/dist/Public/Rules.types.d.ts +10 -0
  22. package/dist/Public/Rules.types.js +15 -0
  23. package/dist/Public/Settings.types.d.ts +13 -0
  24. package/dist/Public/Settings.types.js +21 -0
  25. package/dist/Public/index.d.ts +3 -0
  26. package/dist/Public/index.js +19 -0
  27. package/dist/Rules/ElementTypes.d.ts +25 -0
  28. package/dist/Rules/ElementTypes.js +269 -0
  29. package/dist/Rules/EntryPoint.d.ts +2 -0
  30. package/dist/Rules/EntryPoint.js +122 -0
  31. package/dist/Rules/External.d.ts +2 -0
  32. package/dist/Rules/External.js +119 -0
  33. package/dist/Rules/NoIgnored.d.ts +2 -0
  34. package/dist/Rules/NoIgnored.js +19 -0
  35. package/dist/Rules/NoPrivate.d.ts +2 -0
  36. package/dist/Rules/NoPrivate.js +53 -0
  37. package/dist/Rules/NoUnknown.d.ts +2 -0
  38. package/dist/Rules/NoUnknown.js +22 -0
  39. package/dist/Rules/NoUnknownFiles.d.ts +3 -0
  40. package/dist/Rules/NoUnknownFiles.js +29 -0
  41. package/dist/Rules/Support/DependencyRule.d.ts +4 -0
  42. package/dist/Rules/Support/DependencyRule.js +49 -0
  43. package/dist/Rules/Support/DependencyRule.types.d.ts +17 -0
  44. package/dist/Rules/Support/DependencyRule.types.js +2 -0
  45. package/dist/Rules/Support/Helpers.d.ts +8 -0
  46. package/dist/Rules/Support/Helpers.js +39 -0
  47. package/dist/Rules/Support/index.d.ts +3 -0
  48. package/dist/Rules/Support/index.js +19 -0
  49. package/dist/Settings/Helpers.d.ts +41 -0
  50. package/dist/Settings/Helpers.js +72 -0
  51. package/dist/Settings/Settings.d.ts +6 -0
  52. package/dist/Settings/Settings.js +49 -0
  53. package/dist/Settings/Settings.types.d.ts +448 -0
  54. package/dist/Settings/Settings.types.js +190 -0
  55. package/dist/Settings/Validations.d.ts +137 -0
  56. package/dist/Settings/Validations.js +359 -0
  57. package/dist/Settings/index.d.ts +4 -0
  58. package/dist/Settings/index.js +20 -0
  59. package/dist/Support/Common.d.ts +30 -0
  60. package/dist/Support/Common.js +47 -0
  61. package/dist/Support/Debug.d.ts +5 -0
  62. package/dist/Support/Debug.js +54 -0
  63. package/dist/Support/index.d.ts +2 -0
  64. package/dist/Support/index.js +18 -0
  65. package/dist/index.d.ts +8 -0
  66. package/dist/index.js +76 -0
  67. package/package.json +81 -0
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./Messages"), exports);
@@ -0,0 +1,2 @@
1
+ export type { Rules, Config, PluginBoundaries } from "../Settings";
2
+ export { PLUGIN_NAME } from "../Settings";
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PLUGIN_NAME = void 0;
4
+ var Settings_1 = require("../Settings");
5
+ Object.defineProperty(exports, "PLUGIN_NAME", { enumerable: true, get: function () { return Settings_1.PLUGIN_NAME; } });
@@ -0,0 +1,10 @@
1
+ import type { DependencyKind } from "@boundaries/elements";
2
+ export type { DependencyKind, CapturedValuesSelector, ElementSelector, ElementSelectors, ElementsSelector, ExternalLibrarySelectorOptions, ExternalLibrarySelectorWithOptions, ExternalLibrarySelector, ExternalLibrarySelectors, ExternalLibrariesSelector, ElementSelectorWithOptions, } from "@boundaries/elements";
3
+ export { isElementSelector, isElementsSelector, isExternalLibrarySelector, isExternalLibrariesSelector, } from "@boundaries/elements";
4
+ export type { RulePolicy, RuleBaseOptions, ElementTypesRule, ElementTypesRuleOptions, EntryPointRule, EntryPointRuleOptions, ExternalRule, ExternalRuleOptions, NoPrivateOptions, RuleShortName, RuleName, } from "../Settings";
5
+ export { RULE_POLICIES_MAP, isRulePolicy, RULE_SHORT_NAMES_MAP, RULE_NAMES_MAP, isRuleShortName, isRuleName, } from "../Settings";
6
+ /**
7
+ * Kind of import that the rule applies to (e.g., "type", "value")
8
+ * @deprecated Use DependencyKind instead
9
+ */
10
+ export type ImportKind = DependencyKind;
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isRuleName = exports.isRuleShortName = exports.RULE_NAMES_MAP = exports.RULE_SHORT_NAMES_MAP = exports.isRulePolicy = exports.RULE_POLICIES_MAP = exports.isExternalLibrariesSelector = exports.isExternalLibrarySelector = exports.isElementsSelector = exports.isElementSelector = void 0;
4
+ var elements_1 = require("@boundaries/elements");
5
+ Object.defineProperty(exports, "isElementSelector", { enumerable: true, get: function () { return elements_1.isElementSelector; } });
6
+ Object.defineProperty(exports, "isElementsSelector", { enumerable: true, get: function () { return elements_1.isElementsSelector; } });
7
+ Object.defineProperty(exports, "isExternalLibrarySelector", { enumerable: true, get: function () { return elements_1.isExternalLibrarySelector; } });
8
+ Object.defineProperty(exports, "isExternalLibrariesSelector", { enumerable: true, get: function () { return elements_1.isExternalLibrariesSelector; } });
9
+ var Settings_1 = require("../Settings");
10
+ Object.defineProperty(exports, "RULE_POLICIES_MAP", { enumerable: true, get: function () { return Settings_1.RULE_POLICIES_MAP; } });
11
+ Object.defineProperty(exports, "isRulePolicy", { enumerable: true, get: function () { return Settings_1.isRulePolicy; } });
12
+ Object.defineProperty(exports, "RULE_SHORT_NAMES_MAP", { enumerable: true, get: function () { return Settings_1.RULE_SHORT_NAMES_MAP; } });
13
+ Object.defineProperty(exports, "RULE_NAMES_MAP", { enumerable: true, get: function () { return Settings_1.RULE_NAMES_MAP; } });
14
+ Object.defineProperty(exports, "isRuleShortName", { enumerable: true, get: function () { return Settings_1.isRuleShortName; } });
15
+ Object.defineProperty(exports, "isRuleName", { enumerable: true, get: function () { return Settings_1.isRuleName; } });
@@ -0,0 +1,13 @@
1
+ export { DEPENDENCY_KINDS_MAP, isDependencyKind } from "@boundaries/elements";
2
+ export type { ElementDescriptorMode, ElementDescriptor, ElementDescriptors, } from "@boundaries/elements";
3
+ export { ELEMENT_DESCRIPTOR_MODES_MAP, isElementDescriptorMode, } from "@boundaries/elements";
4
+ export type { Settings, IgnoreSetting, IncludeSetting, RootPathSetting, SettingsKey, DependencyNodeKey, DependencyNodeSelector, AliasSetting, } from "../Settings";
5
+ /**
6
+ * Map of the kinds of import, either a type import or a value import.
7
+ * @deprecated Use DEPENDENCY_KINDS_MAP instead
8
+ */
9
+ export declare const IMPORT_KINDS_MAP: {
10
+ readonly TYPE: "type";
11
+ readonly VALUE: "value";
12
+ };
13
+ export { isImportKind, DEPENDENCY_NODE_KEYS_MAP, isDependencyNodeKey, SETTINGS_KEYS_MAP, isSettingsKey, } from "../Settings";
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isSettingsKey = exports.SETTINGS_KEYS_MAP = exports.isDependencyNodeKey = exports.DEPENDENCY_NODE_KEYS_MAP = exports.isImportKind = exports.IMPORT_KINDS_MAP = exports.isElementDescriptorMode = exports.ELEMENT_DESCRIPTOR_MODES_MAP = exports.isDependencyKind = exports.DEPENDENCY_KINDS_MAP = void 0;
4
+ var elements_1 = require("@boundaries/elements");
5
+ Object.defineProperty(exports, "DEPENDENCY_KINDS_MAP", { enumerable: true, get: function () { return elements_1.DEPENDENCY_KINDS_MAP; } });
6
+ Object.defineProperty(exports, "isDependencyKind", { enumerable: true, get: function () { return elements_1.isDependencyKind; } });
7
+ const elements_2 = require("@boundaries/elements");
8
+ var elements_3 = require("@boundaries/elements");
9
+ Object.defineProperty(exports, "ELEMENT_DESCRIPTOR_MODES_MAP", { enumerable: true, get: function () { return elements_3.ELEMENT_DESCRIPTOR_MODES_MAP; } });
10
+ Object.defineProperty(exports, "isElementDescriptorMode", { enumerable: true, get: function () { return elements_3.isElementDescriptorMode; } });
11
+ /**
12
+ * Map of the kinds of import, either a type import or a value import.
13
+ * @deprecated Use DEPENDENCY_KINDS_MAP instead
14
+ */
15
+ exports.IMPORT_KINDS_MAP = elements_2.DEPENDENCY_KINDS_MAP;
16
+ var Settings_1 = require("../Settings");
17
+ Object.defineProperty(exports, "isImportKind", { enumerable: true, get: function () { return Settings_1.isImportKind; } });
18
+ Object.defineProperty(exports, "DEPENDENCY_NODE_KEYS_MAP", { enumerable: true, get: function () { return Settings_1.DEPENDENCY_NODE_KEYS_MAP; } });
19
+ Object.defineProperty(exports, "isDependencyNodeKey", { enumerable: true, get: function () { return Settings_1.isDependencyNodeKey; } });
20
+ Object.defineProperty(exports, "SETTINGS_KEYS_MAP", { enumerable: true, get: function () { return Settings_1.SETTINGS_KEYS_MAP; } });
21
+ Object.defineProperty(exports, "isSettingsKey", { enumerable: true, get: function () { return Settings_1.isSettingsKey; } });
@@ -0,0 +1,3 @@
1
+ export * from "./Config.types";
2
+ export * from "./Settings.types";
3
+ export * from "./Rules.types";
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./Config.types"), exports);
18
+ __exportStar(require("./Settings.types"), exports);
19
+ __exportStar(require("./Rules.types"), exports);
@@ -0,0 +1,25 @@
1
+ import type { DependencyDescription, Matcher } from "@boundaries/elements";
2
+ import type { ElementTypesRuleOptions, RuleResult, SettingsNormalized } from "../Settings";
3
+ type PolicyMatch = {
4
+ isMatch: boolean;
5
+ specifiers?: string | string[];
6
+ internalPath?: string;
7
+ };
8
+ export declare function getRulesResults(ruleOptions: ElementTypesRuleOptions, dependencyDescription: DependencyDescription, matcher: Matcher, settings: SettingsNormalized): {
9
+ index: number;
10
+ originalRuleIndex: any;
11
+ selectorsMatching: {
12
+ selectors: {
13
+ [x: string]: string | import("@boundaries/elements").BaseElementSelectorData | import("@boundaries/elements").BaseElementSelectorWithOptions | import("@boundaries/elements").BaseElementSelector[] | null;
14
+ };
15
+ selectorsData: {
16
+ isMatch: boolean;
17
+ } | null;
18
+ };
19
+ ruleHasImportKind: boolean;
20
+ allowPolicyMatches: PolicyMatch;
21
+ denyPolicyMatches: PolicyMatch;
22
+ }[];
23
+ export declare function elementRulesAllowDependency(dependency: DependencyDescription, settings: SettingsNormalized, ruleOptions?: ElementTypesRuleOptions): RuleResult;
24
+ declare const _default: import("eslint").Rule.RuleModule;
25
+ export default _default;
@@ -0,0 +1,269 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.getRulesResults = getRulesResults;
7
+ exports.elementRulesAllowDependency = elementRulesAllowDependency;
8
+ const elements_1 = require("@boundaries/elements");
9
+ const micromatch_1 = __importDefault(require("micromatch"));
10
+ const Elements_1 = require("../Elements");
11
+ const Messages_1 = require("../Messages");
12
+ const Settings_1 = require("../Settings");
13
+ const Support_1 = require("../Support");
14
+ const Support_2 = require("./Support");
15
+ const { RULE_ELEMENT_TYPES } = Settings_1.SETTINGS;
16
+ /**
17
+ * Safely matches a dependency selector, catching and logging any errors
18
+ */
19
+ function createSafeMatcherFunction(dependencyDescription, matcher) {
20
+ return (dependencySelector, extraTemplateData, dependencySelectorsGlobals) => {
21
+ // Just in case selectors are invalid, we catch errors here to avoid breaking the whole rule evaluation
22
+ try {
23
+ return matcher.getSelectorMatchingDescription(dependencyDescription, dependencySelector, {
24
+ extraTemplateData,
25
+ dependencySelectorsGlobals,
26
+ });
27
+ }
28
+ catch (error) {
29
+ (0, Support_1.warnOnce)(`Error occurred while matching dependency: ${String(error)}`);
30
+ return { isMatch: false };
31
+ }
32
+ };
33
+ }
34
+ /**
35
+ * Determines the rule matching context (directions, template data, etc.)
36
+ */
37
+ function createRuleMatchContext(rule, dependencyDescription) {
38
+ const targetElementDirection = rule.from ? "from" : "to";
39
+ const policyElementDirection = rule.from ? "to" : "from";
40
+ const denyKeyToUse = rule.deny ? "deny" : "disallow";
41
+ const capturedValuesTemplateData = targetElementDirection === "from"
42
+ ? {
43
+ ...dependencyDescription.from.captured,
44
+ from: dependencyDescription.from.captured,
45
+ to: dependencyDescription.to.captured,
46
+ }
47
+ : {
48
+ ...dependencyDescription.to.captured,
49
+ from: dependencyDescription.from.captured,
50
+ to: dependencyDescription.to.captured,
51
+ };
52
+ const dependencySelectorsGlobals = rule.importKind ? { kind: rule.importKind } : {};
53
+ const targetElementSelector = rule[targetElementDirection];
54
+ return {
55
+ targetElementDirection,
56
+ policyElementDirection,
57
+ denyKeyToUse,
58
+ capturedValuesTemplateData,
59
+ dependencySelectorsGlobals,
60
+ targetElementSelector,
61
+ };
62
+ }
63
+ /**
64
+ * Evaluates both deny and allow policy matches for a rule
65
+ */
66
+ function evaluatePolicyMatches(rule, context, isMatch, settings) {
67
+ const { targetElementDirection, policyElementDirection, denyKeyToUse, capturedValuesTemplateData, dependencySelectorsGlobals, targetElementSelector, } = context;
68
+ const disallowPolicyMatches = rule[denyKeyToUse]
69
+ ? isMatch({
70
+ [targetElementDirection]: targetElementSelector,
71
+ [policyElementDirection]: rule[denyKeyToUse],
72
+ }, settings.legacyTemplates ? capturedValuesTemplateData : {}, dependencySelectorsGlobals)
73
+ : { isMatch: false };
74
+ const allowPolicyMatches = !disallowPolicyMatches.isMatch && rule.allow
75
+ ? isMatch({
76
+ [targetElementDirection]: targetElementSelector,
77
+ [policyElementDirection]: rule.allow,
78
+ }, settings.legacyTemplates ? capturedValuesTemplateData : {}, dependencySelectorsGlobals)
79
+ : { isMatch: false };
80
+ return { disallowPolicyMatches, allowPolicyMatches };
81
+ }
82
+ /**
83
+ * Creates rule selectors data based on policy matches
84
+ */
85
+ function createRuleSelectorsData(rule, context, disallowPolicyMatches, allowPolicyMatches) {
86
+ const { targetElementDirection, policyElementDirection, denyKeyToUse } = context;
87
+ const allowPolicyMatchesIsMatch = allowPolicyMatches.isMatch;
88
+ const disallowPolicyMatchesIsMatch = disallowPolicyMatches.isMatch;
89
+ const targetSelector = disallowPolicyMatchesIsMatch || allowPolicyMatchesIsMatch
90
+ ? context.targetElementSelector
91
+ : null;
92
+ let policySelector = null;
93
+ if (disallowPolicyMatchesIsMatch) {
94
+ policySelector = rule[denyKeyToUse];
95
+ }
96
+ else if (allowPolicyMatchesIsMatch) {
97
+ policySelector = rule.allow;
98
+ }
99
+ let selectorsData = null;
100
+ if (disallowPolicyMatchesIsMatch) {
101
+ selectorsData = disallowPolicyMatches;
102
+ }
103
+ else if (allowPolicyMatchesIsMatch) {
104
+ selectorsData = allowPolicyMatches;
105
+ }
106
+ return {
107
+ selectors: {
108
+ [targetElementDirection]: targetSelector,
109
+ [policyElementDirection]: policySelector,
110
+ },
111
+ selectorsData,
112
+ };
113
+ }
114
+ function getRulesResults(ruleOptions, dependencyDescription, matcher, settings) {
115
+ if (!ruleOptions.rules) {
116
+ return [];
117
+ }
118
+ const isMatch = createSafeMatcherFunction(dependencyDescription, matcher);
119
+ return ruleOptions.rules.map((rule, index) => {
120
+ const context = createRuleMatchContext(rule, dependencyDescription);
121
+ const { disallowPolicyMatches, allowPolicyMatches } = evaluatePolicyMatches(rule, context, isMatch, settings);
122
+ const selectorsMatching = createRuleSelectorsData(rule, context, disallowPolicyMatches, allowPolicyMatches);
123
+ return {
124
+ index,
125
+ // @ts-expect-error Workaround to support both allow and disallow in the same entry point rule
126
+ originalRuleIndex: rule.originalRuleIndex,
127
+ selectorsMatching,
128
+ ruleHasImportKind: !!rule.importKind,
129
+ allowPolicyMatches,
130
+ denyPolicyMatches: disallowPolicyMatches,
131
+ };
132
+ });
133
+ }
134
+ /**
135
+ * Determines the rule result based on policy matches
136
+ */
137
+ function determineRuleResult(rulesResults) {
138
+ let isAllowed = false;
139
+ let ruleIndexMatching = null;
140
+ for (const ruleResult of rulesResults) {
141
+ if (ruleResult.denyPolicyMatches.isMatch) {
142
+ isAllowed = false;
143
+ ruleIndexMatching = ruleResult.index;
144
+ }
145
+ else if (ruleResult.allowPolicyMatches.isMatch) {
146
+ isAllowed = true;
147
+ ruleIndexMatching = ruleResult.index;
148
+ }
149
+ }
150
+ return { isAllowed, ruleIndexMatching };
151
+ }
152
+ /**
153
+ * Gets the message for the rule, prioritizing rule-specific messages
154
+ */
155
+ function getRuleMessage(ruleIndexMatching, ruleOptions) {
156
+ return ((ruleIndexMatching === null
157
+ ? ruleOptions.message
158
+ : ruleOptions.rules?.[ruleIndexMatching]?.message) || ruleOptions.message);
159
+ }
160
+ /**
161
+ * Gets specifiers that match the rule for error reporting
162
+ */
163
+ function getMatchingSpecifiers(ruleIndexMatching, rulesResults, dependency) {
164
+ if (ruleIndexMatching === null)
165
+ return null;
166
+ const selectorDataSpecifiers =
167
+ // @ts-expect-error TODO: Align types. At this point, selectorsData.to must always be defined, because otherwise isMatch would be false
168
+ rulesResults[ruleIndexMatching].selectorsMatching?.selectorsData?.to
169
+ ?.specifiers;
170
+ if (!selectorDataSpecifiers) {
171
+ return null;
172
+ }
173
+ if ((0, Support_1.isString)(selectorDataSpecifiers)) {
174
+ const hasMatchingSpecifier = dependency.dependency.specifiers?.some((specifier) => micromatch_1.default.isMatch(specifier, selectorDataSpecifiers));
175
+ return hasMatchingSpecifier ? [selectorDataSpecifiers] : null;
176
+ }
177
+ return selectorDataSpecifiers.filter((pattern) => {
178
+ return dependency.dependency.specifiers?.some((specifier) => micromatch_1.default.isMatch(specifier, pattern));
179
+ });
180
+ }
181
+ /**
182
+ * Creates the rule report object
183
+ */
184
+ function createRuleReport(ruleIndexMatching, message, dependency, rulesResults) {
185
+ if (ruleIndexMatching === null) {
186
+ return {
187
+ message,
188
+ isDefault: true,
189
+ importKind: undefined,
190
+ disallow: dependency.to,
191
+ element: dependency.from,
192
+ index: -1,
193
+ };
194
+ }
195
+ return {
196
+ message,
197
+ isDefault: false,
198
+ importKind: rulesResults[ruleIndexMatching].ruleHasImportKind
199
+ ? dependency.dependency.kind
200
+ : undefined,
201
+ disallow: rulesResults[ruleIndexMatching].selectorsMatching?.selectors.to,
202
+ element: rulesResults[ruleIndexMatching].selectorsMatching?.selectors.from,
203
+ index: rulesResults[ruleIndexMatching].originalRuleIndex ?? ruleIndexMatching,
204
+ };
205
+ }
206
+ /**
207
+ * Determines the report path for error reporting
208
+ */
209
+ function getReportPath(ruleIndexMatching, rulesResults, dependency) {
210
+ return ruleIndexMatching === null ||
211
+ // @ts-expect-error TODO: Align types. At this point, selectorsData should always be defined
212
+ !rulesResults[ruleIndexMatching].selectorsMatching?.selectorsData?.to
213
+ ?.internalPath
214
+ ? null
215
+ : dependency.to.internalPath;
216
+ }
217
+ function elementRulesAllowDependency(dependency, settings, ruleOptions = {}) {
218
+ const defaultIsAllowed = ruleOptions.default === "allow";
219
+ const matcher = (0, Elements_1.getElementsMatcher)(settings);
220
+ const rulesResults = getRulesResults(ruleOptions, dependency, matcher, settings);
221
+ const { isAllowed, ruleIndexMatching } = determineRuleResult(rulesResults);
222
+ const finalIsAllowed = ruleIndexMatching === null ? defaultIsAllowed : isAllowed;
223
+ const message = getRuleMessage(ruleIndexMatching, ruleOptions);
224
+ const ruleReport = createRuleReport(ruleIndexMatching, message, dependency, rulesResults);
225
+ const reportPath = getReportPath(ruleIndexMatching, rulesResults, dependency);
226
+ const result = {
227
+ result: finalIsAllowed,
228
+ // @ts-expect-error Temporary workaround for RuleResult type until types are aligned
229
+ ruleReport,
230
+ report: {
231
+ specifiers: getMatchingSpecifiers(ruleIndexMatching, rulesResults, dependency) ||
232
+ undefined,
233
+ path: reportPath,
234
+ },
235
+ };
236
+ return result;
237
+ }
238
+ function errorMessage(ruleData, dependency) {
239
+ const ruleReport = ruleData.ruleReport;
240
+ if (!ruleReport) {
241
+ 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}`;
242
+ }
243
+ if (ruleReport.message) {
244
+ return (0, Messages_1.customErrorMessage)(ruleReport.message, dependency);
245
+ }
246
+ if (ruleReport.isDefault) {
247
+ return `No rule allowing this dependency was found. File is ${(0, Messages_1.elementMessage)(dependency.from)}. Dependency is ${(0, Messages_1.elementMessage)(dependency.to)}`;
248
+ }
249
+ return `Importing ${(0, Messages_1.dependencyImportKindMessage)(ruleReport.importKind, dependency)}${(0, Messages_1.ruleElementMessage)(ruleReport.disallow, dependency.from.captured)} is not allowed in ${(0, Messages_1.ruleElementMessage)(ruleReport.element, dependency.from.captured)}. Disallowed in rule ${ruleReport.index + 1}`;
250
+ }
251
+ exports.default = (0, Support_2.dependencyRule)({
252
+ ruleName: RULE_ELEMENT_TYPES,
253
+ description: `Check allowed dependencies between element types`,
254
+ schema: (0, Settings_1.rulesOptionsSchema)(),
255
+ }, function ({ dependency, node, context, settings, options }) {
256
+ // TODO: Remove these checks when allowing to use more selectors in ESLint rules
257
+ if ((0, elements_1.isLocalElement)(dependency.to) &&
258
+ !(0, elements_1.isIgnoredElement)(dependency.to) &&
259
+ !(0, elements_1.isUnknownLocalElement)(dependency.to) &&
260
+ !(0, elements_1.isInternalDependency)(dependency)) {
261
+ const ruleData = elementRulesAllowDependency(dependency, settings, options);
262
+ if (!ruleData.result) {
263
+ context.report({
264
+ message: errorMessage(ruleData, dependency),
265
+ node,
266
+ });
267
+ }
268
+ }
269
+ });
@@ -0,0 +1,2 @@
1
+ declare const _default: import("eslint").Rule.RuleModule;
2
+ export default _default;
@@ -0,0 +1,122 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const elements_1 = require("@boundaries/elements");
4
+ const Messages_1 = require("../Messages");
5
+ const Settings_1 = require("../Settings");
6
+ const ElementTypes_1 = require("./ElementTypes");
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
+ }
29
+ const templatesArray = Array.isArray(templates) ? templates : [templates];
30
+ return templatesArray.map((template) => template.replaceAll("${target.", "${to."));
31
+ }
32
+ function modifyRules(rules) {
33
+ const newRules = [];
34
+ for (let i = 0; i < rules.length; i++) {
35
+ const rule = rules[i];
36
+ 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 = ["*"];
79
+ }
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
+ }
95
+ return newRules;
96
+ }
97
+ exports.default = (0, Support_1.dependencyRule)({
98
+ ruleName: RULE_ENTRY_POINT,
99
+ description: `Check entry point used for each element type`,
100
+ schema: (0, Settings_1.rulesOptionsSchema)({
101
+ rulesMainKey: "target",
102
+ }),
103
+ }, function ({ dependency, node, context, settings, options }) {
104
+ if (!dependency.to.isIgnored &&
105
+ dependency.to.type &&
106
+ dependency.dependency.relationship.to !==
107
+ 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
+ }
119
+ }
120
+ }, {
121
+ validateRules: { onlyMainKey: true, mainKey: "target" },
122
+ });
@@ -0,0 +1,2 @@
1
+ declare const _default: import("eslint").Rule.RuleModule;
2
+ export default _default;
@@ -0,0 +1,119 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const elements_1 = require("@boundaries/elements");
4
+ const Messages_1 = require("../Messages");
5
+ 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;
17
+ }
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}`;
42
+ }
43
+ function modifySelectors(selectors) {
44
+ const originsToMatch = [
45
+ elements_1.ELEMENT_ORIGINS_MAP.EXTERNAL,
46
+ elements_1.ELEMENT_ORIGINS_MAP.CORE,
47
+ ];
48
+ if ((0, Support_1.isString)(selectors)) {
49
+ return [{ baseSource: selectors, origin: originsToMatch }];
50
+ }
51
+ return selectors.map((selector) => {
52
+ if ((0, Support_1.isArray)(selector)) {
53
+ return {
54
+ origin: originsToMatch,
55
+ baseSource: selector[0],
56
+ specifiers: selector[1].specifiers,
57
+ internalPath: selector[1].path,
58
+ };
59
+ }
60
+ return {
61
+ origin: originsToMatch,
62
+ baseSource: selector,
63
+ };
64
+ });
65
+ }
66
+ exports.default = (0, Support_2.dependencyRule)({
67
+ ruleName: RULE_EXTERNAL,
68
+ description: `Check allowed external dependencies by element type`,
69
+ schema: (0, Settings_1.rulesOptionsSchema)({
70
+ targetMatcherOptions: {
71
+ type: "object",
72
+ properties: {
73
+ specifiers: {
74
+ type: "array",
75
+ items: {
76
+ type: "string",
77
+ },
78
+ },
79
+ path: {
80
+ oneOf: [
81
+ {
82
+ type: "string",
83
+ },
84
+ {
85
+ type: "array",
86
+ items: {
87
+ type: "string",
88
+ },
89
+ },
90
+ ],
91
+ },
92
+ },
93
+ additionalProperties: false,
94
+ },
95
+ }),
96
+ }, function ({ dependency, node, context, settings, options }) {
97
+ if ((0, elements_1.isExternalDependencyElement)(dependency.to) ||
98
+ (0, elements_1.isCoreDependencyElement)(dependency.to)) {
99
+ const adaptedRuleOptions = {
100
+ ...options,
101
+ rules: options && options.rules
102
+ ? options.rules.map((rule) => ({
103
+ ...rule,
104
+ allow: rule.allow && modifySelectors(rule.allow),
105
+ disallow: rule.disallow && modifySelectors(rule.disallow),
106
+ }))
107
+ : [],
108
+ };
109
+ const ruleData = (0, ElementTypes_1.elementRulesAllowDependency)(dependency, settings, adaptedRuleOptions);
110
+ if (!ruleData.result) {
111
+ context.report({
112
+ message: errorMessage(ruleData, dependency),
113
+ node: node,
114
+ });
115
+ }
116
+ }
117
+ }, {
118
+ validateRules: { onlyMainKey: true },
119
+ });
@@ -0,0 +1,2 @@
1
+ declare const _default: import("eslint").Rule.RuleModule;
2
+ export default _default;