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

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 +4 -8
  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 -11
  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 +16 -14
  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,40 +1,168 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.elementsMatcherSchema = elementsMatcherSchema;
3
+ exports.legacyPoliciesSchema = legacyPoliciesSchema;
4
4
  exports.rulesOptionsSchema = rulesOptionsSchema;
5
- exports.isValidElementAssigner = isValidElementAssigner;
5
+ exports.getRuleMainSelector = getRuleMainSelector;
6
+ exports.validateAndWarnRuleOptions = validateAndWarnRuleOptions;
7
+ exports.isValidElementDescriptor = isValidElementDescriptor;
8
+ exports.validateElementDescriptors = validateElementDescriptors;
9
+ exports.validateDependencyNodes = validateDependencyNodes;
10
+ exports.validateLegacyTemplates = validateLegacyTemplates;
11
+ exports.isValidDependencyNodeSelector = isValidDependencyNodeSelector;
12
+ exports.validateAdditionalDependencyNodes = validateAdditionalDependencyNodes;
13
+ exports.isAliasSetting = isAliasSetting;
14
+ exports.deprecateAlias = deprecateAlias;
15
+ exports.deprecateTypes = deprecateTypes;
16
+ exports.validateIgnore = validateIgnore;
17
+ exports.validateInclude = validateInclude;
18
+ exports.validateRootPath = validateRootPath;
19
+ exports.validateFlagAsExternal = validateFlagAsExternal;
20
+ exports.validateDebugFilterSelectors = validateDebugFilterSelectors;
21
+ exports.validateDebugFilesFilter = validateDebugFilesFilter;
22
+ exports.validateDebugDependenciesFilter = validateDebugDependenciesFilter;
23
+ exports.validateDebug = validateDebug;
6
24
  exports.validateSettings = validateSettings;
7
25
  exports.getSettings = getSettings;
8
26
  const elements_1 = require("@boundaries/elements");
9
- const Common_1 = require("../Support/Common");
10
- const Debug_1 = require("../Support/Debug");
27
+ const Debug_1 = require("../Debug");
28
+ const Shared_1 = require("../Shared");
29
+ const Settings_types_1 = require("../Shared/Settings.types");
11
30
  const Helpers_1 = require("./Helpers");
12
31
  const Settings_1 = require("./Settings");
13
- const Settings_types_1 = require("./Settings.types");
14
32
  const { TYPES, ALIAS, ELEMENTS, DEPENDENCY_NODES, ADDITIONAL_DEPENDENCY_NODES, VALID_DEPENDENCY_NODE_KINDS, DEFAULT_DEPENDENCY_NODES, VALID_MODES, } = Settings_types_1.SETTINGS;
