@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,40 @@
1
+ import type { Linter } from "eslint";
2
+ import type { PluginBoundaries, Config } from "../Settings";
3
+ import { PLUGIN_NAME } from "../Settings";
4
+ export * from "../Public";
5
+ type PluginFullConfig<PluginName extends string = typeof PLUGIN_NAME> = {
6
+ plugins: Record<PluginName, PluginBoundaries>;
7
+ files: Linter.Config["files"];
8
+ } & Omit<Config<PluginName>, "plugins">;
9
+ /**
10
+ * Returns an ESLint config object with the boundaries plugin registered, providing default JS and TS file patterns
11
+ * and enforcing valid types for settings and rules. Supports renaming the plugin. Rules can be prefixed with either
12
+ * the original plugin name or the provided plugin name.
13
+ *
14
+ * @param config - ESLint config object without the plugins field.
15
+ * @param name - The name of the plugin to register. Defaults to "boundaries".
16
+ * @returns {Linter.Config} The ESLint config object with the boundaries plugin registered and the provided config merged in.
17
+ * @throws {Error} If settings or rules are not from eslint-plugin-boundaries.
18
+ *
19
+ * @example
20
+ * ```ts
21
+ * import { createConfig, recommended } from "eslint-plugin-boundaries/config";
22
+ *
23
+ * const config = createConfig({
24
+ * settings: {
25
+ * ...recommended.settings,
26
+ * "boundaries/elements": [],
27
+ * "boundaries/ignore": ["ignored/*.js"],
28
+ * },
29
+ * rules: {
30
+ * ...recommended.rules,
31
+ * "boundaries/element-types": ["error", { default: "disallow" }],
32
+ * }
33
+ * });
34
+ *
35
+ * export default [config];
36
+ * ```
37
+ */
38
+ export declare function createConfig<PluginName extends string = typeof PLUGIN_NAME>(config: Omit<Config<PluginName> | Config, "plugins">, name?: PluginName): PluginFullConfig<PluginName>;
39
+ export declare const recommended: Config<"boundaries">;
40
+ export declare const strict: Config<"boundaries">;
@@ -0,0 +1,119 @@
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
+ var __importDefault = (this && this.__importDefault) || function (mod) {
17
+ return (mod && mod.__esModule) ? mod : { "default": mod };
18
+ };
19
+ Object.defineProperty(exports, "__esModule", { value: true });
20
+ exports.strict = exports.recommended = void 0;
21
+ exports.createConfig = createConfig;
22
+ const index_1 = __importDefault(require("../index"));
23
+ const Settings_1 = require("../Settings");
24
+ const Recommended_1 = __importDefault(require("./Recommended"));
25
+ const Strict_1 = __importDefault(require("./Strict"));
26
+ __exportStar(require("../Public"), exports);
27
+ function renamePluginRules(pluginName, rules) {
28
+ if (!rules) {
29
+ return {};
30
+ }
31
+ const allowedPrefixes = new Set([Settings_1.PLUGIN_NAME, pluginName]);
32
+ // Return the same rules objects, but converting plugin default rule keys with provided plugin name
33
+ return Object.entries(rules).reduce((acc, [key, value]) => {
34
+ if (!key.includes("/")) {
35
+ throw new Error(`Invalid rule key "${key}". When using createConfig, all rules must belong to eslint-plugin-boundaries. You can prefix them with the original plugin name "${Settings_1.PLUGIN_NAME}/", or with the provided plugin name "${pluginName}/".`);
36
+ }
37
+ const splittedRuleKey = key.split("/");
38
+ const rulePrefix = splittedRuleKey[0];
39
+ const ruleName = splittedRuleKey[1];
40
+ if (!allowedPrefixes.has(rulePrefix)) {
41
+ throw new Error(`Invalid rule key "${key}". When using createConfig, all rules must belong to eslint-plugin-boundaries. You can prefix them with the original plugin name "${Settings_1.PLUGIN_NAME}/", or with the provided plugin name "${pluginName}/".`);
42
+ }
43
+ if (!(0, Settings_1.isRuleShortName)(ruleName)) {
44
+ throw new Error(`Invalid rule name "${ruleName}". When using createConfig, all rules must belong to eslint-plugin-boundaries.`);
45
+ }
46
+ let newKey;
47
+ if (rulePrefix === Settings_1.PLUGIN_NAME) {
48
+ const suffix = key.slice(Settings_1.PLUGIN_NAME.length + 1);
49
+ newKey = `${pluginName}/${suffix}`;
50
+ }
51
+ else {
52
+ newKey = key;
53
+ }
54
+ acc[newKey] = value;
55
+ return acc;
56
+ }, {});
57
+ }
58
+ /**
59
+ * Returns an ESLint config object with the boundaries plugin registered, providing default JS and TS file patterns
60
+ * and enforcing valid types for settings and rules. Supports renaming the plugin. Rules can be prefixed with either
61
+ * the original plugin name or the provided plugin name.
62
+ *
63
+ * @param config - ESLint config object without the plugins field.
64
+ * @param name - The name of the plugin to register. Defaults to "boundaries".
65
+ * @returns {Linter.Config} The ESLint config object with the boundaries plugin registered and the provided config merged in.
66
+ * @throws {Error} If settings or rules are not from eslint-plugin-boundaries.
67
+ *
68
+ * @example
69
+ * ```ts
70
+ * import { createConfig, recommended } from "eslint-plugin-boundaries/config";
71
+ *
72
+ * const config = createConfig({
73
+ * settings: {
74
+ * ...recommended.settings,
75
+ * "boundaries/elements": [],
76
+ * "boundaries/ignore": ["ignored/*.js"],
77
+ * },
78
+ * rules: {
79
+ * ...recommended.rules,
80
+ * "boundaries/element-types": ["error", { default: "disallow" }],
81
+ * }
82
+ * });
83
+ *
84
+ * export default [config];
85
+ * ```
86
+ */
87
+ function createConfig(config, name = Settings_1.PLUGIN_NAME) {
88
+ const pluginsRegistration = {
89
+ [name]: index_1.default,
90
+ };
91
+ if (Object.hasOwn(config, "plugins")) {
92
+ throw new Error("The 'plugins' field is managed by createConfig and should not be provided in the config argument.");
93
+ }
94
+ if (Object.hasOwn(config, "settings")) {
95
+ const settings = config.settings;
96
+ if (settings) {
97
+ for (const key of Object.keys(settings)) {
98
+ if (!(0, Settings_1.isSettingsKey)(key)) {
99
+ throw new Error(`Invalid settings key "${key}". When using createConfig, all settings keys must belong to eslint-plugin-boundaries.`);
100
+ }
101
+ }
102
+ }
103
+ }
104
+ return {
105
+ files: [
106
+ "**/*.js",
107
+ "**/*.jsx",
108
+ "**/*.ts",
109
+ "**/*.tsx",
110
+ "**/*.mjs",
111
+ "**/*.cjs",
112
+ ],
113
+ ...config,
114
+ plugins: pluginsRegistration,
115
+ rules: renamePluginRules(name, config.rules),
116
+ };
117
+ }
118
+ exports.recommended = Recommended_1.default;
119
+ exports.strict = Strict_1.default;
@@ -0,0 +1,10 @@
1
+ import type { Config } from "../Settings";
2
+ /**
3
+ * Recommended configuration for eslint-plugin-boundaries.
4
+ *
5
+ * It is recommended for applying the plugin to an already existing project.
6
+ * Rules `boundaries/no-unknown`, `boundaries/no-unknown-files` and `boundaries/no-ignored` are disabled,
7
+ * so it allows to have parts of the project non-compliant with defined rules, allowing to refactor the code progressively.
8
+ */
9
+ declare const config: Config;
10
+ export default config;
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const Settings_1 = require("../Settings");
4
+ const { ELEMENTS,
5
+ // rules
6
+ RULE_ELEMENT_TYPES, RULE_ENTRY_POINT, RULE_EXTERNAL, RULE_NO_IGNORED, RULE_NO_PRIVATE, RULE_NO_UNKNOWN_FILES, RULE_NO_UNKNOWN, } = Settings_1.SETTINGS;
7
+ // TODO In next major version: Export also files, plugin, etc.
8
+ /**
9
+ * Recommended configuration for eslint-plugin-boundaries.
10
+ *
11
+ * It is recommended for applying the plugin to an already existing project.
12
+ * Rules `boundaries/no-unknown`, `boundaries/no-unknown-files` and `boundaries/no-ignored` are disabled,
13
+ * so it allows to have parts of the project non-compliant with defined rules, allowing to refactor the code progressively.
14
+ */
15
+ const config = {
16
+ rules: {
17
+ [RULE_ELEMENT_TYPES]: [2],
18
+ [RULE_ENTRY_POINT]: [2],
19
+ [RULE_EXTERNAL]: [2],
20
+ [RULE_NO_IGNORED]: 0,
21
+ [RULE_NO_PRIVATE]: [
22
+ 2,
23
+ {
24
+ allowUncles: true,
25
+ },
26
+ ],
27
+ [RULE_NO_UNKNOWN_FILES]: 0,
28
+ [RULE_NO_UNKNOWN]: 0,
29
+ },
30
+ settings: {
31
+ [ELEMENTS]: [],
32
+ },
33
+ };
34
+ exports.default = config;
35
+ // For CommonJS compatibility
36
+ module.exports = config;
@@ -0,0 +1,8 @@
1
+ import type { Config } from "../Settings";
2
+ /**
3
+ * Strict configuration for eslint-plugin-boundaries.
4
+ *
5
+ * It enables all rules, enforcing full compliance with defined boundaries. Unknown files and importing ignored files are not allowed.
6
+ */
7
+ declare const config: Config;
8
+ export default config;
@@ -0,0 +1,26 @@
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
+ const Settings_1 = require("../Settings");
7
+ const Recommended_1 = __importDefault(require("./Recommended"));
8
+ const { RULE_NO_IGNORED, RULE_NO_UNKNOWN_FILES, RULE_NO_UNKNOWN } = Settings_1.SETTINGS;
9
+ // TODO In next major version: Export also files, plugin, etc.
10
+ /**
11
+ * Strict configuration for eslint-plugin-boundaries.
12
+ *
13
+ * It enables all rules, enforcing full compliance with defined boundaries. Unknown files and importing ignored files are not allowed.
14
+ */
15
+ const config = {
16
+ ...Recommended_1.default,
17
+ rules: {
18
+ ...Recommended_1.default.rules,
19
+ [RULE_NO_IGNORED]: 2,
20
+ [RULE_NO_UNKNOWN_FILES]: 2,
21
+ [RULE_NO_UNKNOWN]: 2,
22
+ },
23
+ };
24
+ exports.default = config;
25
+ // For CommonJS compatibility
26
+ module.exports = config;
@@ -0,0 +1,43 @@
1
+ import type { Matcher, DependencyDescription, DependencyKind, ElementDescription } from "@boundaries/elements";
2
+ import type { Rule } from "eslint";
3
+ import type { SettingsNormalized } from "../Settings";
4
+ import type { EslintLiteralNode } from "./Elements.types";
5
+ /**
6
+ * Returns the elements matcher based on the ESLint rule context, filtering out invalid descriptors
7
+ * @param context The ESLint rule context
8
+ * @returns The elements matcher
9
+ */
10
+ export declare function getElementsMatcher(settings: SettingsNormalized): Matcher;
11
+ /**
12
+ * Returns the specifiers used in an import or export statement
13
+ * @param node The AST node representing the import or export
14
+ * @returns The list of specifiers used in the import or export
15
+ */
16
+ export declare function getSpecifiers(node: Rule.Node): string[];
17
+ /**
18
+ * Returns the description of the current file being linted
19
+ * @param fileName The file name
20
+ * @param settings The ESLint rule context settings normalized
21
+ * @returns The description of the current file being linted
22
+ */
23
+ export declare function elementDescription(fileName: string, settings: SettingsNormalized): ElementDescription;
24
+ /**
25
+ * Returns the description of a dependency node
26
+ * @param param0 The dependency node info
27
+ * @param context The ESLint rule context
28
+ * @returns The description of the dependency node
29
+ */
30
+ export declare function dependencyDescription({ node, kind, nodeKind, }: {
31
+ /** The dependency node */
32
+ node: EslintLiteralNode;
33
+ /** The kind of the dependency */
34
+ kind: DependencyKind;
35
+ /** The kind of the node generating the dependency */
36
+ nodeKind?: string;
37
+ },
38
+ /** The file name */
39
+ fileName: string,
40
+ /** The ESLint rule context settings normalized */
41
+ settings: SettingsNormalized,
42
+ /** The ESLint rule context */
43
+ context: Rule.RuleContext): DependencyDescription;
@@ -0,0 +1,107 @@
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.getElementsMatcher = getElementsMatcher;
7
+ exports.getSpecifiers = getSpecifiers;
8
+ exports.elementDescription = elementDescription;
9
+ exports.dependencyDescription = dependencyDescription;
10
+ const elements_1 = require("@boundaries/elements");
11
+ const resolve_1 = __importDefault(require("eslint-module-utils/resolve"));
12
+ const Support_1 = require("../Support");
13
+ const elements = new elements_1.Elements();
14
+ /**
15
+ * Returns the elements matcher based on the ESLint rule context, filtering out invalid descriptors
16
+ * @param context The ESLint rule context
17
+ * @returns The elements matcher
18
+ */
19
+ function getElementsMatcher(settings) {
20
+ const elementsMatcher = elements.getMatcher(settings.elementDescriptors, {
21
+ ignorePaths: settings.ignorePaths,
22
+ includePaths: settings.includePaths,
23
+ legacyTemplates: settings.legacyTemplates,
24
+ });
25
+ return elementsMatcher;
26
+ }
27
+ /**
28
+ * Replaces backslashes with forward slashes in a given path
29
+ * @param filePath The file path to modify
30
+ * @returns The modified file path with forward slashes
31
+ */
32
+ function replacePathSlashes(filePath) {
33
+ return filePath.replaceAll("\\", "/");
34
+ }
35
+ /**
36
+ * Transforms an absolute path into a project-relative path
37
+ * @param absolutePath The absolute path to transform
38
+ * @param rootPath The root path of the project
39
+ * @returns The relative path from the project root
40
+ */
41
+ function projectPath(absolutePath, rootPath) {
42
+ if (absolutePath) {
43
+ // TODO: Use path.relative when possible. With caution because this would break current external paths
44
+ return replacePathSlashes(absolutePath).replace(`${replacePathSlashes(rootPath)}/`, "");
45
+ }
46
+ return "";
47
+ }
48
+ /**
49
+ * Returns the specifiers used in an import or export statement
50
+ * @param node The AST node representing the import or export
51
+ * @returns The list of specifiers used in the import or export
52
+ */
53
+ function getSpecifiers(node) {
54
+ if (node.parent.type === "ImportDeclaration") {
55
+ return node.parent.specifiers
56
+ .filter((specifier) => specifier.type === "ImportSpecifier" &&
57
+ specifier.imported &&
58
+ specifier.imported.name)
59
+ .map((specifier) => specifier.imported.name);
60
+ }
61
+ if (node.parent.type === "ExportNamedDeclaration") {
62
+ return node.parent.specifiers
63
+ .filter((specifier) => specifier.type === "ExportSpecifier" &&
64
+ specifier.exported.name)
65
+ .map((specifier) => specifier.exported.name);
66
+ }
67
+ return [];
68
+ }
69
+ /**
70
+ * Returns the description of the current file being linted
71
+ * @param fileName The file name
72
+ * @param settings The ESLint rule context settings normalized
73
+ * @returns The description of the current file being linted
74
+ */
75
+ function elementDescription(fileName, settings) {
76
+ const matcher = getElementsMatcher(settings);
77
+ const path = projectPath(fileName, settings.rootPath);
78
+ const result = matcher.describeElement(path);
79
+ (0, Support_1.debugDescription)(result);
80
+ return result;
81
+ }
82
+ /**
83
+ * Returns the description of a dependency node
84
+ * @param param0 The dependency node info
85
+ * @param context The ESLint rule context
86
+ * @returns The description of the dependency node
87
+ */
88
+ function dependencyDescription({ node, kind, nodeKind, },
89
+ /** The file name */
90
+ fileName,
91
+ /** The ESLint rule context settings normalized */
92
+ settings,
93
+ /** The ESLint rule context */
94
+ context) {
95
+ const source = String(node.value);
96
+ const matcher = getElementsMatcher(settings);
97
+ const description = matcher.describeDependency({
98
+ from: projectPath(fileName, settings.rootPath),
99
+ to: projectPath((0, resolve_1.default)(source, context), settings.rootPath),
100
+ source,
101
+ kind: kind || "value", // TODO: Change by runtime in a backwards compatible way
102
+ nodeKind,
103
+ specifiers: getSpecifiers(node),
104
+ });
105
+ (0, Support_1.debugDescription)(description);
106
+ return description;
107
+ }
@@ -0,0 +1,5 @@
1
+ import type { Rule } from "eslint";
2
+ import type { Literal } from "estree";
3
+ export type EslintLiteralNode = Literal & {
4
+ parent: Rule.Node;
5
+ };
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,2 @@
1
+ export * from "./Elements.types";
2
+ export * from "./Elements";
@@ -0,0 +1,18 @@
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("./Elements.types"), exports);
18
+ __exportStar(require("./Elements"), exports);
@@ -0,0 +1,14 @@
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;
14
+ }): string;
@@ -0,0 +1,204 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.replaceObjectValuesInTemplates = replaceObjectValuesInTemplates;
4
+ exports.replaceObjectValuesInTemplate = replaceObjectValuesInTemplate;
5
+ exports.quote = quote;
6
+ exports.micromatchPatternReplacingObjectsValues = micromatchPatternReplacingObjectsValues;
7
+ exports.ruleElementMessage = ruleElementMessage;
8
+ exports.customErrorMessage = customErrorMessage;
9
+ exports.elementMessage = elementMessage;
10
+ exports.dependencyImportKindMessage = dependencyImportKindMessage;
11
+ exports.dependencyUsageKindMessage = dependencyUsageKindMessage;
12
+ const elements_1 = require("@boundaries/elements");
13
+ const Support_1 = require("../Support");
14
+ function replaceObjectValueInTemplate(template, key, value, namespace) {
15
+ const keyToReplace = namespace ? `${namespace}.${key}` : key;
16
+ const regexp = new RegExp(`\\$\\{${keyToReplace}\\}`, "g");
17
+ return template.replace(regexp, value);
18
+ }
19
+ function replaceObjectValuesInTemplates(strings, object, namespace) {
20
+ const finalResult = (0, Support_1.isArray)(strings) ? [...strings] : strings;
21
+ return Object.keys(object).reduce((result, objectKey) => {
22
+ // If template is an array, replace key by value in all patterns
23
+ if ((0, Support_1.isArray)(result)) {
24
+ return result.map((resultEntry) => {
25
+ return replaceObjectValueInTemplate(resultEntry, objectKey, object[objectKey], namespace);
26
+ });
27
+ }
28
+ return replaceObjectValueInTemplate(result, objectKey, object[objectKey], namespace);
29
+ }, finalResult);
30
+ }
31
+ function replaceObjectValuesInTemplate(template, object, namespace) {
32
+ return replaceObjectValuesInTemplates(template, object, namespace);
33
+ }
34
+ function quote(str) {
35
+ return `'${str || ""}'`;
36
+ }
37
+ function typeMessage(elementMatcher) {
38
+ return `elements of type ${quote(elementMatcher)}`;
39
+ }
40
+ function categoryMessage(category) {
41
+ return `category ${quote(category)}`;
42
+ }
43
+ function propertiesConcatenator(properties, index) {
44
+ if (properties.length > 1 && index === properties.length - 1) {
45
+ return " and";
46
+ }
47
+ if (index === 0) {
48
+ return " with";
49
+ }
50
+ return ",";
51
+ }
52
+ function micromatchPatternReplacingObjectsValues(pattern, object) {
53
+ let patternToReplace = pattern;
54
+ if (!patternToReplace) {
55
+ return "";
56
+ }
57
+ // Backward compatibility. Possibly unused, because the value is already replaced in the next step.
58
+ // For the moment, keep it to avoid unexpected issues until the oncoming refactor.
59
+ if (object.from) {
60
+ patternToReplace = replaceObjectValuesInTemplates(patternToReplace, object.from);
61
+ }
62
+ return Object.keys(object).reduce((replacedPattern, namespace) => {
63
+ if (!object[namespace]) {
64
+ return replacedPattern;
65
+ }
66
+ return replaceObjectValuesInTemplates(replacedPattern, object[namespace] || {}, namespace);
67
+ }, patternToReplace);
68
+ }
69
+ function micromatchPatternMessage(micromatchPatterns, elementCapturedValues) {
70
+ const micromatchPatternsWithValues = micromatchPatternReplacingObjectsValues(micromatchPatterns, { from: elementCapturedValues || {} });
71
+ if ((0, Support_1.isArray)(micromatchPatternsWithValues)) {
72
+ if (micromatchPatternsWithValues.length === 1) {
73
+ return quote(micromatchPatternsWithValues[0]);
74
+ }
75
+ return micromatchPatternsWithValues.reduce((message, micromatchPattern, index) => {
76
+ if (index === 0) {
77
+ return quote(micromatchPattern);
78
+ }
79
+ if (index === micromatchPatternsWithValues.length - 1) {
80
+ return `${message} or ${quote(micromatchPattern)}`;
81
+ }
82
+ return `${message}, ${quote(micromatchPattern)}`;
83
+ }, "");
84
+ }
85
+ return quote(micromatchPatternsWithValues);
86
+ }
87
+ function capturedValuesMatcherMessage(capturedValuesPattern, elementCapturedValues) {
88
+ const capturedValuesPatternKeys = Object.keys(capturedValuesPattern || {});
89
+ return capturedValuesPatternKeys
90
+ .map((key) => {
91
+ return [key, capturedValuesPattern?.[key]];
92
+ })
93
+ .reduce((message, propertyNameAndMatcher, index) => {
94
+ return `${message}${propertiesConcatenator(capturedValuesPatternKeys, index)} ${propertyNameAndMatcher[0]
95
+ // TODO: Support array patterns
96
+ } ${micromatchPatternMessage(propertyNameAndMatcher[1], elementCapturedValues)}`;
97
+ }, "");
98
+ }
99
+ function elementMatcherMessage(elementMatcher, elementCapturedValues) {
100
+ if (!elementMatcher) {
101
+ return "";
102
+ }
103
+ if ((0, elements_1.isElementSelector)(elementMatcher)) {
104
+ const selector = (0, elements_1.normalizeElementsSelector)(elementMatcher);
105
+ const parts = [];
106
+ const toAdd = [];
107
+ if (selector[0].type) {
108
+ // @ts-expect-error Types have to be aligned properly
109
+ toAdd.push(typeMessage(selector[0].type));
110
+ }
111
+ if (selector[0].category) {
112
+ toAdd.push(propertiesConcatenator(parts, parts.length + toAdd.length + 1),
113
+ // @ts-expect-error Types have to be aligned properly
114
+ categoryMessage(selector[0].category));
115
+ }
116
+ if (selector[0].captured) {
117
+ toAdd.push(capturedValuesMatcherMessage(selector[0].captured, elementCapturedValues));
118
+ }
119
+ parts.push(...toAdd);
120
+ return parts.map((part) => part.trim()).join(" ");
121
+ }
122
+ // Backward compatibility. Code should not reach here normally.
123
+ if ((0, Support_1.isString)(elementMatcher)) {
124
+ return typeMessage(elementMatcher);
125
+ }
126
+ // TODO: Support array patterns
127
+ return `${typeMessage(elementMatcher[0])}${capturedValuesMatcherMessage(elementMatcher[1], elementCapturedValues)}`;
128
+ }
129
+ function ruleElementMessage(elementPatterns, elementCapturedValues) {
130
+ if ((0, Support_1.isArray)(elementPatterns)) {
131
+ if (elementPatterns.length === 1) {
132
+ return elementMatcherMessage(elementPatterns[0], elementCapturedValues);
133
+ }
134
+ return elementPatterns.reduce((message, elementPattern, index) => {
135
+ if (index === 0) {
136
+ return elementMatcherMessage(elementPattern, elementCapturedValues);
137
+ }
138
+ return `${message}, or ${elementMatcherMessage(elementPattern, elementCapturedValues)}`;
139
+ }, "");
140
+ }
141
+ return elementMatcherMessage(elementPatterns, elementCapturedValues);
142
+ }
143
+ function elementPropertiesToReplaceInTemplate(element, importKind) {
144
+ if ((0, elements_1.isElementDescription)(element)) {
145
+ return {
146
+ ...element.captured,
147
+ type: element.type || "",
148
+ internalPath: element.internalPath || "",
149
+ source: element.source || "",
150
+ importKind: importKind || "",
151
+ };
152
+ }
153
+ return {
154
+ ...element.captured,
155
+ type: element.type || "",
156
+ internalPath: "",
157
+ source: "",
158
+ importKind: importKind || "",
159
+ };
160
+ }
161
+ function customErrorMessage(message, dependency, report = {}) {
162
+ let replacedMessage = replaceObjectValuesInTemplate(replaceObjectValuesInTemplate(message, elementPropertiesToReplaceInTemplate(dependency.from, dependency.dependency.kind), "file"), elementPropertiesToReplaceInTemplate(dependency.to, dependency.dependency.kind), "dependency");
163
+ replacedMessage = replaceObjectValuesInTemplate(replaceObjectValuesInTemplate(replacedMessage, elementPropertiesToReplaceInTemplate(dependency.from, dependency.dependency.kind), "from"), elementPropertiesToReplaceInTemplate(dependency.to, dependency.dependency.kind), "target");
164
+ if (dependency.from.parents?.[0]) {
165
+ replacedMessage = replaceObjectValuesInTemplate(replacedMessage, elementPropertiesToReplaceInTemplate(dependency.from.parents?.[0], dependency.dependency.kind), "file.parent");
166
+ replacedMessage = replaceObjectValuesInTemplate(replacedMessage, elementPropertiesToReplaceInTemplate(dependency.from.parents?.[0], dependency.dependency.kind), "from.parent");
167
+ }
168
+ if (dependency.to.parents?.[0]) {
169
+ replacedMessage = replaceObjectValuesInTemplate(replacedMessage, elementPropertiesToReplaceInTemplate(dependency.to.parents?.[0], dependency.dependency.kind), "dependency.parent");
170
+ replacedMessage = replaceObjectValuesInTemplate(replacedMessage, elementPropertiesToReplaceInTemplate(dependency.to.parents?.[0], dependency.dependency.kind), "target.parent");
171
+ }
172
+ return replaceObjectValuesInTemplate(replacedMessage, report, "report");
173
+ }
174
+ function elementCapturedValuesMessage(capturedValues) {
175
+ if (!capturedValues) {
176
+ return "";
177
+ }
178
+ const capturedValuesKeys = Object.keys(capturedValues);
179
+ return capturedValuesKeys
180
+ .map((key) => {
181
+ return [key, capturedValues[key]];
182
+ })
183
+ .reduce((message, propertyNameAndValue, index) => {
184
+ return `${message}${propertiesConcatenator(capturedValuesKeys, index)} ${propertyNameAndValue[0]} ${quote(propertyNameAndValue[1])}`;
185
+ }, "");
186
+ }
187
+ function elementMessage(elementInfo) {
188
+ return `of type ${quote(elementInfo.type)}${elementCapturedValuesMessage(elementInfo.captured)}`;
189
+ }
190
+ function hasToPrintKindMessage(ruleImportKind, dependency) {
191
+ return ruleImportKind && dependency.dependency.kind;
192
+ }
193
+ function dependencyImportKindMessage(ruleImportKind, dependency) {
194
+ if (hasToPrintKindMessage(ruleImportKind, dependency)) {
195
+ return `kind ${quote(dependency.dependency.kind)} from `;
196
+ }
197
+ return "";
198
+ }
199
+ function dependencyUsageKindMessage(ruleImportKind, dependency, { suffix = " ", prefix = "", } = {}) {
200
+ if (hasToPrintKindMessage(ruleImportKind, dependency)) {
201
+ return `${prefix}${dependency.dependency.kind}${suffix}`;
202
+ }
203
+ return "";
204
+ }
@@ -0,0 +1 @@
1
+ export * from "./Messages";