@boundaries/eslint-plugin 5.2.0-beta.1 → 5.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -320,6 +320,18 @@ You can also provide an absolute path in the environment variable, but it may be
320
320
 
321
321
  </details>
322
322
 
323
+ #### __`boundaries/cache`__
324
+
325
+ Enable or disable the cache mechanism used to boost performance. By default, it is enabled. We recommend to keep it enabled unless you experience issues. In such case, please, open an issue describing the problem.
326
+
327
+ ```js
328
+ export default [{
329
+ settings: {
330
+ "boundaries/cache": true // or false to disable the cache
331
+ }
332
+ }]
333
+ ```
334
+
323
335
  ### Predefined configurations
324
336
 
325
337
  The plugin is distributed with two different predefined configurations: "recommended" and "strict".
@@ -21,6 +21,7 @@ function getElementsMatcher(settings) {
21
21
  ignorePaths: settings.ignorePaths,
22
22
  includePaths: settings.includePaths,
23
23
  legacyTemplates: settings.legacyTemplates,
24
+ cache: settings.cache,
24
25
  });
25
26
  return elementsMatcher;
26
27
  }
@@ -26,8 +26,8 @@ function createSafeMatcherFunction(dependencyDescription, matcher) {
26
26
  });
27
27
  }
28
28
  catch (error) {
29
- (0, Support_1.warnOnce)(`Error occurred while matching dependency: ${String(error)}`);
30
- return { isMatch: false };
29
+ (0, Support_1.warnOnce)(`Error occurred while matching dependency with selector ${JSON.stringify(dependencySelector)}: ${String(error)}`);
30
+ return { isMatch: false, from: null, to: null };
31
31
  }
32
32
  };
33
33
  }
@@ -65,17 +65,20 @@ function createRuleMatchContext(rule, dependencyDescription) {
65
65
  */
66
66
  function evaluatePolicyMatches(rule, context, isMatch, settings) {
67
67
  const { targetElementDirection, policyElementDirection, denyKeyToUse, capturedValuesTemplateData, dependencySelectorsGlobals, targetElementSelector, } = context;
68
+ const templateData = settings.legacyTemplates
69
+ ? capturedValuesTemplateData
70
+ : {};
68
71
  const disallowPolicyMatches = rule[denyKeyToUse]
69
72
  ? isMatch({
70
73
  [targetElementDirection]: targetElementSelector,
71
74
  [policyElementDirection]: rule[denyKeyToUse],
72
- }, settings.legacyTemplates ? capturedValuesTemplateData : {}, dependencySelectorsGlobals)
75
+ }, templateData, dependencySelectorsGlobals)
73
76
  : { isMatch: false };
74
77
  const allowPolicyMatches = !disallowPolicyMatches.isMatch && rule.allow
75
78
  ? isMatch({
76
79
  [targetElementDirection]: targetElementSelector,
77
80
  [policyElementDirection]: rule.allow,
78
- }, settings.legacyTemplates ? capturedValuesTemplateData : {}, dependencySelectorsGlobals)
81
+ }, templateData, dependencySelectorsGlobals)
79
82
  : { isMatch: false };
80
83
  return { disallowPolicyMatches, allowPolicyMatches };
81
84
  }