15
- const DEFAULT_MATCHER_OPTIONS = {
33
+ const trackedValidatedSettings = new WeakMap();
34
+ const trackedWarnedOptions = new WeakSet();
35
+ const defaultLegacyMatcherOptionsSchema = {
16
36
  type: "object",
17
37
  };
18
- function elementsMatcherSchema(matcherOptions = DEFAULT_MATCHER_OPTIONS) {
38
+ /** Schema for validating a micromatch pattern or array of patterns that can also be null. */
39
+ const micromatchPatternNullableSchema = {
40
+ oneOf: [
41
+ { type: ["string", "null"] },
42
+ { type: "array", items: { type: ["string", "null"] } },
43
+ ],
44
+ };
45
+ const dependencyRelationshipSchema = {
46
+ type: "object",
47
+ properties: {
48
+ from: micromatchPatternNullableSchema,
49
+ to: micromatchPatternNullableSchema,
50
+ },
51
+ additionalProperties: false,
52
+ };
53
+ const dependencyMatcherItemSchema = {
54
+ type: "object",
55
+ properties: {
56
+ relationship: dependencyRelationshipSchema,
57
+ kind: micromatchPatternNullableSchema,
58
+ specifiers: micromatchPatternNullableSchema,
59
+ nodeKind: micromatchPatternNullableSchema,
60
+ source: micromatchPatternNullableSchema,
61
+ module: micromatchPatternNullableSchema,
62
+ },
63
+ additionalProperties: false,
64
+ };
65
+ const dependencyMatcherSchema = {
66
+ oneOf: [
67
+ dependencyMatcherItemSchema,
68
+ {
69
+ type: "array",
70
+ items: dependencyMatcherItemSchema,
71
+ },
72
+ ],
73
+ };
74
+ const capturedValuesSelectorSchema = {
75
+ type: "object",
76
+ additionalProperties: micromatchPatternNullableSchema,
77
+ };
78
+ const capturedValuesSchema = {
79
+ oneOf: [
80
+ {
81
+ type: "null",
82
+ },
83
+ capturedValuesSelectorSchema,
84
+ {
85
+ type: "array",
86
+ items: capturedValuesSelectorSchema,
87
+ },
88
+ ],
89
+ };
90
+ const parentElementMatcherSchema = {
91
+ type: "object",
92
+ properties: {
93
+ type: micromatchPatternNullableSchema,
94
+ category: micromatchPatternNullableSchema,
95
+ elementPath: micromatchPatternNullableSchema,
96
+ captured: capturedValuesSchema,
97
+ },
98
+ additionalProperties: false,
99
+ };
100
+ const objectElementMatcherSchemaItem = {
101
+ type: "object", // single object-based selector (new format)
102
+ properties: {
103
+ path: micromatchPatternNullableSchema,
104
+ elementPath: micromatchPatternNullableSchema,
105
+ internalPath: micromatchPatternNullableSchema,
106
+ type: micromatchPatternNullableSchema,
107
+ category: micromatchPatternNullableSchema,
108
+ captured: capturedValuesSchema,
109
+ parent: {
110
+ oneOf: [
111
+ { type: "null" },
112
+ parentElementMatcherSchema,
113
+ { type: "array", items: parentElementMatcherSchema },
114
+ ],
115
+ },
116
+ origin: micromatchPatternNullableSchema,
117
+ isIgnored: { type: "boolean" },
118
+ isUnknown: { type: "boolean" },
119
+ },
120
+ additionalProperties: false,
121
+ };
122
+ const objectElementMatcherSchema = {
123
+ oneOf: [
124
+ objectElementMatcherSchemaItem,
125
+ {
126
+ type: "array",
127
+ items: objectElementMatcherSchemaItem,
128
+ },
129
+ ],
130
+ };
131
+ /**
132
+ * Builds JSON schema for legacy policy selectors.
133
+ *
134
+ * @param matcherOptions - Extra matcher options accepted in legacy tuple syntax.
135
+ * @returns JSON schema definition for legacy policy values.
136
+ */
137
+ function legacyPoliciesSchema(matcherOptions = defaultLegacyMatcherOptionsSchema) {
19
138
  return {
20
- oneOf: [
139
+ anyOf: [
21
140
  {
22
- type: "string", // single matcher
141
+ type: "string", // single matcher (legacy)
142
+ },
143
+ {
144
+ type: "array", // matcher with captured values (legacy)
145
+ items: [
146
+ {
147
+ type: "string", // matcher
148
+ },
149
+ matcherOptions, // Extra options for legacy rules with custom syntax
150
+ ],
23
151
  },
24
152
  {
25
153
  type: "array", // multiple matchers
26
154
  items: {
27
- oneOf: [
155
+ anyOf: [
28
156
  {
29
- type: "string", // matcher with options
157
+ type: "string", // matcher (legacy)
30
158
  },
31
159
  {
32
- type: "array",
160
+ type: "array", // matcher with captured values (legacy)
33
161
  items: [
34
162
  {
35
163
  type: "string", // matcher
36
164
  },
37
- matcherOptions, // options
165
+ matcherOptions, // Extra options for legacy rules with custom syntax
38
166
  ],
39
167
  },
40
168
  ],
@@ -43,9 +171,116 @@ function elementsMatcherSchema(matcherOptions = DEFAULT_MATCHER_OPTIONS) {
43
171
  ],
44
172
  };
45
173
  }
46
- function rulesOptionsSchema(options = {}) {
47
- const mainKey = (0, Helpers_1.rulesMainKey)(options.rulesMainKey);
48
- return [
174
+ const legacyElementsSelectorItemSchema = {
175
+ anyOf: [
176
+ {
177
+ type: "string", // single matcher (legacy)
178
+ },
179
+ {
180
+ type: "array", // matcher with captured values (legacy)
181
+ items: [
182
+ {
183
+ type: "string", // matcher
184
+ },
185
+ defaultLegacyMatcherOptionsSchema, // Extra options for legacy rules with custom syntax
186
+ ],
187
+ },
188
+ ],
189
+ };
190
+ const legacyElementsSelectorSchema = {
191
+ anyOf: [
192
+ legacyElementsSelectorItemSchema,
193
+ {
194
+ type: "array",
195
+ items: legacyElementsSelectorItemSchema,
196
+ },
197
+ ],
198
+ };
199
+ /**
200
+ * Builds JSON schema for rule options of dependency-based rules.
201
+ *
202
+ * @param options - Schema customization options for rule main key and extras.
203
+ * @returns ESLint-compatible schema array for rule options.
204
+ */
205
+ function rulesOptionsSchema({ rulesMainKey: mainKey, targetMatcherOptions, extraOptionsSchema, isLegacy = false, } = {}) {
206
+ const policySchema = isLegacy
207
+ ? legacyPoliciesSchema(targetMatcherOptions)
208
+ : {
209
+ anyOf: [
210
+ legacyPoliciesSchema(targetMatcherOptions),
211
+ {
212
+ type: "object",
213
+ properties: {
214
+ from: objectElementMatcherSchema,
215
+ to: objectElementMatcherSchema,
216
+ dependency: dependencyMatcherSchema,
217
+ },
218
+ additionalProperties: false,
219
+ },
220
+ ],
221
+ };
222
+ const policiesSchema = {
223
+ anyOf: [
224
+ policySchema,
225
+ {
226
+ type: "array",
227
+ items: policySchema,
228
+ },
229
+ ],
230
+ };
231
+ const elementSelectorSchema = {
232
+ anyOf: [legacyElementsSelectorSchema, objectElementMatcherSchema],
233
+ };
234
+ const legacyMainKey = (0, Helpers_1.rulesMainKey)(mainKey);
235
+ const ruleSupportedProperties = isLegacy
236
+ ? {
237
+ [legacyMainKey]: elementSelectorSchema,
238
+ allow: policiesSchema,
239
+ disallow: policiesSchema,
240
+ }
241
+ : {
242
+ from: elementSelectorSchema,
243
+ to: elementSelectorSchema,
244
+ dependency: dependencyMatcherSchema,
245
+ allow: policiesSchema,
246
+ disallow: policiesSchema,
247
+ };
248
+ const requiredProperties = isLegacy
249
+ ? [
250
+ {
251
+ required: [legacyMainKey, "allow"],
252
+ },
253
+ {
254
+ required: [legacyMainKey, "disallow"],
255
+ },
256
+ ]
257
+ : [
258
+ {
259
+ required: ["allow"],
260
+ },
261
+ {
262
+ required: ["disallow"],
263
+ },
264
+ {
265
+ required: ["from", "allow"],
266
+ },
267
+ {
268
+ required: ["from", "disallow"],
269
+ },
270
+ {
271
+ required: ["to", "allow"],
272
+ },
273
+ {
274
+ required: ["to", "disallow"],
275
+ },
276
+ {
277
+ required: ["dependency", "allow"],
278
+ },
279
+ {
280
+ required: ["dependency", "disallow"],
281
+ },
282
+ ];
283
+ const schema = [
49
284
  {
50
285
  type: "object",
51
286
  properties: {
@@ -61,11 +296,9 @@ function rulesOptionsSchema(options = {}) {
61
296
  items: {
62
297
  type: "object",
63
298
  properties: {
64
- [mainKey]: elementsMatcherSchema(),
65
- allow: elementsMatcherSchema(options.targetMatcherOptions),
66
- disallow: elementsMatcherSchema(options.targetMatcherOptions),
299
+ ...ruleSupportedProperties,
67
300
  importKind: {
68
- oneOf: [
301
+ anyOf: [
69
302
  {
70
303
  type: "string",
71
304
  },
@@ -82,218 +315,611 @@ function rulesOptionsSchema(options = {}) {
82
315
  },
83
316
  },
84
317
  additionalProperties: false,
85
- anyOf: [
86
- {
87
- required: [mainKey, "allow", "disallow"],
88
- },
89
- {
90
- required: [mainKey, "allow"],
91
- },
92
- {
93
- required: [mainKey, "disallow"],
94
- },
95
- ],
318
+ anyOf: requiredProperties,
96
319
  },
97
320
  },
321
+ ...extraOptionsSchema,
98
322
  },
99
323
  additionalProperties: false,
100
324
  },
101
325
  ];
326
+ return schema;
102
327
  }
103
- function isValidElementAssigner(element) {
104
- if (!element) {
105
- (0, Debug_1.warnOnce)(`Please provide a valid object to define element types in '${ELEMENTS}' setting`);
106
- return false;
328
+ /**
329
+ * Returns the selector configured under the active rule main key.
330
+ *
331
+ * @param rule - Single rule entry from options.
332
+ * @param mainKey - Main selector key configured for current rule.
333
+ * @returns Selector value from the corresponding property, when present.
334
+ */
335
+ function getRuleMainSelector(rule, mainKey) {
336
+ if (mainKey === "from") {
337
+ return "from" in rule ? rule.from : undefined;
107
338
  }
108
- if ((0, Helpers_1.isLegacyType)(element)) {
109
- (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`);
110
- return true;
339
+ if (mainKey === "to") {
340
+ return "to" in rule ? rule.to : undefined;
111
341
  }
112
- else {
113
- const isObjectElement = (0, Common_1.isObject)(element);
114
- if (!isObjectElement) {
115
- (0, Debug_1.warnOnce)(`Please provide a valid object to define element types in '${ELEMENTS}' setting`);
116
- return false;
342
+ return "target" in rule ? rule.target : undefined;
343
+ }
344
+ /**
345
+ * Returns all rule selectors that must be checked for legacy syntax.
346
+ *
347
+ * @param rule - Rule entry from options.
348
+ * @param mainKey - Main key used by the current rule.
349
+ * @returns List of selectors from main key, allow and disallow.
350
+ */
351
+ function getRuleSelectorsToCheck(rule, mainKey) {
352
+ const ruleMainKey = (0, Helpers_1.rulesMainKey)(mainKey);
353
+ return [getRuleMainSelector(rule, ruleMainKey), rule.allow, rule.disallow];
354
+ }
355
+ /**
356
+ * Detects deprecated selector and template syntax across selectors.
357
+ *
358
+ * @param selectors - Selector values to inspect.
359
+ * @returns Flags describing whether each deprecated syntax was found.
360
+ */
361
+ function detectLegacyFlags(selectors) {
362
+ let hasLegacySelector = false;
363
+ let hasLegacyTemplate = false;
364
+ for (const selector of selectors) {
365
+ if (!selector) {
366
+ continue;
117
367
  }
118
- if (!element.type || !(0, Common_1.isString)(element.type)) {
119
- (0, Debug_1.warnOnce)(`Please provide type in '${ELEMENTS}' setting`);
120
- return false;
368
+ if ((0, Helpers_1.detectLegacyElementSelector)(selector)) {
369
+ hasLegacySelector = true;
121
370
  }
122
- if (element.mode &&
123
- (0, Common_1.isString)(element.mode) &&
124
- !VALID_MODES.includes(element.mode)) {
125
- (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`);
126
- return false;
371
+ if ((0, Helpers_1.detectLegacyTemplateSyntax)(selector)) {
372
+ hasLegacyTemplate = true;
127
373
  }
128
- if (!element.pattern ||
129
- !((0, Common_1.isString)(element.pattern) || (0, Common_1.isArray)(element.pattern))) {
130
- (0, Debug_1.warnOnce)(`Please provide a valid pattern to type ${element.type} in '${ELEMENTS}' setting`);
131
- return false;
374
+ }
375
+ return {
376
+ hasLegacySelector,
377
+ hasLegacyTemplate,
378
+ };
379
+ }
380
+ /**
381
+ * Collects indices of rules using deprecated selector/template/importKind syntax.
382
+ *
383
+ * @param rules - Rule list to inspect.
384
+ * @param mainKey - Main selector key configured for current rule.
385
+ * @returns Rule indices grouped by deprecated syntax type.
386
+ */
387
+ function collectRuleWarningIndexes(rules, mainKey) {
388
+ const indexes = {
389
+ rulesWithLegacySelector: [],
390
+ rulesWithLegacyTemplate: [],
391
+ rulesWithDeprecatedImportKind: [],
392
+ };
393
+ for (const [index, rule] of rules.entries()) {
394
+ const selectorsToCheck = getRuleSelectorsToCheck(rule, mainKey);
395
+ const { hasLegacySelector, hasLegacyTemplate } = detectLegacyFlags(selectorsToCheck);
396
+ if (hasLegacySelector) {
397
+ indexes.rulesWithLegacySelector.push(index);
132
398
  }
133
- if (element.capture && !(0, Common_1.isArray)(element.capture)) {
134
- (0, Debug_1.warnOnce)(`Invalid capture property of type ${element.type} in '${ELEMENTS}' setting`);
135
- return false;
399
+ if (hasLegacyTemplate) {
400
+ indexes.rulesWithLegacyTemplate.push(index);
136
401
  }
402
+ if (!(0, Shared_1.isUndefined)(rule.importKind)) {
403
+ indexes.rulesWithDeprecatedImportKind.push(index);
404
+ }
405
+ }
406
+ return indexes;
407
+ }
408
+ /**
409
+ * Warns once when deprecated selector/template syntax is detected in rules.
410
+ *
411
+ * @param options - Rule options containing `rules` entries.
412
+ * @param ruleName - Rule name displayed in warning messages.
413
+ * @param mainKey - Main selector key used by the current rule.
414
+ */
415
+ function validateAndWarnRuleOptions(options, ruleName, mainKey = "from") {
416
+ if (!options || trackedWarnedOptions.has(options)) {
417
+ return;
418
+ }
419
+ if (!options.rules || !(0, Shared_1.isArray)(options.rules)) {
420
+ return;
421
+ }
422
+ trackedWarnedOptions.add(options);
423
+ const { rulesWithLegacySelector, rulesWithLegacyTemplate, rulesWithDeprecatedImportKind, } = collectRuleWarningIndexes(options.rules, mainKey);
424
+ if (rulesWithLegacySelector.length > 0) {
425
+ (0, Debug_1.warnOnce)(`[${ruleName}] Detected legacy selector syntax in ${rulesWithLegacySelector.length} rule(s) at indices: ${rulesWithLegacySelector.join(", ")}.`, `Consider migrating to object-based selectors. ${(0, Helpers_1.migrationToV6GuideLink)()}`);
426
+ }
427
+ if (rulesWithLegacyTemplate.length > 0) {
428
+ (0, Debug_1.warnOnce)(`[${ruleName}] Detected legacy template syntax \${...} in ${rulesWithLegacyTemplate.length} rule(s) at indices: ${rulesWithLegacyTemplate.join(", ")}.`, `Consider migrating to {{...}} syntax. ${(0, Helpers_1.migrationToV6GuideLink)("new-template-syntax")}`);
429
+ }
430
+ if (rulesWithDeprecatedImportKind.length > 0) {
431
+ (0, Debug_1.warnOnce)(`[${ruleName}] Detected deprecated rule-level "importKind" in ${rulesWithDeprecatedImportKind.length} rule(s) at indices: ${rulesWithDeprecatedImportKind.join(", ")}.`, `Use selector-level "dependency.kind" instead. When both are defined, "dependency.kind" takes precedence. ${(0, Helpers_1.migrationToV6GuideLink)("rule-level-importkind-is-deprecated")}`);
432
+ }
433
+ }
434
+ /**
435
+ * Emits a generic warning for invalid element descriptor values.
436
+ */
437
+ function warnInvalidElementDescriptor() {
438
+ (0, Debug_1.warnOnce)(`Invalid element descriptor in '${ELEMENTS}' setting.`, (0, Helpers_1.moreInfoSettingsLink)());
439
+ }
440
+ /**
441
+ * Validates that descriptor contains at least one identity property.
442
+ *
443
+ * @param element - Candidate element descriptor object.
444
+ * @returns `true` when descriptor has either `type` or `category`.
445
+ */
446
+ function hasTypeOrCategory(element) {
447
+ return Boolean(element.type || element.category);
448
+ }
449
+ /**
450
+ * Checks whether descriptor `type` property, when present, is valid.
451
+ *
452
+ * @param element - Candidate element descriptor object.
453
+ * @returns `true` when `type` is absent or a string.
454
+ */
455
+ function hasValidTypeProperty(element) {
456
+ return !element.type || (0, Shared_1.isString)(element.type);
457
+ }
458
+ /**
459
+ * Checks whether descriptor `category` property, when present, is valid.
460
+ *
461
+ * @param element - Candidate element descriptor object.
462
+ * @returns `true` when `category` is absent or a string.
463
+ */
464
+ function hasValidCategoryProperty(element) {
465
+ return !element.category || (0, Shared_1.isString)(element.category);
466
+ }
467
+ /**
468
+ * Checks whether descriptor `mode` property uses a supported mode value.
469
+ *
470
+ * @param element - Candidate element descriptor object.
471
+ * @returns `true` when mode is absent, non-string, or included in valid modes.
472
+ */
473
+ function hasValidModeProperty(element) {
474
+ if (!element.mode || !(0, Shared_1.isString)(element.mode)) {
137
475
  return true;
138
476
  }
477
+ return VALID_MODES.includes(element.mode);
478
+ }
479
+ /**
480
+ * Checks whether descriptor `pattern` property is valid.
481
+ *
482
+ * @param element - Candidate element descriptor object.
483
+ * @returns `true` when pattern exists and is a string or array.
484
+ */
485
+ function hasValidPatternProperty(element) {
486
+ return Boolean(element.pattern && ((0, Shared_1.isString)(element.pattern) || (0, Shared_1.isArray)(element.pattern)));
487
+ }
488
+ /**
489
+ * Checks whether descriptor `capture` property, when present, is valid.
490
+ *
491
+ * @param element - Candidate element descriptor object.
492
+ * @returns `true` when capture is absent or an array.
493
+ */
494
+ function hasValidCaptureProperty(element) {
495
+ return !element.capture || (0, Shared_1.isArray)(element.capture);
139
496
  }
140
- function validateElements(elements) {
141
- if (!elements || !(0, Common_1.isArray)(elements) || !elements.length) {
142
- (0, Debug_1.warnOnce)(`Please provide element types using the '${ELEMENTS}' setting`);
497
+ /**
498
+ * Validates object-based element descriptor properties and emits warnings.
499
+ *
500
+ * @param element - Candidate element descriptor object.
501
+ * @returns `true` when descriptor object is valid.
502
+ */
503
+ function validateObjectElementDescriptor(element) {
504
+ if (!hasTypeOrCategory(element)) {
505
+ (0, Debug_1.warnOnce)(`Missing "type" or "category" property in an element descriptor in '${ELEMENTS}' setting.`, (0, Helpers_1.moreInfoSettingsLink)());
506
+ return false;
507
+ }
508
+ if (!hasValidTypeProperty(element)) {
509
+ (0, Debug_1.warnOnce)(`Invalid "type" property in an element descriptor in '${ELEMENTS}' setting.`, (0, Helpers_1.moreInfoSettingsLink)());
510
+ return false;
511
+ }
512
+ if (!hasValidCategoryProperty(element)) {
513
+ (0, Debug_1.warnOnce)(`Invalid "category" property in an element descriptor in '${ELEMENTS}' setting.`, (0, Helpers_1.moreInfoSettingsLink)());
514
+ return false;
515
+ }
516
+ if (!hasValidModeProperty(element)) {
517
+ (0, Debug_1.warnOnce)(`Invalid "mode" property in an element descriptor in '${ELEMENTS}' setting.`, `It should be one of ${VALID_MODES.join(", ")}. ${(0, Helpers_1.moreInfoSettingsLink)()}`);
518
+ return false;
519
+ }
520
+ if (!hasValidPatternProperty(element)) {
521
+ (0, Debug_1.warnOnce)(`Invalid "pattern" property in an element descriptor in '${ELEMENTS}' setting.`, (0, Helpers_1.moreInfoSettingsLink)());
522
+ return false;
523
+ }
524
+ if (!hasValidCaptureProperty(element)) {
525
+ (0, Debug_1.warnOnce)(`Invalid "capture" property in an element descriptor in '${ELEMENTS}' setting.`, `Capture should be an array of strings. ${(0, Helpers_1.moreInfoSettingsLink)()}`);
526
+ return false;
527
+ }
528
+ return true;
529
+ }
530
+ /**
531
+ * Validates one element descriptor item from plugin settings.
532
+ *
533
+ * @param element - Candidate element descriptor from settings.
534
+ * @returns `true` when descriptor is valid or accepted legacy string.
535
+ */
536
+ function isValidElementDescriptor(element) {
537
+ if (!element) {
538
+ warnInvalidElementDescriptor();
539
+ return false;
540
+ }
541
+ if ((0, Helpers_1.isLegacyType)(element)) {
542
+ (0, Debug_1.warnOnce)(`Defining elements as strings in settings is deprecated.`, `It will be automatically converted, but this feature will be removed in next major versions. ${(0, Helpers_1.migrationToV6GuideLink)()}`);
543
+ return true;
544
+ }
545
+ if (!(0, Shared_1.isObject)(element)) {
546
+ warnInvalidElementDescriptor();
547
+ return false;
548
+ }
549
+ return validateObjectElementDescriptor(element);
550
+ }
551
+ /**
552
+ * Validates and filters the configured list of element descriptors.
553
+ *
554
+ * @param elements - Raw `boundaries/elements` setting value.
555
+ * @returns Valid descriptors or `undefined` when setting is invalid/missing.
556
+ */
557
+ function validateElementDescriptors(elements) {
558
+ if (!elements || !(0, Shared_1.isArray)(elements) || !elements.length) {
559
+ (0, Debug_1.warnOnce)(`Please provide element descriptors using the '${ELEMENTS}' setting.`, (0, Helpers_1.moreInfoSettingsLink)());
143
560
  return;
144
561
  }
145
- return elements.filter(isValidElementAssigner);
562
+ return elements.filter(isValidElementDescriptor);
146
563
  }
564
+ /**
565
+ * Validates configured dependency node keys.
566
+ *
567
+ * @param dependencyNodes - Raw dependency node keys from settings.
568
+ * @returns Filtered valid keys or `undefined` for missing/invalid setting.
569
+ */
147
570
  function validateDependencyNodes(dependencyNodes) {
148
571
  if (!dependencyNodes) {
149
572
  return;
150
573
  }
151
574
  const defaultNodesNames = Object.keys(DEFAULT_DEPENDENCY_NODES);
152
- const invalidFormatMessage = [
153
- `Please provide a valid value in ${DEPENDENCY_NODES} setting.`,
154
- `The value should be an array of the following strings:`,
155
- ` "${defaultNodesNames.join('", "')}".`,
156
- ].join(" ");
157
- if (!(0, Common_1.isArray)(dependencyNodes)) {
158
- (0, Debug_1.warnOnce)(invalidFormatMessage);
575
+ const invalidFormatTitle = `Invalid ${DEPENDENCY_NODES} setting format.`;
576
+ const invalidNodeMessage = `It should be an array of the following strings: "${defaultNodesNames.join('", "')}". ${(0, Helpers_1.moreInfoSettingsLink)()}`;
577
+ if (!(0, Shared_1.isArray)(dependencyNodes)) {
578
+ (0, Debug_1.warnOnce)(invalidFormatTitle, invalidNodeMessage);
159
579
  return;
160
580
  }
161
581
  for (const dependencyNode of dependencyNodes) {
162
582
  if (!(0, Helpers_1.isDependencyNodeKey)(dependencyNode)) {
163
- (0, Debug_1.warnOnce)(invalidFormatMessage);
583
+ (0, Debug_1.warnOnce)(invalidFormatTitle, invalidNodeMessage);
164
584
  }
165
585
  }
166
586
  return dependencyNodes.filter(Helpers_1.isDependencyNodeKey);
167
587
  }
168
588
  /**
169
589
  * Validates the legacyTemplates setting.
170
- * @param legacyTemplates The legacyTemplates setting value
171
- * @returns The validated legacyTemplates value or undefined
590
+ *
591
+ * @param legacyTemplates - Raw legacyTemplates setting value.
592
+ * @returns Validated boolean value or `undefined` when missing/invalid.
172
593
  */
173
- function validateLegacyTemplates(
174
- /** The legacyTemplates setting value */
175
- legacyTemplates) {
176
- if (legacyTemplates === undefined) {
594
+ function validateLegacyTemplates(legacyTemplates) {
595
+ if ((0, Shared_1.isUndefined)(legacyTemplates)) {
177
596
  return;
178
597
  }
179
- if ((0, Common_1.isBoolean)(legacyTemplates)) {
598
+ if ((0, Shared_1.isBoolean)(legacyTemplates)) {
180
599
  return legacyTemplates;
181
600
  }
182
- (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.`);
601
+ (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. ${(0, Helpers_1.moreInfoSettingsLink)()}`);
183
602
  }
603
+ /**
604
+ * Validates one custom dependency-node selector object.
605
+ *
606
+ * @param selector - Candidate additional dependency node selector.
607
+ * @returns `true` when selector has a valid shape.
608
+ */
184
609
  function isValidDependencyNodeSelector(selector) {
185
- const isValidObject = (0, Common_1.isObject)(selector) &&
186
- (0, Common_1.isString)(selector.selector) &&
610
+ const isValidObject = (0, Shared_1.isObject)(selector) &&
611
+ (0, Shared_1.isString)(selector.selector) &&
187
612
  (!selector.kind ||
188
- ((0, Common_1.isString)(selector.kind) &&
189
- VALID_DEPENDENCY_NODE_KINDS.includes(selector.kind)));
613
+ ((0, Shared_1.isString)(selector.kind) &&
614
+ VALID_DEPENDENCY_NODE_KINDS.includes(selector.kind))) &&
615
+ (!selector.name || (0, Shared_1.isString)(selector.name));
190
616
  if (!isValidObject) {
191
- (0, Debug_1.warnOnce)(`Please provide a valid object in ${ADDITIONAL_DEPENDENCY_NODES} setting. The object should be composed of the following properties: { selector: "<esquery selector>", kind: "value" | "type" }. The invalid object will be ignored.`);
617
+ (0, Debug_1.warnOnce)(`Please provide a valid object in ${ADDITIONAL_DEPENDENCY_NODES} setting.`, `The object should be composed of the following properties: { selector: "<esquery selector>", kind: "value" | "type", name: "<string>" (optional) }. The invalid object will be ignored. ${(0, Helpers_1.moreInfoSettingsLink)()}`);
618
+ }
619
+ else if ((0, Shared_1.isObject)(selector) && !selector.name) {
620
+ (0, Debug_1.warnOnce)(`Consider adding a "name" property to your custom dependency node for using it in selectors and custom messages.`, (0, Helpers_1.moreInfoSettingsLink)());
192
621
  }
193
622
  return isValidObject;
194
623
  }
624
+ /**
625
+ * Validates the list of additional dependency node selectors.
626
+ *
627
+ * @param additionalDependencyNodes - Raw custom dependency nodes setting.
628
+ * @returns Valid selectors or `undefined` when absent/invalid.
629
+ */
195
630
  function validateAdditionalDependencyNodes(additionalDependencyNodes) {
196
631
  if (!additionalDependencyNodes) {
197
632
  return;
198
633
  }
199
- const invalidFormatMessage = [
200
- `Please provide a valid value in ${ADDITIONAL_DEPENDENCY_NODES} setting.`,
201
- "The value should be an array composed of the following objects:",
202
- '{ selector: "<esquery selector>", kind: "value" | "type" }.',
203
- ].join(" ");
204
- if (!(0, Common_1.isArray)(additionalDependencyNodes)) {
205
- (0, Debug_1.warnOnce)(invalidFormatMessage);
634
+ const invalidFormatTitle = `Invalid ${ADDITIONAL_DEPENDENCY_NODES} setting format.`;
635
+ const invalidNodeMessage = `It should be an array containing objects with the following properties: { selector: "<esquery selector>", kind: "value" | "type", name: "<string>" (optional) }. ${(0, Helpers_1.moreInfoSettingsLink)()}`;
636
+ if (!(0, Shared_1.isArray)(additionalDependencyNodes)) {
637
+ (0, Debug_1.warnOnce)(invalidFormatTitle, invalidNodeMessage);
206
638
  return;
207
639
  }
208
640
  return additionalDependencyNodes.filter(isValidDependencyNodeSelector);
209
641
  }
642
+ /**
643
+ * Type guard for alias setting object.
644
+ *
645
+ * @param value - Candidate alias setting value.
646
+ * @returns `true` when value is an object whose values are strings.
647
+ */
648
+ function isAliasSetting(value) {
649
+ return (0, Shared_1.isObject)(value) && Object.values(value).every(Shared_1.isString);
650
+ }
651
+ /**
652
+ * Emits deprecation warning for legacy `alias` setting.
653
+ *
654
+ * @param aliases - Alias setting value when present.
655
+ */
210
656
  function deprecateAlias(aliases) {
211
657
  if (aliases) {
212
- (0, Debug_1.warnOnce)(`Defining aliases in '${ALIAS}' setting is deprecated. Please use 'import/resolver' setting`);
658
+ (0, Debug_1.warnOnce)(`Defining aliases in '${ALIAS}' setting is deprecated.`, `Please use 'import/resolver' setting. ${(0, Helpers_1.moreInfoSettingsLink)()}`);
213
659
  }
214
660
  }
661
+ /**
662
+ * Emits deprecation warning for legacy `types` setting.
663
+ *
664
+ * @param types - Legacy types setting value when present.
665
+ */
215
666
  function deprecateTypes(types) {
216
667
  if (types) {
217
- (0, Debug_1.warnOnce)(`'${TYPES}' setting is deprecated. Please use '${ELEMENTS}' instead`);
668
+ (0, Debug_1.warnOnce)(`'${TYPES}' setting is deprecated.`, `Please use '${ELEMENTS}' instead. ${(0, Helpers_1.migrationToV2GuideLink)()}`);
218
669
  }
219
670
  }
671
+ /**
672
+ * Validates `ignore` setting values.
673
+ *
674
+ * @param ignore - Raw ignore setting.
675
+ * @returns String or string array when valid.
676
+ */
220
677
  function validateIgnore(ignore) {
221
678
  if (!ignore) {
222
679
  return;
223
680
  }
224
- if ((0, Common_1.isString)(ignore) || ((0, Common_1.isArray)(ignore) && ignore.every(Common_1.isString))) {
681
+ if ((0, Shared_1.isString)(ignore) || ((0, Shared_1.isArray)(ignore) && ignore.every(Shared_1.isString))) {
225
682
  return ignore;
226
683
  }
227
- (0, Debug_1.warnOnce)(`Please provide a valid value in '${Settings_types_1.SETTINGS_KEYS_MAP.IGNORE}' setting. The value should be a string or an array of strings.`);
684
+ (0, Debug_1.warnOnce)(`Please provide a valid value in '${Settings_types_1.SETTINGS_KEYS_MAP.IGNORE}' setting.`, `The value should be a string or an array of strings. ${(0, Helpers_1.moreInfoSettingsLink)()}`);
228
685
  }
686
+ /**
687
+ * Validates `include` setting values.
688
+ *
689
+ * @param include - Raw include setting.
690
+ * @returns String or string array when valid.
691
+ */
229
692
  function validateInclude(include) {
230
693
  if (!include) {
231
694
  return;
232
695
  }
233
- if ((0, Common_1.isString)(include) || ((0, Common_1.isArray)(include) && include.every(Common_1.isString))) {
696
+ if ((0, Shared_1.isString)(include) || ((0, Shared_1.isArray)(include) && include.every(Shared_1.isString))) {
234
697
  return include;
235
698
  }
236
- (0, Debug_1.warnOnce)(`Please provide a valid value in '${Settings_types_1.SETTINGS_KEYS_MAP.INCLUDE}' setting. The value should be a string or an array of strings.`);
699
+ (0, Debug_1.warnOnce)(`Please provide a valid value in '${Settings_types_1.SETTINGS_KEYS_MAP.INCLUDE}' setting.`, `The value should be a string or an array of strings. ${(0, Helpers_1.moreInfoSettingsLink)()}`);
237
700
  }
701
+ /**
702
+ * Validates `root-path` setting values.
703
+ *
704
+ * @param rootPath - Raw root-path setting.
705
+ * @returns Root path string when valid.
706
+ */
238
707
  function validateRootPath(rootPath) {
239
708
  if (!rootPath) {
240
709
  return;
241
710
  }
242
- if ((0, Common_1.isString)(rootPath)) {
711
+ if ((0, Shared_1.isString)(rootPath)) {
243
712
  return rootPath;
244
713
  }
245
- (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.`);
714
+ (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. ${(0, Helpers_1.moreInfoSettingsLink)()}`);
715
+ }
716
+ /**
717
+ * Validates and assigns an optional boolean field in `flag-as-external` settings.
718
+ *
719
+ * @param options - Raw `flag-as-external` settings object.
720
+ * @param validated - Accumulator for validated options.
721
+ * @param optionKey - Optional boolean field to validate and assign.
722
+ */
723
+ function assignFlagAsExternalBooleanOption(options, validated, optionKey) {
724
+ const value = options[optionKey];
725
+ if ((0, Shared_1.isUndefined)(value)) {
726
+ return;
727
+ }
728
+ if ((0, Shared_1.isBoolean)(value)) {
729
+ validated[optionKey] = value;
730
+ return;
731
+ }
732
+ (0, Debug_1.warnOnce)(`Please provide a valid boolean for '${optionKey}' in '${Settings_types_1.SETTINGS_KEYS_MAP.FLAG_AS_EXTERNAL}' setting.`, (0, Helpers_1.moreInfoSettingsLink)());
733
+ }
734
+ /**
735
+ * Validates and assigns `customSourcePatterns` in `flag-as-external` settings.
736
+ *
737
+ * @param options - Raw `flag-as-external` settings object.
738
+ * @param validated - Accumulator for validated options.
739
+ */
740
+ function assignFlagAsExternalCustomSourcePatterns(options, validated) {
741
+ const value = options.customSourcePatterns;
742
+ if ((0, Shared_1.isUndefined)(value)) {
743
+ return;
744
+ }
745
+ if ((0, Shared_1.isArray)(value) && value.every(Shared_1.isString)) {
746
+ validated.customSourcePatterns = value;
747
+ return;
748
+ }
749
+ (0, Debug_1.warnOnce)(`Please provide a valid array of strings for 'customSourcePatterns' in '${Settings_types_1.SETTINGS_KEYS_MAP.FLAG_AS_EXTERNAL}' setting.`, (0, Helpers_1.moreInfoSettingsLink)());
246
750
  }
751
+ /**
752
+ * Validates `flag-as-external` setting object and fields.
753
+ *
754
+ * @param flagAsExternal - Raw flag-as-external setting value.
755
+ * @returns Normalized options object with valid fields only.
756
+ */
247
757
  function validateFlagAsExternal(flagAsExternal) {
248
758
  if (!flagAsExternal) {
249
759
  return;
250
760
  }
251
- if (!(0, Common_1.isObject)(flagAsExternal)) {
252
- (0, Debug_1.warnOnce)(`Please provide a valid value in '${Settings_types_1.SETTINGS_KEYS_MAP.FLAG_AS_EXTERNAL}' setting. The value should be an object.`);
761
+ if (!(0, Shared_1.isObject)(flagAsExternal)) {
762
+ (0, Debug_1.warnOnce)(`Please provide a valid value in '${Settings_types_1.SETTINGS_KEYS_MAP.FLAG_AS_EXTERNAL}' setting.`, `The value should be an object. ${(0, Helpers_1.moreInfoSettingsLink)()}`);
253
763
  return;
254
764
  }
765
+ const options = flagAsExternal;
255
766
  const validated = {};
256
- if (flagAsExternal.unresolvableAlias !== undefined) {
257
- if ((0, Common_1.isBoolean)(flagAsExternal.unresolvableAlias)) {
258
- validated.unresolvableAlias = flagAsExternal.unresolvableAlias;
259
- }
260
- else {
261
- (0, Debug_1.warnOnce)(`Please provide a valid boolean for 'unresolvableAlias' in '${Settings_types_1.SETTINGS_KEYS_MAP.FLAG_AS_EXTERNAL}' setting.`);
262
- }
767
+ assignFlagAsExternalBooleanOption(options, validated, "unresolvableAlias");
768
+ assignFlagAsExternalBooleanOption(options, validated, "inNodeModules");
769
+ assignFlagAsExternalBooleanOption(options, validated, "outsideRootPath");
770
+ assignFlagAsExternalCustomSourcePatterns(options, validated);
771
+ return validated;
772
+ }
773
+ /**
774
+ * Validates debug filter selectors for files or dependencies.
775
+ *
776
+ * @param value - Raw filter value.
777
+ * @param filterName - Filter key used in warning messages.
778
+ * @returns Filter array when valid, otherwise `undefined`.
779
+ */
780
+ function validateDebugFilterSelectors(value, filterName) {
781
+ if ((0, Shared_1.isUndefined)(value)) {
782
+ return undefined;
263
783
  }
264
- if (flagAsExternal.inNodeModules !== undefined) {
265
- if ((0, Common_1.isBoolean)(flagAsExternal.inNodeModules)) {
266
- validated.inNodeModules = flagAsExternal.inNodeModules;
267
- }
268
- else {
269
- (0, Debug_1.warnOnce)(`Please provide a valid boolean for 'inNodeModules' in '${Settings_types_1.SETTINGS_KEYS_MAP.FLAG_AS_EXTERNAL}' setting.`);
270
- }
784
+ if ((0, Shared_1.isArray)(value)) {
785
+ return value;
271
786
  }
272
- if (flagAsExternal.outsideRootPath !== undefined) {
273
- if ((0, Common_1.isBoolean)(flagAsExternal.outsideRootPath)) {
274
- validated.outsideRootPath = flagAsExternal.outsideRootPath;
275
- }
276
- else {
277
- (0, Debug_1.warnOnce)(`Please provide a valid boolean for 'outsideRootPath' in '${Settings_types_1.SETTINGS_KEYS_MAP.FLAG_AS_EXTERNAL}' setting.`);
278
- }
787
+ (0, Debug_1.warnOnce)(`Please provide a valid array for '${filterName}' in '${Settings_types_1.SETTINGS_KEYS_MAP.DEBUG}' setting.`, (0, Helpers_1.moreInfoSettingsLink)());
788
+ return undefined;
789
+ }
790
+ /**
791
+ * Validates debug `files` filter selector list.
792
+ *
793
+ * @param value - Raw `debug.filter.files` setting value.
794
+ * @returns Valid files filter selectors.
795
+ */
796
+ function validateDebugFilesFilter(value) {
797
+ return validateDebugFilterSelectors(value, "files");
798
+ }
799
+ /**
800
+ * Validates debug `dependencies` filter selector list.
801
+ *
802
+ * @param value - Raw `debug.filter.dependencies` setting value.
803
+ * @returns Valid dependency filter selectors.
804
+ */
805
+ function validateDebugDependenciesFilter(value) {
806
+ return validateDebugFilterSelectors(value, "dependencies");
807
+ }
808
+ /**
809
+ * Validates and assigns `debug.enabled` when provided.
810
+ *
811
+ * @param debug - Raw debug setting object.
812
+ * @param validated - Debug setting accumulator.
813
+ */
814
+ function assignDebugEnabled(debug, validated) {
815
+ if ((0, Shared_1.isUndefined)(debug.enabled)) {
816
+ return;
279
817
  }
280
- if (flagAsExternal.customSourcePatterns !== undefined) {
281
- if ((0, Common_1.isArray)(flagAsExternal.customSourcePatterns) &&
282
- flagAsExternal.customSourcePatterns.every(Common_1.isString)) {
283
- validated.customSourcePatterns = flagAsExternal.customSourcePatterns;
284
- }
285
- else {
286
- (0, Debug_1.warnOnce)(`Please provide a valid array of strings for 'customSourcePatterns' in '${Settings_types_1.SETTINGS_KEYS_MAP.FLAG_AS_EXTERNAL}' setting.`);
287
- }
818
+ if ((0, Shared_1.isBoolean)(debug.enabled)) {
819
+ validated.enabled = debug.enabled;
820
+ return;
821
+ }
822
+ (0, Debug_1.warnOnce)(`Please provide a valid boolean for 'enabled' in '${Settings_types_1.SETTINGS_KEYS_MAP.DEBUG}' setting.`, (0, Helpers_1.moreInfoSettingsLink)());
823
+ }
824
+ /**
825
+ * Validates and assigns a `debug.messages.*` boolean flag when provided.
826
+ *
827
+ * @param messages - Raw `debug.messages` object.
828
+ * @param validated - Debug setting accumulator.
829
+ * @param key - Message flag key to validate.
830
+ */
831
+ function assignDebugMessageFlag(messages, validated, key) {
832
+ const value = messages[key];
833
+ if ((0, Shared_1.isUndefined)(value)) {
834
+ return;
835
+ }
836
+ if ((0, Shared_1.isBoolean)(value)) {
837
+ validated.messages[key] = value;
838
+ return;
839
+ }
840
+ (0, Debug_1.warnOnce)(`Please provide a valid boolean for 'messages.${key}' in '${Settings_types_1.SETTINGS_KEYS_MAP.DEBUG}' setting.`, (0, Helpers_1.moreInfoSettingsLink)());
841
+ }
842
+ /**
843
+ * Validates and assigns `debug.messages` object and known flags.
844
+ *
845
+ * @param debug - Raw debug setting object.
846
+ * @param validated - Debug setting accumulator.
847
+ */
848
+ function assignDebugMessages(debug, validated) {
849
+ if ((0, Shared_1.isUndefined)(debug.messages)) {
850
+ return;
851
+ }
852
+ if (!(0, Shared_1.isObject)(debug.messages)) {
853
+ (0, Debug_1.warnOnce)(`Please provide a valid object for 'messages' in '${Settings_types_1.SETTINGS_KEYS_MAP.DEBUG}' setting.`, (0, Helpers_1.moreInfoSettingsLink)());
854
+ return;
855
+ }
856
+ assignDebugMessageFlag(debug.messages, validated, "files");
857
+ assignDebugMessageFlag(debug.messages, validated, "dependencies");
858
+ assignDebugMessageFlag(debug.messages, validated, "violations");
859
+ }
860
+ /**
861
+ * Validates and assigns `debug.filter` object and supported selectors.
862
+ *
863
+ * @param debug - Raw debug setting object.
864
+ * @param validated - Debug setting accumulator.
865
+ */
866
+ function assignDebugFilter(debug, validated) {
867
+ if ((0, Shared_1.isUndefined)(debug.filter)) {
868
+ return;
869
+ }
870
+ if (!(0, Shared_1.isObject)(debug.filter)) {
871
+ (0, Debug_1.warnOnce)(`Please provide a valid object for 'filter' in '${Settings_types_1.SETTINGS_KEYS_MAP.DEBUG}' setting.`, (0, Helpers_1.moreInfoSettingsLink)());
872
+ return;
288
873
  }
874
+ const files = validateDebugFilesFilter(debug.filter.files);
875
+ const dependencies = validateDebugDependenciesFilter(debug.filter.dependencies);
876
+ validated.filter = {
877
+ ...((0, Shared_1.isUndefined)(files) ? {} : { files }),
878
+ ...((0, Shared_1.isUndefined)(dependencies) ? {} : { dependencies }),
879
+ };
880
+ }
881
+ /**
882
+ * Validates the `debug` setting object and nested filters.
883
+ *
884
+ * @param debug - Raw debug setting value.
885
+ * @returns Normalized debug setting when valid.
886
+ */
887
+ function validateDebug(debug) {
888
+ const validated = {
889
+ enabled: false,
890
+ filter: {
891
+ files: undefined,
892
+ dependencies: undefined,
893
+ },
894
+ messages: {
895
+ files: true,
896
+ dependencies: true,
897
+ violations: true,
898
+ },
899
+ };
900
+ if (!debug) {
901
+ return validated;
902
+ }
903
+ if (!(0, Shared_1.isObject)(debug)) {
904
+ (0, Debug_1.warnOnce)(`Please provide a valid value in '${Settings_types_1.SETTINGS_KEYS_MAP.DEBUG}' setting.`, `The value should be an object. ${(0, Helpers_1.moreInfoSettingsLink)()}`);
905
+ return validated;
906
+ }
907
+ assignDebugEnabled(debug, validated);
908
+ assignDebugMessages(debug, validated);
909
+ assignDebugFilter(debug, validated);
289
910
  return validated;
290
911
  }
291
- // TODO: Remove settings validation in next major version. It should be done by schema validation only
912
+ /**
913
+ * Validates plugin settings and returns a sanitized settings object.
914
+ *
915
+ * @param settings - Raw ESLint context settings.
916
+ * @returns Validated settings ready for normalization.
917
+ */
292
918
  function validateSettings(settings) {
293
919
  deprecateTypes(settings[TYPES]);
294
- deprecateAlias(settings[ALIAS]);
920
+ deprecateAlias(isAliasSetting(settings[ALIAS]) ? settings[ALIAS] : undefined);
295
921
  return {
296
- [Settings_types_1.SETTINGS_KEYS_MAP.ELEMENTS]: validateElements(settings[ELEMENTS] || settings[TYPES]),
922
+ [Settings_types_1.SETTINGS_KEYS_MAP.ELEMENTS]: validateElementDescriptors(settings[ELEMENTS] || settings[TYPES]),
297
923
  [Settings_types_1.SETTINGS_KEYS_MAP.IGNORE]: validateIgnore(settings[Settings_types_1.SETTINGS_KEYS_MAP.IGNORE]),
298
924
  [Settings_types_1.SETTINGS_KEYS_MAP.INCLUDE]: validateInclude(settings[Settings_types_1.SETTINGS_KEYS_MAP.INCLUDE]),
299
925
  [Settings_types_1.SETTINGS_KEYS_MAP.ROOT_PATH]: validateRootPath(settings[Settings_types_1.SETTINGS_KEYS_MAP.ROOT_PATH]),
@@ -302,46 +928,44 @@ function validateSettings(settings) {
302
928
  [Settings_types_1.SETTINGS_KEYS_MAP.ADDITIONAL_DEPENDENCY_NODES]: validateAdditionalDependencyNodes(settings[ADDITIONAL_DEPENDENCY_NODES]),
303
929
  [Settings_types_1.SETTINGS_KEYS_MAP.CACHE]: settings[Settings_types_1.SETTINGS_KEYS_MAP.CACHE],
304
930
  [Settings_types_1.SETTINGS_KEYS_MAP.FLAG_AS_EXTERNAL]: validateFlagAsExternal(settings[Settings_types_1.SETTINGS_KEYS_MAP.FLAG_AS_EXTERNAL]),
931
+ [Settings_types_1.SETTINGS_KEYS_MAP.DEBUG]: validateDebug(settings[Settings_types_1.SETTINGS_KEYS_MAP.DEBUG]),
305
932
  };
306
933
  }
307
934
  /**
308
- * Returns the normalized settings from the ESLint rule context
309
- * @param context The ESLint rule context
310
- * @returns The normalized settings
935
+ * Returns normalized and cached settings from ESLint rule context.
936
+ *
937
+ * @param context - ESLint rule context.
938
+ * @returns Normalized settings object used by rules.
311
939
  */
312
940
  function getSettings(context) {
941
+ const alreadyValidatedSettings = trackedValidatedSettings.get(context.settings);
942
+ if (alreadyValidatedSettings) {
943
+ return alreadyValidatedSettings;
944
+ }
313
945
  const validatedSettings = validateSettings(context.settings);
314
- const dependencyNodesSetting = (0, Common_1.getArrayOrNull)(validatedSettings[Settings_types_1.SETTINGS_KEYS_MAP.DEPENDENCY_NODES]);
315
- const additionalDependencyNodesSetting = (0, Common_1.getArrayOrNull)(validatedSettings[ADDITIONAL_DEPENDENCY_NODES]);
316
- const dependencyNodes =
317
- // TODO In next major version, make this default to all types of nodes!!!
318
- (dependencyNodesSetting || [Settings_types_1.DEPENDENCY_NODE_KEYS_MAP.IMPORT])
319
- .flatMap((dependencyNode) => [
320
- ...DEFAULT_DEPENDENCY_NODES[dependencyNode],
946
+ const dependencyNodesSetting = (0, Shared_1.getArrayOrNull)(validatedSettings[Settings_types_1.SETTINGS_KEYS_MAP.DEPENDENCY_NODES]);
947
+ const additionalDependencyNodesSetting = (0, Shared_1.getArrayOrNull)(validatedSettings[ADDITIONAL_DEPENDENCY_NODES]);
948
+ const dependencyNodes = (dependencyNodesSetting || [
949
+ Settings_types_1.DEPENDENCY_NODE_KEYS_MAP.IMPORT,
950
+ Settings_types_1.DEPENDENCY_NODE_KEYS_MAP.EXPORT,
951
+ Settings_types_1.DEPENDENCY_NODE_KEYS_MAP.REQUIRE,
952
+ Settings_types_1.DEPENDENCY_NODE_KEYS_MAP.DYNAMIC_IMPORT,
321
953
  ])
954
+ .flatMap((dependencyNode) => [...DEFAULT_DEPENDENCY_NODES[dependencyNode]])
322
955
  .filter(Boolean);
323
956
  const additionalDependencyNodes = additionalDependencyNodesSetting || [];
324
957
  const ignoreSetting = validatedSettings[Settings_types_1.SETTINGS_KEYS_MAP.IGNORE];
325
- const ignorePaths = (0, Common_1.isString)(ignoreSetting) ? [ignoreSetting] : ignoreSetting;
958
+ const ignorePaths = (0, Shared_1.isString)(ignoreSetting) ? [ignoreSetting] : ignoreSetting;
326
959
  const includeSetting = validatedSettings[Settings_types_1.SETTINGS_KEYS_MAP.INCLUDE];
327
- const includePaths = (0, Common_1.isString)(includeSetting)
960
+ const includePaths = (0, Shared_1.isString)(includeSetting)
328
961
  ? [includeSetting]
329
962
  : includeSetting;
963
+ const debugSetting = validatedSettings[Settings_types_1.SETTINGS_KEYS_MAP.DEBUG];
330
964
  const descriptors = (0, Settings_1.transformLegacyTypes)(validatedSettings[ELEMENTS]);
331
- // NOTE: Filter valid descriptors only to avoid a breaking change for the moment
332
965
  const validDescriptors = descriptors.filter(elements_1.isElementDescriptor);
333
- const invalidDescriptors = descriptors.filter((desc) => !(0, elements_1.isElementDescriptor)(desc));
334
- if (invalidDescriptors.length > 0) {
335
- /*
336
- * TODO: Report invalid descriptors in ESLint context as a warning in a separate rule:
337
- * context.report({
338
- * message: `Some element descriptors are invalid and will be ignored: ${JSON.stringify(
339
- * invalidDescriptors,
340
- * )}`,
341
- * loc: { line: 1, column: 0 },
342
- * });
343
- */
344
- (0, Debug_1.warnOnce)(`Some element descriptors are invalid and will be ignored: ${JSON.stringify(invalidDescriptors)}`);
966
+ if (validDescriptors.length < descriptors.length) {
967
+ const invalidDescriptors = descriptors.filter((desc) => !(0, elements_1.isElementDescriptor)(desc));
968
+ (0, Debug_1.warnOnce)(`Some element descriptors are invalid and will be ignored.`, `Invalid descriptors:\n${JSON.stringify(invalidDescriptors)}.\n${(0, Helpers_1.moreInfoSettingsLink)()}`);
345
969
  }
346
970
  const result = {
347
971
  elementDescriptors: validDescriptors,
@@ -363,6 +987,8 @@ function getSettings(context) {
363
987
  customSourcePatterns: validatedSettings[Settings_types_1.SETTINGS_KEYS_MAP.FLAG_AS_EXTERNAL]
364
988
  ?.customSourcePatterns ?? [],
365
989
  },
990
+ debug: debugSetting,
366
991
  };
992
+ trackedValidatedSettings.set(context.settings, result);
367
993
  return result;
368
994
  }