@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
@@ -0,0 +1,156 @@
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.replaceObjectValueInLegacyTemplate = replaceObjectValueInLegacyTemplate;
7
+ exports.elementPropertiesToReplaceInLegacyTemplate = elementPropertiesToReplaceInLegacyTemplate;
8
+ exports.customErrorMessage = customErrorMessage;
9
+ const elements_1 = require("@boundaries/elements");
10
+ const handlebars_1 = __importDefault(require("handlebars"));
11
+ const Shared_1 = require("../Shared");
12
+ /** Regular expression to detect Handlebars expressions in custom message templates */
13
+ const HANDLEBARS_TEMPLATE_REGEX = /{{\s*[^{}\s][^{}]*}}/;
14
+ /**
15
+ * Replaces all occurrences of a placeholder key in a template string.
16
+ *
17
+ * Placeholders use the `${key}` syntax and optionally support namespacing
18
+ * (for example `${from.type}` or `${dependency.parent.category}`).
19
+ *
20
+ * @param template - Message template where placeholders are replaced.
21
+ * @param key - Placeholder key to replace (without `${}` delimiters).
22
+ * @param value - Value injected in place of the placeholder.
23
+ * @param namespace - Optional namespace prepended to the key before replacing.
24
+ * @returns Template string with the requested placeholder replaced.
25
+ */
26
+ function replaceObjectValueInLegacyTemplate(template, key, value, namespace) {
27
+ const keyToReplace = namespace ? `${namespace}.${key}` : key;
28
+ const regexp = new RegExp(String.raw `\$\{${keyToReplace}\}`, "g");
29
+ return template.replace(regexp, value);
30
+ }
31
+ /**
32
+ * Replaces multiple placeholders in a template string using values from an object.
33
+ *
34
+ * @param template - One template string.
35
+ * @param object - Key/value pairs used for placeholder replacement.
36
+ * @param namespace - Optional namespace prepended to every object key.
37
+ * @returns Replaced template string.
38
+ */
39
+ function replaceObjectValuesInLegacyTemplate(template, object, namespace) {
40
+ const finalResult = template;
41
+ return Object.keys(object).reduce((result, objectKey) => {
42
+ return replaceObjectValueInLegacyTemplate(result, objectKey, object[objectKey], namespace);
43
+ }, finalResult);
44
+ }
45
+ /**
46
+ * Creates the replacement context consumed by legacy `${...}` placeholders.
47
+ *
48
+ * The resulting object normalizes available element information and dependency
49
+ * metadata so templates can use keys consistently regardless of source.
50
+ *
51
+ * @param element - Element or parent element that provides captured values.
52
+ * @param importKind - Dependency kind (`value`, `type`, etc.).
53
+ * @param dependencyMetadata - Extra dependency metadata for full elements.
54
+ * @returns Normalized key/value map used during placeholder replacement.
55
+ */
56
+ function elementPropertiesToReplaceInLegacyTemplate(element, importKind, dependencyMetadata) {
57
+ if ((0, elements_1.isElementDescription)(element)) {
58
+ const source = dependencyMetadata?.source || "";
59
+ const dependencyModule = dependencyMetadata?.module || "";
60
+ return {
61
+ ...element.captured,
62
+ type: element.type || "",
63
+ internalPath: element.internalPath || "",
64
+ source,
65
+ module: dependencyModule,
66
+ importKind: importKind || "",
67
+ };
68
+ }
69
+ return {
70
+ ...element.captured,
71
+ type: element.type || "",
72
+ internalPath: "",
73
+ source: "",
74
+ module: "",
75
+ importKind: importKind || "",
76
+ };
77
+ }
78
+ /**
79
+ * Checks whether a template uses Handlebars syntax.
80
+ *
81
+ * @param template - Custom message template.
82
+ * @returns `true` when the template contains at least one Handlebars token.
83
+ */
84
+ function hasHandlebarsTemplate(template) {
85
+ return HANDLEBARS_TEMPLATE_REGEX.test(template);
86
+ }
87
+ /**
88
+ * Renders Handlebars expressions in a custom message template.
89
+ *
90
+ * If the template does not contain Handlebars expressions, it is returned as-is.
91
+ *
92
+ * @param template - Message template that may include Handlebars expressions.
93
+ * @param dependency - Dependency context exposed to the template.
94
+ * @param ruleIndex - Index of the rule that triggered the error, if applicable.
95
+ * @param matchResult - Full result of the dependency matching process, if applicable.
96
+ * @returns Final message after optional Handlebars rendering.
97
+ */
98
+ function renderCustomMessageHandlebarsTemplate(template, dependency, ruleIndex, matchResult) {
99
+ if (!hasHandlebarsTemplate(template)) {
100
+ return template;
101
+ }
102
+ const context = {
103
+ from: dependency.from,
104
+ to: dependency.to,
105
+ dependency: dependency.dependency,
106
+ rule: !(0, Shared_1.isNull)(ruleIndex) && matchResult
107
+ ? {
108
+ index: ruleIndex,
109
+ selector: {
110
+ from: matchResult.from,
111
+ to: matchResult.to,
112
+ dependency: matchResult.dependency,
113
+ },
114
+ }
115
+ : null,
116
+ };
117
+ const compiledTemplate = handlebars_1.default.compile(template, { noEscape: true });
118
+ return compiledTemplate(context);
119
+ }
120
+ /**
121
+ * Returns message fragments replacing legacy `${...}` placeholders with dependency information.
122
+ * @param template Template string containing `${...}` placeholders.
123
+ * @param dependency The dependency information used to replace placeholders in the template.
124
+ * @returns Template string with `${...}` placeholders replaced by corresponding values from the dependency information.
125
+ */
126
+ function replaceLegacyTemplateVariables(template, dependency) {
127
+ let replacedMessage = replaceObjectValuesInLegacyTemplate(replaceObjectValuesInLegacyTemplate(template, elementPropertiesToReplaceInLegacyTemplate(dependency.from, dependency.dependency.kind), "file"), elementPropertiesToReplaceInLegacyTemplate(dependency.to, dependency.dependency.kind, dependency.dependency), "dependency");
128
+ replacedMessage = replaceObjectValuesInLegacyTemplate(replaceObjectValuesInLegacyTemplate(replacedMessage, elementPropertiesToReplaceInLegacyTemplate(dependency.from, dependency.dependency.kind), "from"), elementPropertiesToReplaceInLegacyTemplate(dependency.to, dependency.dependency.kind, dependency.dependency), "target");
129
+ if (dependency.from.parents?.[0]) {
130
+ replacedMessage = replaceObjectValuesInLegacyTemplate(replacedMessage, elementPropertiesToReplaceInLegacyTemplate(dependency.from.parents?.[0], dependency.dependency.kind), "file.parent");
131
+ replacedMessage = replaceObjectValuesInLegacyTemplate(replacedMessage, elementPropertiesToReplaceInLegacyTemplate(dependency.from.parents?.[0], dependency.dependency.kind), "from.parent");
132
+ }
133
+ if (dependency.to.parents?.[0]) {
134
+ replacedMessage = replaceObjectValuesInLegacyTemplate(replacedMessage, elementPropertiesToReplaceInLegacyTemplate(dependency.to.parents?.[0], dependency.dependency.kind), "dependency.parent");
135
+ replacedMessage = replaceObjectValuesInLegacyTemplate(replacedMessage, elementPropertiesToReplaceInLegacyTemplate(dependency.to.parents?.[0], dependency.dependency.kind), "target.parent");
136
+ }
137
+ return replaceObjectValuesInLegacyTemplate(replacedMessage, {
138
+ path: dependency.to.internalPath || "",
139
+ specifiers: dependency.dependency.specifiers?.join(", ") || "",
140
+ }, "report");
141
+ }
142
+ /**
143
+ * Builds the final custom error message for a dependency violation.
144
+ *
145
+ * This function first resolves legacy `${...}` placeholders (`file`, `from`,
146
+ * `dependency`, `target`, and parent variants) and then evaluates optional
147
+ * Handlebars expressions with the same dependency context.
148
+ *
149
+ * @param template - User-defined message template from rule configuration.
150
+ * @param dependency - Runtime dependency information used by placeholders.
151
+ * @returns Rendered, user-facing error message.
152
+ */
153
+ function customErrorMessage(template, dependency, ruleIndex = null, matchResult = null) {
154
+ const replacedMessage = replaceLegacyTemplateVariables(template, dependency);
155
+ return renderCustomMessageHandlebarsTemplate(replacedMessage, dependency, ruleIndex, matchResult);
156
+ }
@@ -0,0 +1,25 @@
1
+ import type { DependencyDescription, DependencySelector } from "@boundaries/elements";
2
+ export type CustomMessageTemplateRuleContext = {
3
+ /** Index of the rule that triggered the error */
4
+ index: number | null;
5
+ /** Selector of the rule that matched the dependency */
6
+ selector: {
7
+ /** Information about the selector that matched the dependency importer element */
8
+ from: DependencySelector["from"] | null;
9
+ /** Information about the selector that matched the dependency target element */
10
+ to: DependencySelector["to"] | null;
11
+ /** Information about the selector that matched the dependency metadata */
12
+ dependency: DependencySelector["dependency"] | null;
13
+ };
14
+ } | null;
15
+ /** Context received by custom message templates */
16
+ export type CustomMessageTemplateContext = {
17
+ /** Information about the dependency importer element */
18
+ from: DependencyDescription["from"] | null;
19
+ /** Information about the dependency target element */
20
+ to: DependencyDescription["to"] | null;
21
+ /** Information about the dependency itself */
22
+ dependency: DependencyDescription["dependency"] | null;
23
+ /** Context about the rule that matched the dependency, if any */
24
+ rule: CustomMessageTemplateRuleContext;
25
+ };
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -1,14 +1,43 @@
1
- import type { DependencyKind, CapturedValuesSelector, ElementParent, ElementsSelector, CapturedValues, DependencyDescription, ElementDescription } from "@boundaries/elements";
2
- import type { RuleMatcherElementsCapturedValues } from "../Settings";
3
- export declare function replaceObjectValuesInTemplates(strings: string | string[], object: Record<string, string>, namespace?: string | null): string | string[];
4
- export declare function replaceObjectValuesInTemplate(template: string, object: Record<string, string>, namespace?: string | null): string;
5
- export declare function quote(str: string | undefined | null): string;
6
- export declare function micromatchPatternReplacingObjectsValues(pattern: string | string[] | undefined, object: Partial<RuleMatcherElementsCapturedValues>): string | string[];
7
- export declare function ruleElementMessage(elementPatterns: ElementsSelector | undefined, elementCapturedValues: CapturedValues | null): string | import("@boundaries/elements").BaseElementSelectorData | import("@boundaries/elements").BaseElementSelectorWithOptions | CapturedValuesSelector;
8
- export declare function customErrorMessage(message: string, dependency: DependencyDescription, report?: {}): string;
9
- export declare function elementMessage(elementInfo: ElementDescription | ElementParent): string;
10
- export declare function dependencyImportKindMessage(ruleImportKind: DependencyKind | undefined, dependency: DependencyDescription): string;
11
- export declare function dependencyUsageKindMessage(ruleImportKind: DependencyKind | undefined, dependency: DependencyDescription, { suffix, prefix, }?: {
12
- suffix?: string;
13
- prefix?: string;
1
+ import type { DependencyDescription, DependencyMatchResult, BaseElementSelectorData, DependencyDataSelectorData, ElementDescription, ElementParent, ElementsDependencyInfo } from "@boundaries/elements";
2
+ /**
3
+ * Describes elements using the selected relevant properties.
4
+ * @param elementDescription - Element to describe.
5
+ * @param properties - List of element properties to include in the description.
6
+ * @param options - Additional options for message formatting.
7
+ * @param options.singleElement - If `true`, uses singular "element" label instead of "elements of".
8
+ * @returns Formatted message describing the element based on the selected properties.
9
+ */
10
+ export declare function elementDescriptionMessage(elementDescription: ElementDescription | ElementParent, properties: string[], { singleElement, includeNullValues, }?: {
11
+ singleElement?: boolean;
12
+ includeNullValues?: boolean;
14
13
  }): string;
14
+ /**
15
+ * Describes elements using selector-driven relevant properties and captured keys.
16
+ * @param elementDescription - Element to describe.
17
+ * @param selectorData - Selector data that determines which properties and captured keys to include in the description.
18
+ */
19
+ export declare function elementDescriptionMessageFromSelector(elementDescription: ElementDescription | ElementParent, selectorData: BaseElementSelectorData | null): string | null;
20
+ /**
21
+ * Describes dependency metadata using selected relevant properties.
22
+ * @param dependencyMetadata - Dependency metadata to describe.
23
+ * @param properties - List of dependency metadata properties to include in the description.
24
+ * @returns Formatted message describing the dependency metadata based on the selected properties.
25
+ */
26
+ export declare function dependencyDescriptionMessage(dependencyMetadata: ElementsDependencyInfo, properties: string[], options?: {
27
+ includeNullValues?: boolean;
28
+ }): string;
29
+ /**
30
+ * Describes dependency metadata using selector-driven relevant properties.
31
+ * @param dependencyMetadata - Dependency metadata to describe.
32
+ * @param selectorData - Selector data that determines which properties and captured keys to include in the description.
33
+ * @returns Formatted message describing the dependency metadata based on the selected properties.
34
+ */
35
+ export declare function dependencyDescriptionMessageFromSelector(dependencyMetadata: ElementsDependencyInfo, selectorData: DependencyDataSelectorData | null): string | null;
36
+ /**
37
+ * Builds the default message for dependencies rule violations from the matching selector data.
38
+ * @param matchResult - Result of matching the dependency against the rule's selector, containing the relevant selector data for the from/to elements and the dependency metadata.
39
+ * @param ruleIndex - Index of the matching rule.
40
+ * @param dependency - Described dependency that triggered the violation, used to extract element and dependency metadata for message construction.
41
+ * @returns Formatted error message describing the violation based on the matching selector data.
42
+ */
43
+ export declare function dependenciesRuleDefaultErrorMessage(matchResult: DependencyMatchResult | null, ruleIndex: number | null, dependency: DependencyDescription): string;