eslint-plugin-boundaries 2.4.2 → 2.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +45 -10
- package/package.json +12 -12
- package/src/core/cache.js +0 -4
- package/src/core/elementsInfo.js +2 -3
- package/src/helpers/messages.js +117 -0
- package/src/helpers/rules.js +41 -12
- package/src/helpers/settings.js +2 -1
- package/src/helpers/utils.js +30 -0
- package/src/helpers/validations.js +20 -11
- package/src/rules/element-types.js +34 -14
- package/src/rules/entry-point.js +29 -12
- package/src/rules/no-private.js +2 -2
- package/src/rules-factories/dependency-rule.js +2 -2
- package/CHANGELOG.md +0 -208
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[![Build status][build-image]][build-url] [![Coverage Status][coveralls-image]][coveralls-url] [![Quality Gate][quality-gate-image]][quality-gate-url]
|
|
2
2
|
|
|
3
|
-
[](https://renovatebot.com) [![Last commit][last-commit-image]][last-commit-url] [![Last release][release-image]][release-url]
|
|
4
4
|
|
|
5
5
|
[![NPM downloads][npm-downloads-image]][npm-downloads-url] [![License][license-image]][license-url]
|
|
6
6
|
|
|
@@ -29,6 +29,7 @@ __This plugin ensures that your architecture boundaries are respected by the ele
|
|
|
29
29
|
* [Rules configuration](#rules-configuration)
|
|
30
30
|
* [Main format of rules options](#main-format-of-rules-options)
|
|
31
31
|
* [Elements matchers](#elements-matchers)
|
|
32
|
+
* [Error messages](#error-messages)
|
|
32
33
|
* [Advanced example](#advanced-example)
|
|
33
34
|
- [Resolvers](#resolvers)
|
|
34
35
|
- [Usage with TypeScript](#usage-with-typescript)
|
|
@@ -199,7 +200,7 @@ Define patterns to recognize each file in the project as one of this element typ
|
|
|
199
200
|
}
|
|
200
201
|
```
|
|
201
202
|
|
|
202
|
-
> Tip: You can enable the [debug mode](debug-mode) when configuring the plugin, and you will get information about the type assigned to each file in the project.
|
|
203
|
+
> Tip: You can enable the [debug mode](#debug-mode) when configuring the plugin, and you will get information about the type assigned to each file in the project, as well as captured properties and values.
|
|
203
204
|
|
|
204
205
|
#### __`boundaries/include`__
|
|
205
206
|
|
|
@@ -258,23 +259,31 @@ Some rules require extra configuration, and it has to be defined in each specifi
|
|
|
258
259
|
|
|
259
260
|
#### Main format of rules options
|
|
260
261
|
|
|
261
|
-
The docs of each rule contains an specification of their own options, but
|
|
262
|
+
The docs of each rule contains an specification of their own options, but __the main rules share the format in which the options have to be defined__. The format described here is valid for options of [`element-types`](docs/rules/element-types.md), [`external`](docs/rules/external.md) and [`entry-point`](docs/rules/entry-point.md) rules, __except the `message` property, which for the moment is only supported in the [`element-types`](docs/rules/element-types.md) and [`entry-point`](docs/rules/entry-point.md) rules settings.
|
|
262
263
|
|
|
263
264
|
Options set an "allow/disallow" value by default, and provide an array of rules. Each matching rule will override the default value and the value returned by previous matching rules. So, the final result of the options, once processed for each case, will be "allow" or "disallow", and this value will be applied by the plugin rule in the correspondant way, making it to produce an eslint error or not.
|
|
264
265
|
|
|
265
|
-
```
|
|
266
|
+
```jsonc
|
|
266
267
|
{
|
|
267
268
|
"rules": {
|
|
268
269
|
"boundaries/element-types": [2, {
|
|
270
|
+
// Allow or disallow any dependency by default
|
|
269
271
|
"default": "allow",
|
|
272
|
+
// Define a custom message for this rule
|
|
273
|
+
"message": "${file.type} is not allowed to import ${dependency.type}",
|
|
270
274
|
"rules": [
|
|
271
275
|
{
|
|
276
|
+
// In this type of files...
|
|
272
277
|
"from": ["helpers"],
|
|
273
|
-
|
|
278
|
+
// ...disallow importing this type of elements
|
|
279
|
+
"disallow": ["modules", "components"],
|
|
280
|
+
// ...and return this custom error message
|
|
281
|
+
"message": "Helpers must not import other thing than helpers"
|
|
274
282
|
},
|
|
275
283
|
{
|
|
276
284
|
"from": ["components"],
|
|
277
285
|
"disallow": ["modules"]
|
|
286
|
+
// As this rule has not "message" property, it will use the message defined at first level
|
|
278
287
|
}
|
|
279
288
|
]
|
|
280
289
|
}]
|
|
@@ -291,8 +300,9 @@ Remember that:
|
|
|
291
300
|
|
|
292
301
|
* __`from/target`__: `<element matchers>` Depending of the rule to which the options are for, the rule will be applied only if the file being analized matches with this element matcher (`from`), or the dependency being imported matches with this element matcher (`target`).
|
|
293
302
|
* __`disallow/allow`__: `<value matchers>` If the plugin rule target matches with this, then the result of the rule will be "disallow/allow". Each rule will require a type of value here depending of what it is checking. In the case of the `element-types` rule, for example, another `<element matcher>` has to be provided in order to check the type of the local dependency.
|
|
303
|
+
* __`message`__: `<string>` Optional. If the rule results in an error, the plugin will return this message instead of the default one. Read [error messages](#error-messages) for further info.
|
|
294
304
|
|
|
295
|
-
> Tip:
|
|
305
|
+
> Tip: Properties `from/target` and `disallow/allow` can receive a single matcher, or an array of matchers.
|
|
296
306
|
|
|
297
307
|
##### Elements matchers
|
|
298
308
|
|
|
@@ -303,6 +313,29 @@ Elements matchers used in the rules options can have the next formats:
|
|
|
303
313
|
* `["helpers", { category: "data", elementName: "parsers"}]`: Will only match with helpers with category "data" and elementName "parsers" (`helpers/data/parsers.js`).
|
|
304
314
|
* `["helpers", { category: "data" }]`: Will match with all helpers with category "data" (`helpers/data/*.js`)
|
|
305
315
|
|
|
316
|
+
##### Error messages
|
|
317
|
+
|
|
318
|
+
The plugin returns a different default message for each rule, check the documentation of each one for further info. But some rules support defining custom messages in their configuration, as seen in ["Main format of rules options"](#main-format-of-rules-options).
|
|
319
|
+
|
|
320
|
+
When defining custom messages, it is possible to provide information about the current file or dependency. Use `${file.PROPERTY}` or `${dependency.PROPERTY}`, and it will be replaced by the correspondent captured value from the file or the dependency:
|
|
321
|
+
|
|
322
|
+
```jsonc
|
|
323
|
+
{
|
|
324
|
+
"message": "${file.type}s of category ${file.category} are not allowed to import ${dependency.category}s"
|
|
325
|
+
// If the error was produced by a file with type "component" and captured value "category" being "atom", trying to import a dependency with category "molecule", the message would be:
|
|
326
|
+
// "components of category atom are not allowed to import molecules"
|
|
327
|
+
}
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
Available properties in error templates both from `file` or `dependency` are:
|
|
331
|
+
|
|
332
|
+
* `type`: Element's type.
|
|
333
|
+
* `internalPath`: File path being analyzed or imported. Relative to the element's root path.
|
|
334
|
+
* ...All captured properties are also available
|
|
335
|
+
|
|
336
|
+
|
|
337
|
+
> Tip: Read ["Global settings"](#global-settings) for further info about how to capture values from elements.
|
|
338
|
+
|
|
306
339
|
##### Advanced example of a rule configuration
|
|
307
340
|
|
|
308
341
|
Just to illustrate the high level of customization that the plugin supports, here is an example of advanced options for the `boundaries/element-types` rule based on the previous global `elements` settings example:
|
|
@@ -343,7 +376,9 @@ Just to illustrate the high level of customization that the plugin supports, her
|
|
|
343
376
|
"disallow": [
|
|
344
377
|
// disallow importing helpers with captured category "data"
|
|
345
378
|
["helpers", { "category": "data" }]
|
|
346
|
-
]
|
|
379
|
+
],
|
|
380
|
+
// Custom message only for this specific error
|
|
381
|
+
"message": "Atom components can't import data helpers"
|
|
347
382
|
},
|
|
348
383
|
{
|
|
349
384
|
// when file is inside a module
|
|
@@ -360,7 +395,9 @@ Just to illustrate the high level of customization that the plugin supports, her
|
|
|
360
395
|
"disallow": [
|
|
361
396
|
// disallow importing any type of component not being of family layout
|
|
362
397
|
["components", { "family": "!layout" }]
|
|
363
|
-
]
|
|
398
|
+
],
|
|
399
|
+
// Custom message only for this specific error
|
|
400
|
+
"message": "Modules with name starting by 'page-' can't import not layout components. You tried to import a component of family ${dependency.family} from a module with name ${file.elementName}"
|
|
364
401
|
}
|
|
365
402
|
]
|
|
366
403
|
}]
|
|
@@ -456,8 +493,6 @@ MIT, see [LICENSE](./LICENSE) for details.
|
|
|
456
493
|
[license-url]: https://github.com/javierbrea/eslint-plugin-boundaries/blob/master/LICENSE
|
|
457
494
|
[npm-downloads-image]: https://img.shields.io/npm/dm/eslint-plugin-boundaries.svg
|
|
458
495
|
[npm-downloads-url]: https://www.npmjs.com/package/eslint-plugin-boundaries
|
|
459
|
-
[npm-dependencies-image]: https://img.shields.io/david/javierbrea/eslint-plugin-boundaries.svg
|
|
460
|
-
[npm-dependencies-url]: https://david-dm.org/javierbrea/eslint-plugin-boundaries
|
|
461
496
|
[quality-gate-image]: https://sonarcloud.io/api/project_badges/measure?project=javierbrea_eslint-plugin-boundaries&metric=alert_status
|
|
462
497
|
[quality-gate-url]: https://sonarcloud.io/dashboard?id=javierbrea_eslint-plugin-boundaries
|
|
463
498
|
[release-image]: https://img.shields.io/github/release-date/javierbrea/eslint-plugin-boundaries.svg
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-plugin-boundaries",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.7.0",
|
|
4
4
|
"description": "Eslint plugin checking architecture boundaries between elements",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"eslint",
|
|
@@ -28,25 +28,25 @@
|
|
|
28
28
|
"prepare": "is-ci || husky install"
|
|
29
29
|
},
|
|
30
30
|
"peerDependencies": {
|
|
31
|
-
"eslint": "
|
|
31
|
+
"eslint": ">=6.0.0"
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
34
|
"eslint-import-resolver-node": "0.3.6",
|
|
35
|
-
"eslint-module-utils": "2.
|
|
35
|
+
"eslint-module-utils": "2.7.1",
|
|
36
36
|
"chalk": "4.1.2",
|
|
37
|
-
"is-core-module": "2.
|
|
37
|
+
"is-core-module": "2.8.0",
|
|
38
38
|
"micromatch": "4.0.4"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
41
|
"cross-env": "7.0.3",
|
|
42
|
-
"eslint": "
|
|
42
|
+
"eslint": "8.3.0",
|
|
43
43
|
"eslint-config-prettier": "8.3.0",
|
|
44
|
-
"eslint-plugin-prettier": "
|
|
45
|
-
"husky": "7.0.
|
|
46
|
-
"is-ci": "3.0.
|
|
47
|
-
"jest": "27.
|
|
48
|
-
"lint-staged": "
|
|
49
|
-
"prettier": "2.
|
|
44
|
+
"eslint-plugin-prettier": "4.0.0",
|
|
45
|
+
"husky": "7.0.4",
|
|
46
|
+
"is-ci": "3.0.1",
|
|
47
|
+
"jest": "27.3.1",
|
|
48
|
+
"lint-staged": "12.1.2",
|
|
49
|
+
"prettier": "2.4.1"
|
|
50
50
|
},
|
|
51
51
|
"lint-staged": {
|
|
52
52
|
"test/**/*.js": "eslint",
|
|
@@ -54,6 +54,6 @@
|
|
|
54
54
|
"*.js": "eslint"
|
|
55
55
|
},
|
|
56
56
|
"engines": {
|
|
57
|
-
"node": "
|
|
57
|
+
"node": ">=12.0.0"
|
|
58
58
|
}
|
|
59
59
|
}
|
package/src/core/cache.js
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
const { debug } = require("../helpers/debug");
|
|
2
|
-
|
|
3
1
|
class Cache {
|
|
4
2
|
constructor(name, settings) {
|
|
5
3
|
this._cache = {};
|
|
@@ -13,7 +11,6 @@ class Cache {
|
|
|
13
11
|
|
|
14
12
|
load(key) {
|
|
15
13
|
if (this._cache[key]) {
|
|
16
|
-
debug(`Returning "${key}" ${this._name} info from cache`);
|
|
17
14
|
return this._cache[key];
|
|
18
15
|
}
|
|
19
16
|
|
|
@@ -32,7 +29,6 @@ class CachesManager {
|
|
|
32
29
|
return cacheCandidate._settings === settings;
|
|
33
30
|
});
|
|
34
31
|
if (!cache) {
|
|
35
|
-
debug(`${this._name} cache not found, creating new`);
|
|
36
32
|
cache = new Cache(this._name, settings);
|
|
37
33
|
this._caches.push(cache);
|
|
38
34
|
}
|
package/src/core/elementsInfo.js
CHANGED
|
@@ -5,6 +5,7 @@ const resolve = require("eslint-module-utils/resolve").default;
|
|
|
5
5
|
const { IGNORE, INCLUDE, VALID_MODES } = require("../constants/settings");
|
|
6
6
|
const { getElements } = require("../helpers/settings");
|
|
7
7
|
const { debugFileInfo } = require("../helpers/debug");
|
|
8
|
+
const { isArray } = require("../helpers/utils");
|
|
8
9
|
|
|
9
10
|
const { filesCache, importsCache, elementsCache } = require("./cache");
|
|
10
11
|
|
|
@@ -112,9 +113,7 @@ function elementTypeAndParents(path, settings) {
|
|
|
112
113
|
let elementFound = false;
|
|
113
114
|
getElements(settings).forEach((element) => {
|
|
114
115
|
const typeOfMatch = VALID_MODES.includes(element.mode) ? element.mode : VALID_MODES[0];
|
|
115
|
-
const elementPatterns =
|
|
116
|
-
? element.pattern
|
|
117
|
-
: [element.pattern];
|
|
116
|
+
const elementPatterns = isArray(element.pattern) ? element.pattern : [element.pattern];
|
|
118
117
|
elementPatterns.forEach((elementPattern) => {
|
|
119
118
|
if (!elementFound) {
|
|
120
119
|
const useFullPathMatch = typeOfMatch === VALID_MODES[2] && !elementResult.type;
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
const { isString, isArray, replaceObjectValuesInTemplates } = require("./utils");
|
|
2
|
+
const { micromatchPatternReplacingObjectValues } = require("./rules");
|
|
3
|
+
|
|
4
|
+
function quote(str) {
|
|
5
|
+
return `'${str}'`;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
function typeMessage(elementMatcher) {
|
|
9
|
+
return `elements of type ${quote(elementMatcher)}`;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function propertiesConcater(properties, index) {
|
|
13
|
+
if (properties.length > 1 && index === properties.length - 1) {
|
|
14
|
+
return " and";
|
|
15
|
+
}
|
|
16
|
+
if (index === 0) {
|
|
17
|
+
return " with";
|
|
18
|
+
}
|
|
19
|
+
return ",";
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function micromatchPatternMessage(micromatchPatterns, elementCapturedValues) {
|
|
23
|
+
const micromatchPatternsWithValues = micromatchPatternReplacingObjectValues(
|
|
24
|
+
micromatchPatterns,
|
|
25
|
+
elementCapturedValues
|
|
26
|
+
);
|
|
27
|
+
if (isArray(micromatchPatternsWithValues)) {
|
|
28
|
+
if (micromatchPatternsWithValues.length === 1) {
|
|
29
|
+
return quote(micromatchPatternsWithValues[0]);
|
|
30
|
+
}
|
|
31
|
+
return micromatchPatternsWithValues.reduce((message, micromatchPattern, index) => {
|
|
32
|
+
if (index === 0) {
|
|
33
|
+
return quote(micromatchPattern);
|
|
34
|
+
}
|
|
35
|
+
if (index === micromatchPatternsWithValues.length - 1) {
|
|
36
|
+
return `${message} or ${quote(micromatchPattern)}`;
|
|
37
|
+
}
|
|
38
|
+
return `${message}, ${quote(micromatchPattern)}`;
|
|
39
|
+
}, "");
|
|
40
|
+
}
|
|
41
|
+
return quote(micromatchPatternsWithValues);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function capturedValuesMatcherMessage(capturedValuesPattern, elementCapturedValues) {
|
|
45
|
+
const capturedValuesPatternKeys = Object.keys(capturedValuesPattern);
|
|
46
|
+
return capturedValuesPatternKeys
|
|
47
|
+
.map((key) => {
|
|
48
|
+
return [key, capturedValuesPattern[key]];
|
|
49
|
+
})
|
|
50
|
+
.reduce((message, propertyNameAndMatcher, index) => {
|
|
51
|
+
return `${message}${propertiesConcater(capturedValuesPatternKeys, index)} ${
|
|
52
|
+
propertyNameAndMatcher[0]
|
|
53
|
+
} ${micromatchPatternMessage(propertyNameAndMatcher[1], elementCapturedValues)}`;
|
|
54
|
+
}, "");
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function elementMatcherMessage(elementMatcher, elementCapturedValues) {
|
|
58
|
+
if (isString(elementMatcher)) {
|
|
59
|
+
return typeMessage(elementMatcher);
|
|
60
|
+
}
|
|
61
|
+
return `${typeMessage(elementMatcher[0])}${capturedValuesMatcherMessage(
|
|
62
|
+
elementMatcher[1],
|
|
63
|
+
elementCapturedValues
|
|
64
|
+
)}`;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function ruleElementMessage(elementPatterns, elementCapturedValues) {
|
|
68
|
+
if (isArray(elementPatterns)) {
|
|
69
|
+
if (elementPatterns.length === 1) {
|
|
70
|
+
return elementMatcherMessage(elementPatterns[0], elementCapturedValues);
|
|
71
|
+
}
|
|
72
|
+
return elementPatterns.reduce((message, elementPattern, index) => {
|
|
73
|
+
if (index === 0) {
|
|
74
|
+
return elementMatcherMessage(elementPattern, elementCapturedValues);
|
|
75
|
+
}
|
|
76
|
+
return `${message}, or ${elementMatcherMessage(elementPattern, elementCapturedValues)}`;
|
|
77
|
+
}, "");
|
|
78
|
+
}
|
|
79
|
+
return elementMatcherMessage(elementPatterns, elementCapturedValues);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function customErrorMessage(message, file, dependency) {
|
|
83
|
+
return replaceObjectValuesInTemplates(
|
|
84
|
+
replaceObjectValuesInTemplates(message, { ...file.capturedValues, type: file.type }, "file"),
|
|
85
|
+
{ ...dependency.capturedValues, type: dependency.type, internalPath: dependency.internalPath },
|
|
86
|
+
"dependency"
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function elementCapturedValuesMessage(capturedValues) {
|
|
91
|
+
if (!capturedValues) {
|
|
92
|
+
return "";
|
|
93
|
+
}
|
|
94
|
+
const capturedValuesKeys = Object.keys(capturedValues);
|
|
95
|
+
return capturedValuesKeys
|
|
96
|
+
.map((key) => {
|
|
97
|
+
return [key, capturedValues[key]];
|
|
98
|
+
})
|
|
99
|
+
.reduce((message, propertyNameAndValue, index) => {
|
|
100
|
+
return `${message}${propertiesConcater(capturedValuesKeys, index)} ${
|
|
101
|
+
propertyNameAndValue[0]
|
|
102
|
+
} ${quote(propertyNameAndValue[1])}`;
|
|
103
|
+
}, "");
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function elementMessage(elementInfo) {
|
|
107
|
+
return `of type ${quote(elementInfo.type)}${elementCapturedValuesMessage(
|
|
108
|
+
elementInfo.capturedValues
|
|
109
|
+
)}`;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
module.exports = {
|
|
113
|
+
quote,
|
|
114
|
+
ruleElementMessage,
|
|
115
|
+
customErrorMessage,
|
|
116
|
+
elementMessage,
|
|
117
|
+
};
|
package/src/helpers/rules.js
CHANGED
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
const micromatch = require("micromatch");
|
|
2
2
|
|
|
3
|
+
const { isArray, replaceObjectValuesInTemplates } = require("./utils");
|
|
4
|
+
|
|
3
5
|
const REPO_URL = "https://github.com/javierbrea/eslint-plugin-boundaries";
|
|
4
6
|
|
|
7
|
+
function removePluginNamespace(ruleName) {
|
|
8
|
+
return ruleName.replace("boundaries/", "");
|
|
9
|
+
}
|
|
10
|
+
|
|
5
11
|
function docsUrl(ruleName) {
|
|
6
|
-
return `${REPO_URL}/blob/master/docs/rules/${ruleName}.md`;
|
|
12
|
+
return `${REPO_URL}/blob/master/docs/rules/${removePluginNamespace(ruleName)}.md`;
|
|
7
13
|
}
|
|
8
14
|
|
|
9
15
|
function meta({ description, schema = [], ruleName }) {
|
|
@@ -39,9 +45,7 @@ function dependencyLocation(node, context) {
|
|
|
39
45
|
}
|
|
40
46
|
|
|
41
47
|
function micromatchPatternReplacingObjectValues(pattern, object) {
|
|
42
|
-
return
|
|
43
|
-
return result.replace(`\${${objectKey}}`, object[objectKey]);
|
|
44
|
-
}, pattern);
|
|
48
|
+
return replaceObjectValuesInTemplates(pattern, object);
|
|
45
49
|
}
|
|
46
50
|
|
|
47
51
|
function isObjectMatch(objectWithMatchers, object, objectWithValuesToReplace) {
|
|
@@ -65,10 +69,10 @@ function rulesMainKey(key) {
|
|
|
65
69
|
|
|
66
70
|
function ruleMatch(ruleMatchers, elementInfo, isMatch, elementToCompare = {}) {
|
|
67
71
|
let match = { result: false, report: null };
|
|
68
|
-
const matchers = !
|
|
72
|
+
const matchers = !isArray(ruleMatchers) ? [ruleMatchers] : ruleMatchers;
|
|
69
73
|
matchers.forEach((matcher) => {
|
|
70
74
|
if (!match.result) {
|
|
71
|
-
if (
|
|
75
|
+
if (isArray(matcher)) {
|
|
72
76
|
const [value, captures] = matcher;
|
|
73
77
|
match = isMatch(elementInfo, value, captures, elementToCompare.capturedValues);
|
|
74
78
|
} else {
|
|
@@ -106,9 +110,16 @@ function getElementRules(elementInfo, options, mainKey) {
|
|
|
106
110
|
return [];
|
|
107
111
|
}
|
|
108
112
|
const key = rulesMainKey(mainKey);
|
|
109
|
-
return options.rules
|
|
110
|
-
|
|
111
|
-
|
|
113
|
+
return options.rules
|
|
114
|
+
.map((rule, index) => {
|
|
115
|
+
return {
|
|
116
|
+
...rule,
|
|
117
|
+
index,
|
|
118
|
+
};
|
|
119
|
+
})
|
|
120
|
+
.filter((rule) => {
|
|
121
|
+
return ruleMatch(rule[key], elementInfo, isMatchElementType).result;
|
|
122
|
+
});
|
|
112
123
|
}
|
|
113
124
|
|
|
114
125
|
function elementRulesAllowDependency({
|
|
@@ -118,12 +129,21 @@ function elementRulesAllowDependency({
|
|
|
118
129
|
isMatch,
|
|
119
130
|
rulesMainKey: mainKey,
|
|
120
131
|
}) {
|
|
121
|
-
const [result, report] = getElementRules(element, options, mainKey).reduce(
|
|
132
|
+
const [result, report, ruleReport] = getElementRules(element, options, mainKey).reduce(
|
|
122
133
|
(allowed, rule) => {
|
|
123
134
|
if (rule.disallow) {
|
|
124
135
|
const match = ruleMatch(rule.disallow, dependency, isMatch, element);
|
|
125
136
|
if (match.result) {
|
|
126
|
-
return [
|
|
137
|
+
return [
|
|
138
|
+
false,
|
|
139
|
+
match.report,
|
|
140
|
+
{
|
|
141
|
+
element: rule[rulesMainKey(mainKey)],
|
|
142
|
+
disallow: rule.disallow,
|
|
143
|
+
index: rule.index,
|
|
144
|
+
message: rule.message || options.message,
|
|
145
|
+
},
|
|
146
|
+
];
|
|
127
147
|
}
|
|
128
148
|
}
|
|
129
149
|
if (rule.allow) {
|
|
@@ -134,11 +154,19 @@ function elementRulesAllowDependency({
|
|
|
134
154
|
}
|
|
135
155
|
return allowed;
|
|
136
156
|
},
|
|
137
|
-
[
|
|
157
|
+
[
|
|
158
|
+
options.default === "allow",
|
|
159
|
+
null,
|
|
160
|
+
{
|
|
161
|
+
isDefault: true,
|
|
162
|
+
message: options.message,
|
|
163
|
+
},
|
|
164
|
+
]
|
|
138
165
|
);
|
|
139
166
|
return {
|
|
140
167
|
result,
|
|
141
168
|
report,
|
|
169
|
+
ruleReport,
|
|
142
170
|
};
|
|
143
171
|
}
|
|
144
172
|
|
|
@@ -151,4 +179,5 @@ module.exports = {
|
|
|
151
179
|
elementRulesAllowDependency,
|
|
152
180
|
getElementRules,
|
|
153
181
|
rulesMainKey,
|
|
182
|
+
micromatchPatternReplacingObjectValues,
|
|
154
183
|
};
|
package/src/helpers/settings.js
CHANGED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
function isString(object) {
|
|
2
|
+
return typeof object === "string";
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
function isArray(object) {
|
|
6
|
+
return Array.isArray(object);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
function replaceObjectValueInTemplate(template, key, value, namespace) {
|
|
10
|
+
const keyToReplace = namespace ? `${namespace}.${key}` : key;
|
|
11
|
+
return template.replace(`\${${keyToReplace}}`, value);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function replaceObjectValuesInTemplates(strings, object, namespace) {
|
|
15
|
+
return Object.keys(object).reduce((result, objectKey) => {
|
|
16
|
+
// If template is an array, replace key by value in all patterns
|
|
17
|
+
if (isArray(result)) {
|
|
18
|
+
return result.map((resultEntry) => {
|
|
19
|
+
return replaceObjectValueInTemplate(resultEntry, objectKey, object[objectKey], namespace);
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
return replaceObjectValueInTemplate(result, objectKey, object[objectKey], namespace);
|
|
23
|
+
}, strings);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
module.exports = {
|
|
27
|
+
isString,
|
|
28
|
+
isArray,
|
|
29
|
+
replaceObjectValuesInTemplates,
|
|
30
|
+
};
|
|
@@ -5,6 +5,7 @@ const { TYPES, ALIAS, ELEMENTS, VALID_MODES } = require("../constants/settings")
|
|
|
5
5
|
const { getElementsTypeNames, isLegacyType } = require("./settings");
|
|
6
6
|
const { rulesMainKey } = require("./rules");
|
|
7
7
|
const { warnOnce } = require("./debug");
|
|
8
|
+
const { isArray, isString } = require("./utils");
|
|
8
9
|
|
|
9
10
|
const invalidMatchers = [];
|
|
10
11
|
|
|
@@ -41,9 +42,9 @@ function elementsMatcherSchema(matcherOptions = DEFAULT_MATCHER_OPTIONS) {
|
|
|
41
42
|
};
|
|
42
43
|
}
|
|
43
44
|
|
|
44
|
-
function rulesOptionsSchema(options
|
|
45
|
+
function rulesOptionsSchema(options) {
|
|
45
46
|
const mainKey = rulesMainKey(options.rulesMainKey);
|
|
46
|
-
|
|
47
|
+
const schema = [
|
|
47
48
|
{
|
|
48
49
|
type: "object",
|
|
49
50
|
properties: {
|
|
@@ -78,15 +79,26 @@ function rulesOptionsSchema(options = {}) {
|
|
|
78
79
|
additionalProperties: false,
|
|
79
80
|
},
|
|
80
81
|
];
|
|
82
|
+
if (options.customMessage) {
|
|
83
|
+
schema[0].properties.message = {
|
|
84
|
+
type: "string",
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
if (options.customRuleMessage) {
|
|
88
|
+
schema[0].properties.rules.items.properties.message = {
|
|
89
|
+
type: "string",
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
return schema;
|
|
81
93
|
}
|
|
82
94
|
|
|
83
95
|
function isValidElementTypesMatcher(matcher, settings) {
|
|
84
|
-
const mathcherToCheck =
|
|
96
|
+
const mathcherToCheck = isArray(matcher) ? matcher[0] : matcher;
|
|
85
97
|
return !matcher || micromatch.some(getElementsTypeNames(settings), mathcherToCheck);
|
|
86
98
|
}
|
|
87
99
|
|
|
88
100
|
function validateElementTypesMatcher(elementsMatcher, settings) {
|
|
89
|
-
const [matcher] =
|
|
101
|
+
const [matcher] = isArray(elementsMatcher) ? elementsMatcher : [elementsMatcher];
|
|
90
102
|
if (!invalidMatchers.includes(matcher) && !isValidElementTypesMatcher(matcher, settings)) {
|
|
91
103
|
invalidMatchers.push(matcher);
|
|
92
104
|
warnOnce(`Option '${matcher}' does not match any element type from '${ELEMENTS}' setting`);
|
|
@@ -94,7 +106,7 @@ function validateElementTypesMatcher(elementsMatcher, settings) {
|
|
|
94
106
|
}
|
|
95
107
|
|
|
96
108
|
function validateElements(elements) {
|
|
97
|
-
if (!elements || !
|
|
109
|
+
if (!elements || !isArray(elements) || !elements.length) {
|
|
98
110
|
warnOnce(`Please provide element types using the '${ELEMENTS}' setting`);
|
|
99
111
|
return;
|
|
100
112
|
}
|
|
@@ -106,7 +118,7 @@ function validateElements(elements) {
|
|
|
106
118
|
);
|
|
107
119
|
} else {
|
|
108
120
|
Object.keys(element).forEach(() => {
|
|
109
|
-
if (!element.type ||
|
|
121
|
+
if (!element.type || !isString(element.type)) {
|
|
110
122
|
warnOnce(`Please provide type in '${ELEMENTS}' setting`);
|
|
111
123
|
}
|
|
112
124
|
if (element.mode && !VALID_MODES.includes(element.mode)) {
|
|
@@ -116,13 +128,10 @@ function validateElements(elements) {
|
|
|
116
128
|
)}. Default value "${VALID_MODES[0]}" will be used instead`
|
|
117
129
|
);
|
|
118
130
|
}
|
|
119
|
-
if (
|
|
120
|
-
!element.pattern ||
|
|
121
|
-
!(typeof element.pattern === "string" || Array.isArray(element.pattern))
|
|
122
|
-
) {
|
|
131
|
+
if (!element.pattern || !(isString(element.pattern) || isArray(element.pattern))) {
|
|
123
132
|
warnOnce(`Please provide a valid pattern in '${ELEMENTS}' setting`);
|
|
124
133
|
}
|
|
125
|
-
if (element.capture && !
|
|
134
|
+
if (element.capture && !isArray(element.capture)) {
|
|
126
135
|
warnOnce(`Invalid capture property in '${ELEMENTS}' setting`);
|
|
127
136
|
}
|
|
128
137
|
});
|
|
@@ -8,6 +8,7 @@ const {
|
|
|
8
8
|
isMatchElementType,
|
|
9
9
|
elementRulesAllowDependency,
|
|
10
10
|
} = require("../helpers/rules");
|
|
11
|
+
const { customErrorMessage, ruleElementMessage, elementMessage } = require("../helpers/messages");
|
|
11
12
|
|
|
12
13
|
function elementRulesAllowDependencyType(element, dependency, options) {
|
|
13
14
|
return elementRulesAllowDependency({
|
|
@@ -15,28 +16,47 @@ function elementRulesAllowDependencyType(element, dependency, options) {
|
|
|
15
16
|
dependency,
|
|
16
17
|
options,
|
|
17
18
|
isMatch: isMatchElementType,
|
|
18
|
-
})
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function errorMessage(ruleData, file, dependency) {
|
|
23
|
+
const ruleReport = ruleData.ruleReport;
|
|
24
|
+
if (ruleReport.message) {
|
|
25
|
+
return customErrorMessage(ruleReport.message, file, dependency);
|
|
26
|
+
}
|
|
27
|
+
if (ruleReport.isDefault) {
|
|
28
|
+
return `No rule allowing this dependency was found. File is ${elementMessage(
|
|
29
|
+
file
|
|
30
|
+
)}. Dependency is ${elementMessage(dependency)}`;
|
|
31
|
+
}
|
|
32
|
+
return `Importing ${ruleElementMessage(
|
|
33
|
+
ruleReport.disallow,
|
|
34
|
+
file.capturedValues
|
|
35
|
+
)} is not allowed in ${ruleElementMessage(
|
|
36
|
+
ruleReport.element,
|
|
37
|
+
file.capturedValues
|
|
38
|
+
)}. Disallowed in rule ${ruleReport.index + 1}`;
|
|
19
39
|
}
|
|
20
40
|
|
|
21
41
|
module.exports = dependencyRule(
|
|
22
42
|
{
|
|
23
43
|
ruleName: RULE_ELEMENT_TYPES,
|
|
24
44
|
description: `Check allowed dependencies between element types`,
|
|
25
|
-
schema: rulesOptionsSchema(
|
|
45
|
+
schema: rulesOptionsSchema({
|
|
46
|
+
customMessage: true,
|
|
47
|
+
customRuleMessage: true,
|
|
48
|
+
}),
|
|
26
49
|
},
|
|
27
50
|
function ({ dependency, file, node, context, options }) {
|
|
28
|
-
if (
|
|
29
|
-
dependency
|
|
30
|
-
!
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
node: node,
|
|
38
|
-
...dependencyLocation(node, context),
|
|
39
|
-
});
|
|
51
|
+
if (dependency.isLocal && !dependency.isIgnored && dependency.type && !dependency.isInternal) {
|
|
52
|
+
const ruleData = elementRulesAllowDependencyType(file, dependency, options);
|
|
53
|
+
if (!ruleData.result) {
|
|
54
|
+
context.report({
|
|
55
|
+
message: errorMessage(ruleData, file, dependency),
|
|
56
|
+
node: node,
|
|
57
|
+
...dependencyLocation(node, context),
|
|
58
|
+
});
|
|
59
|
+
}
|
|
40
60
|
}
|
|
41
61
|
}
|
|
42
62
|
);
|
package/src/rules/entry-point.js
CHANGED
|
@@ -8,6 +8,7 @@ const {
|
|
|
8
8
|
isMatchElementKey,
|
|
9
9
|
elementRulesAllowDependency,
|
|
10
10
|
} = require("../helpers/rules");
|
|
11
|
+
const { customErrorMessage, ruleElementMessage, elementMessage } = require("../helpers/messages");
|
|
11
12
|
|
|
12
13
|
function isMatchElementInternalPath(elementInfo, matcher, options) {
|
|
13
14
|
return isMatchElementKey(elementInfo, matcher, options, "internalPath");
|
|
@@ -20,7 +21,23 @@ function elementRulesAllowEntryPoint(element, dependency, options) {
|
|
|
20
21
|
options,
|
|
21
22
|
isMatch: isMatchElementInternalPath,
|
|
22
23
|
rulesMainKey: "target",
|
|
23
|
-
})
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function errorMessage(ruleData, file, dependency) {
|
|
28
|
+
const ruleReport = ruleData.ruleReport;
|
|
29
|
+
if (ruleReport.message) {
|
|
30
|
+
return customErrorMessage(ruleReport.message, file, dependency);
|
|
31
|
+
}
|
|
32
|
+
if (ruleReport.isDefault) {
|
|
33
|
+
return `No rule allows the entry point '${
|
|
34
|
+
dependency.internalPath
|
|
35
|
+
}' in dependencies ${elementMessage(dependency)}`;
|
|
36
|
+
}
|
|
37
|
+
return `The entry point '${dependency.internalPath}' is not allowed in ${ruleElementMessage(
|
|
38
|
+
ruleReport.element,
|
|
39
|
+
dependency.capturedValues
|
|
40
|
+
)}. Disallowed in rule ${ruleReport.index + 1}`;
|
|
24
41
|
}
|
|
25
42
|
|
|
26
43
|
module.exports = dependencyRule(
|
|
@@ -29,20 +46,20 @@ module.exports = dependencyRule(
|
|
|
29
46
|
description: `Check entry point used for each element type`,
|
|
30
47
|
schema: rulesOptionsSchema({
|
|
31
48
|
rulesMainKey: "target",
|
|
49
|
+
customMessage: true,
|
|
50
|
+
customRuleMessage: true,
|
|
32
51
|
}),
|
|
33
52
|
},
|
|
34
53
|
function ({ dependency, file, node, context, options }) {
|
|
35
|
-
if (
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
...dependencyLocation(node, context),
|
|
45
|
-
});
|
|
54
|
+
if (!dependency.isIgnored && dependency.type && !dependency.isInternal) {
|
|
55
|
+
const ruleData = elementRulesAllowEntryPoint(file, dependency, options);
|
|
56
|
+
if (!ruleData.result) {
|
|
57
|
+
context.report({
|
|
58
|
+
message: errorMessage(ruleData, file, dependency),
|
|
59
|
+
node: node,
|
|
60
|
+
...dependencyLocation(node, context),
|
|
61
|
+
});
|
|
62
|
+
}
|
|
46
63
|
}
|
|
47
64
|
},
|
|
48
65
|
{
|
package/src/rules/no-private.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const {
|
|
1
|
+
const { RULE_NO_PRIVATE } = require("../constants/settings");
|
|
2
2
|
|
|
3
3
|
const dependencyRule = require("../rules-factories/dependency-rule");
|
|
4
4
|
|
|
@@ -6,7 +6,7 @@ const { dependencyLocation } = require("../helpers/rules");
|
|
|
6
6
|
|
|
7
7
|
module.exports = dependencyRule(
|
|
8
8
|
{
|
|
9
|
-
ruleName:
|
|
9
|
+
ruleName: RULE_NO_PRIVATE,
|
|
10
10
|
description: `Prevent importing private elements of another element`,
|
|
11
11
|
schema: [
|
|
12
12
|
{
|
|
@@ -5,9 +5,9 @@ const { validateSettings, validateRules } = require("../helpers/validations");
|
|
|
5
5
|
|
|
6
6
|
const { meta } = require("../helpers/rules");
|
|
7
7
|
|
|
8
|
-
module.exports = function (
|
|
8
|
+
module.exports = function (ruleMeta, rule, ruleOptions = {}) {
|
|
9
9
|
return {
|
|
10
|
-
...meta(
|
|
10
|
+
...meta(ruleMeta),
|
|
11
11
|
create: function (context) {
|
|
12
12
|
const options = context.options[0];
|
|
13
13
|
validateSettings(context.settings);
|
package/CHANGELOG.md
DELETED
|
@@ -1,208 +0,0 @@
|
|
|
1
|
-
# Change Log
|
|
2
|
-
All notable changes to this project will be documented in this file.
|
|
3
|
-
|
|
4
|
-
The format is based on [Keep a Changelog](http://keepachangelog.com/)
|
|
5
|
-
and this project adheres to [Semantic Versioning](http://semver.org/).
|
|
6
|
-
|
|
7
|
-
## [unreleased]
|
|
8
|
-
### Added
|
|
9
|
-
### Changed
|
|
10
|
-
### Fixed
|
|
11
|
-
### Removed
|
|
12
|
-
### BREAKING CHANGES
|
|
13
|
-
|
|
14
|
-
## [2.4.2] - 2021-08-22
|
|
15
|
-
|
|
16
|
-
### Added
|
|
17
|
-
- docs(#107): Add usage with TypeScript docs
|
|
18
|
-
|
|
19
|
-
### Changed
|
|
20
|
-
- chore(deps): Update devDependencies
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
## [2.4.1] - 2021-08-16
|
|
24
|
-
|
|
25
|
-
### Fixed
|
|
26
|
-
- fix: Remove trace when ESLINT_PLUGIN_BOUNDARIES_DEBUG is not set
|
|
27
|
-
|
|
28
|
-
## [2.4.0] - 2021-08-15
|
|
29
|
-
|
|
30
|
-
### Added
|
|
31
|
-
- feat: Improve performance adding internal cache
|
|
32
|
-
|
|
33
|
-
### Changed
|
|
34
|
-
- chore(deps): Update devDependencies
|
|
35
|
-
|
|
36
|
-
## [2.3.0] - 2021-07-20
|
|
37
|
-
|
|
38
|
-
### Added
|
|
39
|
-
- feat(#131): Add `boundaries/include` option allowing to ignore all by default except files matching the pattern.
|
|
40
|
-
|
|
41
|
-
### Changed
|
|
42
|
-
- feat(#132): Detect paths from any `node_modules` folder as external
|
|
43
|
-
- chore(deps): Update devDependencies
|
|
44
|
-
|
|
45
|
-
## [2.2.0] - 2021-05-29
|
|
46
|
-
|
|
47
|
-
### Added
|
|
48
|
-
- chore(deps): Add node.js v16.x to engines and add tests using it
|
|
49
|
-
|
|
50
|
-
### Changed
|
|
51
|
-
- chore(deps): Update devDependencies
|
|
52
|
-
- chore: Migrate Sonar project
|
|
53
|
-
## [2.1.0] - 2021-03-25
|
|
54
|
-
|
|
55
|
-
### Added
|
|
56
|
-
- feat: Add basePattern and baseCapture options to elements settings (#97)
|
|
57
|
-
|
|
58
|
-
### Changed
|
|
59
|
-
- chore(deps): Update dependencies
|
|
60
|
-
|
|
61
|
-
### Fixed
|
|
62
|
-
- fix: Avoid crash when import path is broken (#96)
|
|
63
|
-
|
|
64
|
-
## [2.0.0] - 2021-02-02
|
|
65
|
-
|
|
66
|
-
### Added
|
|
67
|
-
- feat: Support multiple levels of categorization and any type of project structure (#75)
|
|
68
|
-
- feat: Support elements as files (#75)
|
|
69
|
-
- feat(settings): Added support for `import/resolver` setting
|
|
70
|
-
- feat(options): Support micromatch patterns in rules options (#11, #10)
|
|
71
|
-
- feat: Add debug mode
|
|
72
|
-
- test: Add more than 500 tests using different project structure examples, with different categorization levels, elements as folders, as files, etc.
|
|
73
|
-
- test: Add one test for each rules docs example
|
|
74
|
-
- chore: Run tests on Windows OS again (#74)
|
|
75
|
-
|
|
76
|
-
### Changed
|
|
77
|
-
- feat(settings): Deprecated `boundaries/types` setting. `boundaries/elements` should be used instead. If it is not present, `boundaries/types` will be used as fallback
|
|
78
|
-
- feat(rules): Rename `allowed-types` rule into `element-types` (now it can be used to allow/disallow). Change the format of rule options
|
|
79
|
-
- feat(rules): Rename `no-external` rule into `external` (now it can be used to allow/disallow). Change the format of rule options
|
|
80
|
-
- feat(rules): Change the format of `entry-point` rule options (now it support allow/disallow format)
|
|
81
|
-
- feat(rules): Rename `no-import-ignored` rule into `no-ignored` (the majority of the plugin rules are referred to `import` statements, so it is not necessary to specify it in the rule name)
|
|
82
|
-
- feat(rules): Rename `no-import-not-recognized-types` rule into `no-unknown`
|
|
83
|
-
- feat(rules): Rename `prefer-recognized-types` rule into `no-unknown-files`
|
|
84
|
-
- refactor(core): Use `eslint-module-utils/resolve` to get files and import paths. Use `micromatch` to match settings and options. Adapt the whole core to this new approach
|
|
85
|
-
|
|
86
|
-
### Fixed
|
|
87
|
-
- fix: Support scoped packages in external rule (#59)
|
|
88
|
-
|
|
89
|
-
### Removed
|
|
90
|
-
- feat(settings): Removed `boundaries/alias` setting
|
|
91
|
-
|
|
92
|
-
### BREAKING CHANGES
|
|
93
|
-
- Removed `boundaries/alias` setting. `import/resolver` has to be used instead
|
|
94
|
-
- Renamed `allowed-types` rule into `element-types` (now it can be used to allow/disallow). Changed the format of rule options
|
|
95
|
-
- Changed the format of `entry-point` rule options (now it support allow/disallow format)
|
|
96
|
-
- Renamed `no-external` rule into `external` (now it can be used to allow/disallow). Changed the format of rule options
|
|
97
|
-
- Renamed `no-import-ignored` rule into `no-ignored` (the majority of the plugin rules are referred to `import` statements, so it is not necessary to specify it in the rule name)
|
|
98
|
-
- Renamed `no-import-not-recognized-types` rule into `no-unknown`
|
|
99
|
-
- Renamed `prefer-recognized-types` rule into `no-unknown-files`
|
|
100
|
-
|
|
101
|
-
## [2.0.0-beta.4] - 2021-01-30
|
|
102
|
-
|
|
103
|
-
### Added
|
|
104
|
-
- feat: debug files and imports info when ESLINT_PLUGIN_BOUNDARIES_DEBUG environment variable exists
|
|
105
|
-
- feat: `mode` option in `elements` setting now also accepts `full` as value. Pattern will try to match the full path in that case.
|
|
106
|
-
- feat: support defining multiple micromatch patterns in an array in the `pattern` property of `elements` setting.
|
|
107
|
-
|
|
108
|
-
## [2.0.0-beta.3] - 2021-01-26
|
|
109
|
-
|
|
110
|
-
### Fixed
|
|
111
|
-
- fix: node_modules packages were being recognized as local
|
|
112
|
-
|
|
113
|
-
## [2.0.0-beta.2] - 2021-01-26
|
|
114
|
-
|
|
115
|
-
### Fixed
|
|
116
|
-
- fix: Add folder resolver-legacy-alias to npm package
|
|
117
|
-
|
|
118
|
-
## [2.0.0-beta.1] - 2021-01-26
|
|
119
|
-
|
|
120
|
-
### Added
|
|
121
|
-
- feat: Support multiple levels of categorization and any type of project structure (#75)
|
|
122
|
-
- feat: Support elements as files (#75)
|
|
123
|
-
- feat(settings): Added support for `import/resolver` setting
|
|
124
|
-
- feat(options): Support micromatch patterns in rules options (#11, #10)
|
|
125
|
-
- test: Add more than 500 tests using different project structure examples, with different categorization levels, elements as folders, as files, etc.
|
|
126
|
-
- test: Add one test for each rules docs example
|
|
127
|
-
|
|
128
|
-
### Changed
|
|
129
|
-
- feat(settings): Deprecated `boundaries/types` setting. `boundaries/elements` should be used instead. If it is not present, `boundaries/types` will be used as fallback
|
|
130
|
-
- feat(rules): Rename `allowed-types` rule into `element-types` (now it can be used to allow/disallow). Change the format of rule options
|
|
131
|
-
- feat(rules): Rename `no-external` rule into `external` (now it can be used to allow/disallow). Change the format of rule options
|
|
132
|
-
- feat(rules): Change the format of `entry-point` rule options (now it support allow/disallow format)
|
|
133
|
-
- feat(rules): Rename `no-import-ignored` rule into `no-ignored` (the majority of the plugin rules are referred to `import` statements, so it is not necessary to specify it in the rule name)
|
|
134
|
-
- feat(rules): Rename `no-import-not-recognized-types` rule into `no-unknown`
|
|
135
|
-
- feat(rules): Rename `prefer-recognized-types` rule into `no-unknown-files`
|
|
136
|
-
- refactor(core): Use `eslint-module-utils/resolve` to get files and import paths. Use `micromatch` to match settings and options. Adapt the whole core to this new approach
|
|
137
|
-
|
|
138
|
-
### Fixed
|
|
139
|
-
- fix: Support scoped packages in external rule (#59)
|
|
140
|
-
|
|
141
|
-
### Removed
|
|
142
|
-
- feat(settings): Removed `boundaries/alias` setting
|
|
143
|
-
|
|
144
|
-
### BREAKING CHANGES
|
|
145
|
-
- Removed `boundaries/alias` setting. `import/resolver` has to be used instead
|
|
146
|
-
- Renamed `allowed-types` rule into `element-types` (now it can be used to allow/disallow). Changed the format of rule options
|
|
147
|
-
- Changed the format of `entry-point` rule options (now it support allow/disallow format)
|
|
148
|
-
- Renamed `no-external` rule into `external` (now it can be used to allow/disallow). Changed the format of rule options
|
|
149
|
-
- Renamed `no-import-ignored` rule into `no-ignored` (the majority of the plugin rules are referred to `import` statements, so it is not necessary to specify it in the rule name)
|
|
150
|
-
- Renamed `no-import-not-recognized-types` rule into `no-unknown`
|
|
151
|
-
- Renamed `prefer-recognized-types` rule into `no-unknown-files`
|
|
152
|
-
|
|
153
|
-
## [1.1.1] - 2020-12-11
|
|
154
|
-
### Added
|
|
155
|
-
- chore(deps): Add Node.js 10.x support while it is in maintenance
|
|
156
|
-
|
|
157
|
-
### Changed
|
|
158
|
-
- chore(ci-cd): Migrate build and publish pipelines to github actions
|
|
159
|
-
- chore(deps): Update dependencies
|
|
160
|
-
|
|
161
|
-
### Fixed
|
|
162
|
-
- fix(#65): Fixed error on dependency scanning when dependencyInfo.name is null (thanks to @skurfuerst)
|
|
163
|
-
|
|
164
|
-
## [1.1.0] - 2020-11-12
|
|
165
|
-
### Added
|
|
166
|
-
- feat(no-external): Allow forbid importing external libraries specifiers
|
|
167
|
-
- chore(ci-cd): Add github workflows for publishing to gpr and check package version
|
|
168
|
-
- chore(engines): Add node v15.x to engines
|
|
169
|
-
|
|
170
|
-
### Fixed
|
|
171
|
-
- fix(no-external): Do not allow importing subfolders of forbidden external libraries
|
|
172
|
-
|
|
173
|
-
## [1.0.2] - 2020-10-18
|
|
174
|
-
### Added
|
|
175
|
-
- chore: Run tests on Windows OS in pipelines
|
|
176
|
-
|
|
177
|
-
### Fixed
|
|
178
|
-
- fix: Plugin was not working properly on Windows
|
|
179
|
-
|
|
180
|
-
## [1.0.1] - 2020-08-27
|
|
181
|
-
### Changed
|
|
182
|
-
- chore: Update dependencies
|
|
183
|
-
|
|
184
|
-
### Fixed
|
|
185
|
-
- docs: Fix typo
|
|
186
|
-
|
|
187
|
-
## [1.0.0] - 2020-06-13
|
|
188
|
-
### Added
|
|
189
|
-
- test(unit): Add unit tests
|
|
190
|
-
- test(coverage): Increase coverage threshold to 100
|
|
191
|
-
- feat(logs): Add chalk to warning logs
|
|
192
|
-
|
|
193
|
-
### Changed
|
|
194
|
-
- refactor: Remove duplicated code
|
|
195
|
-
|
|
196
|
-
## [1.0.0-beta.3] - 2020-06-12
|
|
197
|
-
### Fixed
|
|
198
|
-
- fix(no-external): Fix no-external rule. There was an error reading options, so it was not being applied.
|
|
199
|
-
- fix(prefer-recognized-types): Do not apply prefer-recognized-types rule to ignored files.
|
|
200
|
-
- fix(rules): Ignore dependencies in all rules (except no-import-ignored) if they are marked as ignored
|
|
201
|
-
|
|
202
|
-
## [1.0.0-beta.2] - 2020-06-11
|
|
203
|
-
### Fixed
|
|
204
|
-
- fix(helpers): Avoid error in helper when an element is not recognized
|
|
205
|
-
|
|
206
|
-
## [1.0.0-beta.1] - 2020-06-11
|
|
207
|
-
### Added
|
|
208
|
-
- First pre-release
|