@@ -220,6 +223,13 @@ function elementRulesAllowDependency(dependency, settings, ruleOptions = {}) {
220
223
  const rulesResults = getRulesResults(ruleOptions, dependency, matcher, settings);
221
224
  const { isAllowed, ruleIndexMatching } = determineRuleResult(rulesResults);
222
225
  const finalIsAllowed = ruleIndexMatching === null ? defaultIsAllowed : isAllowed;
226
+ if (finalIsAllowed) {
227
+ return {
228
+ result: finalIsAllowed,
229
+ ruleReport: null,
230
+ report: null,
231
+ };
232
+ }
223
233
  const message = getRuleMessage(ruleIndexMatching, ruleOptions);
224
234
  const ruleReport = createRuleReport(ruleIndexMatching, message, dependency, rulesResults);
225
235
  const reportPath = getReportPath(ruleIndexMatching, rulesResults, dependency);
@@ -98,6 +98,7 @@ exports.default = (0, Support_2.dependencyRule)({
98
98
  (0, elements_1.isCoreDependencyElement)(dependency.to)) {
99
99
  const adaptedRuleOptions = {
100
100
  ...options,
101
+ // @ts-expect-error TODO: Fix type
101
102
  rules: options && options.rules
102
103
  ? options.rules.map((rule) => ({
103
104
  ...rule,
@@ -114,6 +114,7 @@ export declare const SETTINGS: {
114
114
  readonly DEPENDENCY_NODES: "boundaries/dependency-nodes";
115
115
  readonly ADDITIONAL_DEPENDENCY_NODES: "boundaries/additional-dependency-nodes";
116
116
  readonly LEGACY_TEMPLATES: "boundaries/legacy-templates";
117
+ readonly CACHE: "boundaries/cache";
117
118
  readonly DEBUG: "ESLINT_PLUGIN_BOUNDARIES_DEBUG";
118
119
  readonly ENV_ROOT_PATH: "ESLINT_PLUGIN_BOUNDARIES_ROOT_PATH";
119
120
  readonly RULE_ELEMENT_TYPES: "boundaries/element-types";
@@ -173,11 +174,16 @@ export declare const SETTINGS_KEYS_MAP: {
173
174
  readonly TYPES: "boundaries/types";
174
175
  /** @deprecated Use import/resolver settings instead */
175
176
  readonly ALIAS: "boundaries/alias";
177
+ readonly CACHE: "boundaries/cache";
176
178
  };
177
179
  /**
178
180
  * Default value for the legacy templates setting.
179
181
  */
180
182
  export declare const LEGACY_TEMPLATES_DEFAULT: true;
183
+ /**
184
+ * Default value for the cache setting.
185
+ */
186
+ export declare const CACHE_DEFAULT: true;
181
187
  /**
182
188
  * Valid keys for the plugin settings.
183
189
  */
@@ -250,6 +256,8 @@ export type Settings = {
250
256
  [SETTINGS_KEYS_MAP.TYPES]?: ElementDescriptors;
251
257
  /** @deprecated Use "import/resolver" setting instead */
252
258
  [SETTINGS_KEYS_MAP.ALIAS]?: AliasSetting;
259
+ /** Whether to enable caching for the plugin analysis */
260
+ [SETTINGS_KEYS_MAP.CACHE]?: boolean;
253
261
  };
254
262
  /**
255
263
  * Normalized settings for the eslint-plugin-boundaries plugin.
@@ -270,6 +278,8 @@ export type SettingsNormalized = {
270
278
  dependencyNodes: DependencyNodeSelector[];
271
279
  /** Whether legacy template syntax support is enabled */
272
280
  legacyTemplates: boolean;
281
+ /** Whether caching is enabled */
282
+ cache: boolean;
273
283
  };
274
284
  /**
275
285
  * Eslint boundaries plugin rules.
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.RULE_POLICIES_MAP = exports.RULE_POLICY_DISALLOW = exports.RULE_POLICY_ALLOW = exports.LEGACY_TEMPLATES_DEFAULT = exports.SETTINGS_KEYS_MAP = exports.SETTINGS = exports.DEPENDENCY_NODE_KEYS_MAP = exports.FROM = exports.RULE_SHORT_NAMES = exports.RULE_NAMES = exports.RULE_NAMES_MAP = exports.RULE_SHORT_NAMES_MAP = exports.NO_UNKNOWN = exports.NO_UNKNOWN_FILES = exports.NO_PRIVATE = exports.NO_IGNORED = exports.EXTERNAL = exports.ENTRY_POINT = exports.ELEMENT_TYPES = exports.DEPENDENCY_NODE_EXPORT = exports.DEPENDENCY_NODE_DYNAMIC_IMPORT = exports.DEPENDENCY_NODE_IMPORT = exports.DEPENDENCY_NODE_REQUIRE = exports.PLUGIN_ISSUES_URL = exports.REPO_URL = exports.PLUGIN_ENV_VARS_PREFIX = exports.PLUGIN_NAME = void 0;
3
+ exports.RULE_POLICIES_MAP = exports.RULE_POLICY_DISALLOW = exports.RULE_POLICY_ALLOW = exports.CACHE_DEFAULT = exports.LEGACY_TEMPLATES_DEFAULT = exports.SETTINGS_KEYS_MAP = exports.SETTINGS = exports.DEPENDENCY_NODE_KEYS_MAP = exports.FROM = exports.RULE_SHORT_NAMES = exports.RULE_NAMES = exports.RULE_NAMES_MAP = exports.RULE_SHORT_NAMES_MAP = exports.NO_UNKNOWN = exports.NO_UNKNOWN_FILES = exports.NO_PRIVATE = exports.NO_IGNORED = exports.EXTERNAL = exports.ENTRY_POINT = exports.ELEMENT_TYPES = exports.DEPENDENCY_NODE_EXPORT = exports.DEPENDENCY_NODE_DYNAMIC_IMPORT = exports.DEPENDENCY_NODE_IMPORT = exports.DEPENDENCY_NODE_REQUIRE = exports.PLUGIN_ISSUES_URL = exports.REPO_URL = exports.PLUGIN_ENV_VARS_PREFIX = exports.PLUGIN_NAME = void 0;
4
4
  // Plugin constants
5
5
  exports.PLUGIN_NAME = "boundaries";
6
6
  exports.PLUGIN_ENV_VARS_PREFIX = "ESLINT_PLUGIN_BOUNDARIES";
@@ -94,6 +94,7 @@ exports.SETTINGS = {
94
94
  DEPENDENCY_NODES: `${exports.PLUGIN_NAME}/dependency-nodes`,
95
95
  ADDITIONAL_DEPENDENCY_NODES: `${exports.PLUGIN_NAME}/additional-dependency-nodes`,
96
96
  LEGACY_TEMPLATES: `${exports.PLUGIN_NAME}/legacy-templates`,
97
+ CACHE: `${exports.PLUGIN_NAME}/cache`,
97
98
  // env vars
98
99
  DEBUG: `${exports.PLUGIN_ENV_VARS_PREFIX}_DEBUG`,
99
100
  ENV_ROOT_PATH: `${exports.PLUGIN_ENV_VARS_PREFIX}_ROOT_PATH`,
@@ -174,11 +175,16 @@ exports.SETTINGS_KEYS_MAP = {
174
175
  TYPES: exports.SETTINGS.TYPES,
175
176
  /** @deprecated Use import/resolver settings instead */
176
177
  ALIAS: exports.SETTINGS.ALIAS,
178
+ CACHE: exports.SETTINGS.CACHE,
177
179
  };
178
180
  /**
179
181
  * Default value for the legacy templates setting.
180
182
  */
181
183
  exports.LEGACY_TEMPLATES_DEFAULT = true;
184
+ /**
185
+ * Default value for the cache setting.
186
+ */
187
+ exports.CACHE_DEFAULT = true;
182
188
  exports.RULE_POLICY_ALLOW = "allow";
183
189
  exports.RULE_POLICY_DISALLOW = "disallow";
184
190
  /**
@@ -126,6 +126,7 @@ export declare function rulesOptionsSchema(options?: {
126
126
  additionalProperties: boolean;
127
127
  }[];
128
128
  export declare function validateElementTypesMatcher(elementsMatcher: ElementsSelector | ExternalLibrariesSelector, settings: SettingsNormalized): void;
129
+ export declare function isValidElementAssigner(element: unknown): element is ElementDescriptor;
129
130
  export declare function validateSettings(settings: Rule.RuleContext["settings"]): Settings;
130
131
  /**
131
132
  * Returns the normalized settings from the ESLint rule context
@@ -134,4 +135,3 @@ export declare function validateSettings(settings: Rule.RuleContext["settings"])
134
135
  */
135
136
  export declare function getSettings(context: Rule.RuleContext): SettingsNormalized;
136
137
  export declare function validateRules(settings: SettingsNormalized, rules?: RuleOptionsRules[], options?: ValidateRulesOptions): void;
137
- export declare function isValidElementAssigner(element: unknown): element is ElementDescriptor;
@@ -6,10 +6,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.elementsMatcherSchema = elementsMatcherSchema;
7
7
  exports.rulesOptionsSchema = rulesOptionsSchema;
8
8
  exports.validateElementTypesMatcher = validateElementTypesMatcher;
9
+ exports.isValidElementAssigner = isValidElementAssigner;
9
10
  exports.validateSettings = validateSettings;
10
11
  exports.getSettings = getSettings;
11
12
  exports.validateRules = validateRules;
12
- exports.isValidElementAssigner = isValidElementAssigner;
13
13
  const elements_1 = require("@boundaries/elements");
14
14
  const micromatch_1 = __importDefault(require("micromatch"));
15
15
  const Common_1 = require("../Support/Common");
@@ -18,7 +18,6 @@ const Helpers_1 = require("./Helpers");
18
18
  const Settings_1 = require("./Settings");
19
19
  const Settings_types_1 = require("./Settings.types");
20
20
  const { TYPES, ALIAS, ELEMENTS, DEPENDENCY_NODES, ADDITIONAL_DEPENDENCY_NODES, VALID_DEPENDENCY_NODE_KINDS, DEFAULT_DEPENDENCY_NODES, VALID_MODES, } = Settings_types_1.SETTINGS;
21
- const settingsCache = new elements_1.CacheManager();
22
21
  const invalidMatchers = [];
23
22
  const DEFAULT_MATCHER_OPTIONS = {
24
23
  type: "object",
@@ -113,7 +112,7 @@ function isValidElementTypesMatcher(matcher, settings) {
113
112
  const typeMatcherToCheck = (0, Common_1.isString)(matcherToCheck)
114
113
  ? matcherToCheck
115
114
  : matcherToCheck.type;
116
- return (!matcher ||
115
+ return (!typeMatcherToCheck ||
117
116
  (typeMatcherToCheck &&
118
117
  micromatch_1.default.some(settings.elementTypeNames, typeMatcherToCheck)));
119
118
  }
@@ -128,6 +127,43 @@ function validateElementTypesMatcher(elementsMatcher, settings) {
128
127
  (0, Debug_1.warnOnce)(`Option '${matcher}' does not match any element type from '${ELEMENTS}' setting`);
129
128
  }
130
129
  }
130
+ function isValidElementAssigner(element) {
131
+ if (!element) {
132
+ (0, Debug_1.warnOnce)(`Please provide a valid object to define element types in '${ELEMENTS}' setting`);
133
+ return false;
134
+ }
135
+ if ((0, Helpers_1.isLegacyType)(element)) {
136
+ (0, Debug_1.warnOnce)(`Defining elements as strings in settings is deprecated. Will be automatically converted, but this feature will be removed in next major versions`);
137
+ return true;
138
+ }
139
+ else {
140
+ const isObjectElement = (0, Common_1.isObject)(element);
141
+ if (!isObjectElement) {
142
+ (0, Debug_1.warnOnce)(`Please provide a valid object to define element types in '${ELEMENTS}' setting`);
143
+ return false;
144
+ }
145
+ if (!element.type || !(0, Common_1.isString)(element.type)) {
146
+ (0, Debug_1.warnOnce)(`Please provide type in '${ELEMENTS}' setting`);
147
+ return false;
148
+ }
149
+ if (element.mode &&
150
+ (0, Common_1.isString)(element.mode) &&
151
+ !VALID_MODES.includes(element.mode)) {
152
+ (0, Debug_1.warnOnce)(`Invalid mode property of type ${element.type} in '${ELEMENTS}' setting. Should be one of ${VALID_MODES.join(",")}. Default value "${VALID_MODES[0]}" will be used instead`);
153
+ return false;
154
+ }
155
+ if (!element.pattern ||
156
+ !((0, Common_1.isString)(element.pattern) || (0, Common_1.isArray)(element.pattern))) {
157
+ (0, Debug_1.warnOnce)(`Please provide a valid pattern to type ${element.type} in '${ELEMENTS}' setting`);
158
+ return false;
159
+ }
160
+ if (element.capture && !(0, Common_1.isArray)(element.capture)) {
161
+ (0, Debug_1.warnOnce)(`Invalid capture property of type ${element.type} in '${ELEMENTS}' setting`);
162
+ return false;
163
+ }
164
+ return true;
165
+ }
166
+ }
131
167
  function validateElements(elements) {
132
168
  if (!elements || !(0, Common_1.isArray)(elements) || !elements.length) {
133
169
  (0, Debug_1.warnOnce)(`Please provide element types using the '${ELEMENTS}' setting`);
@@ -171,8 +207,6 @@ legacyTemplates) {
171
207
  return legacyTemplates;
172
208
  }
173
209
  (0, Debug_1.warnOnce)(`Please provide a valid value in '${Settings_types_1.SETTINGS_KEYS_MAP.LEGACY_TEMPLATES}' setting. The value should be a boolean.`);
174
- // Value is invalid, return undefined
175
- return;
176
210
  }
177
211
  function isValidDependencyNodeSelector(selector) {
178
212
  const isValidObject = (0, Common_1.isObject)(selector) &&
@@ -237,6 +271,7 @@ function validateRootPath(rootPath) {
237
271
  }
238
272
  (0, Debug_1.warnOnce)(`Please provide a valid value in '${Settings_types_1.SETTINGS_KEYS_MAP.ROOT_PATH}' setting. The value should be a string.`);
239
273
  }
274
+ // TODO: Remove settings validation in next major version. It should be done by schema validation only
240
275
  function validateSettings(settings) {
241
276
  deprecateTypes(settings[TYPES]);
242
277
  deprecateAlias(settings[ALIAS]);
@@ -248,6 +283,7 @@ function validateSettings(settings) {
248
283
  [Settings_types_1.SETTINGS_KEYS_MAP.DEPENDENCY_NODES]: validateDependencyNodes(settings[DEPENDENCY_NODES]),
249
284
  [Settings_types_1.SETTINGS_KEYS_MAP.LEGACY_TEMPLATES]: validateLegacyTemplates(settings[Settings_types_1.SETTINGS_KEYS_MAP.LEGACY_TEMPLATES]),
250
285
  [Settings_types_1.SETTINGS_KEYS_MAP.ADDITIONAL_DEPENDENCY_NODES]: validateAdditionalDependencyNodes(settings[ADDITIONAL_DEPENDENCY_NODES]),
286
+ [Settings_types_1.SETTINGS_KEYS_MAP.CACHE]: settings[Settings_types_1.SETTINGS_KEYS_MAP.CACHE],
251
287
  };
252
288
  }
253
289
  /**
@@ -256,9 +292,6 @@ function validateSettings(settings) {
256
292
  * @returns The normalized settings
257
293
  */
258
294
  function getSettings(context) {
259
- if (settingsCache.has(context.settings)) {
260
- return settingsCache.get(context.settings);
261
- }
262
295
  const validatedSettings = validateSettings(context.settings);
263
296
  const dependencyNodesSetting = (0, Common_1.getArrayOrNull)(validatedSettings[Settings_types_1.SETTINGS_KEYS_MAP.DEPENDENCY_NODES]);
264
297
  const additionalDependencyNodesSetting = (0, Common_1.getArrayOrNull)(validatedSettings[ADDITIONAL_DEPENDENCY_NODES]);
@@ -301,8 +334,8 @@ function getSettings(context) {
301
334
  dependencyNodes: [...dependencyNodes, ...additionalDependencyNodes],
302
335
  legacyTemplates: validatedSettings[Settings_types_1.SETTINGS_KEYS_MAP.LEGACY_TEMPLATES] ??
303
336
  Settings_types_1.LEGACY_TEMPLATES_DEFAULT,
337
+ cache: validatedSettings[Settings_types_1.SETTINGS_KEYS_MAP.CACHE] ?? Settings_types_1.CACHE_DEFAULT,
304
338
  };
305
- settingsCache.set(context.settings, result);
306
339
  return result;
307
340
  }
308
341
  function validateRules(settings, rules = [], options = {}) {
@@ -320,40 +353,3 @@ function validateRules(settings, rules = [], options = {}) {
320
353
  }
321
354
  }
322
355
  }
323
- function isValidElementAssigner(element) {
324
- if (!element) {
325
- (0, Debug_1.warnOnce)(`Please provide a valid object to define element types in '${ELEMENTS}' setting`);
326
- return false;
327
- }
328
- if ((0, Helpers_1.isLegacyType)(element)) {
329
- (0, Debug_1.warnOnce)(`Defining elements as strings in settings is deprecated. Will be automatically converted, but this feature will be removed in next major versions`);
330
- return true;
331
- }
332
- else {
333
- const isObjectElement = (0, Common_1.isObject)(element);
334
- if (!isObjectElement) {
335
- (0, Debug_1.warnOnce)(`Please provide a valid object to define element types in '${ELEMENTS}' setting`);
336
- return false;
337
- }
338
- if (!element.type || !(0, Common_1.isString)(element.type)) {
339
- (0, Debug_1.warnOnce)(`Please provide type in '${ELEMENTS}' setting`);
340
- return false;
341
- }
342
- if (element.mode &&
343
- (0, Common_1.isString)(element.mode) &&
344
- !VALID_MODES.includes(element.mode)) {
345
- (0, Debug_1.warnOnce)(`Invalid mode property of type ${element.type} in '${ELEMENTS}' setting. Should be one of ${VALID_MODES.join(",")}. Default value "${VALID_MODES[0]}" will be used instead`);
346
- return false;
347
- }
348
- if (!element.pattern ||
349
- !((0, Common_1.isString)(element.pattern) || (0, Common_1.isArray)(element.pattern))) {
350
- (0, Debug_1.warnOnce)(`Please provide a valid pattern to type ${element.type} in '${ELEMENTS}' setting`);
351
- return false;
352
- }
353
- if (element.capture && !(0, Common_1.isArray)(element.capture)) {
354
- (0, Debug_1.warnOnce)(`Invalid capture property of type ${element.type} in '${ELEMENTS}' setting`);
355
- return false;
356
- }
357
- return true;
358
- }
359
- }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@boundaries/eslint-plugin",
3
- "version": "5.2.0-beta.1",
3
+ "version": "5.2.0",
4
4
  "description": "Eslint plugin checking architecture boundaries between elements",
5
5
  "keywords": [
6
6
  "eslint",
@@ -53,7 +53,7 @@
53
53
  "eslint-import-resolver-node": "0.3.9",
54
54
  "eslint-module-utils": "2.12.1",
55
55
  "micromatch": "4.0.8",
56
- "@boundaries/elements": "1.0.0"
56
+ "@boundaries/elements": "1.1.0"
57
57
  },
58
58
  "engines": {
59
59
  "node": ">=18.18"