eslint-plugin-boundaries 5.0.2 → 5.1.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 +184 -19
- package/dist/configs/Config.types.d.ts +41 -0
- package/dist/configs/Config.types.js +2 -0
- package/dist/configs/config.d.ts +40 -0
- package/dist/configs/config.js +116 -0
- package/dist/configs/recommended.d.ts +10 -0
- package/dist/configs/recommended.js +36 -0
- package/dist/configs/strict.d.ts +8 -0
- package/dist/configs/strict.js +26 -0
- package/dist/constants/DependencyInfo.types.d.ts +9 -0
- package/dist/constants/DependencyInfo.types.js +2 -0
- package/dist/constants/ElementsInfo.types.d.ts +24 -0
- package/dist/constants/ElementsInfo.types.js +2 -0
- package/dist/constants/Options.types.d.ts +180 -0
- package/dist/constants/Options.types.js +23 -0
- package/dist/constants/plugin.d.ts +7 -0
- package/dist/constants/plugin.js +10 -0
- package/dist/constants/rules.d.ts +67 -0
- package/dist/constants/rules.js +70 -0
- package/dist/constants/settings.d.ts +278 -0
- package/dist/constants/settings.js +186 -0
- package/dist/core/cache.d.ts +22 -0
- package/dist/core/cache.js +54 -0
- package/dist/core/dependencyInfo.d.ts +4 -0
- package/dist/core/dependencyInfo.js +73 -0
- package/dist/core/elementsInfo.d.ts +4 -0
- package/dist/core/elementsInfo.js +271 -0
- package/dist/helpers/Helpers.types.d.ts +5 -0
- package/dist/helpers/Helpers.types.js +2 -0
- package/dist/helpers/Rules.types.d.ts +10 -0
- package/dist/helpers/Rules.types.js +2 -0
- package/dist/helpers/debug.d.ts +4 -0
- package/dist/helpers/debug.js +44 -0
- package/dist/helpers/messages.d.ts +13 -0
- package/dist/helpers/messages.js +147 -0
- package/dist/helpers/rules.d.ts +37 -0
- package/dist/helpers/rules.js +206 -0
- package/dist/helpers/settings.d.ts +7 -0
- package/dist/helpers/settings.js +94 -0
- package/dist/helpers/utils.d.ts +10 -0
- package/dist/helpers/utils.js +49 -0
- package/dist/helpers/validations.d.ts +131 -0
- package/dist/helpers/validations.js +241 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +76 -0
- package/dist/rules/element-types.d.ts +2 -0
- package/dist/rules/element-types.js +51 -0
- package/dist/rules/entry-point.d.ts +2 -0
- package/dist/rules/entry-point.js +63 -0
- package/dist/rules/external.d.ts +3 -0
- package/dist/rules/external.js +169 -0
- package/dist/rules/no-ignored.d.ts +2 -0
- package/dist/rules/no-ignored.js +21 -0
- package/dist/rules/no-private.d.ts +2 -0
- package/dist/rules/no-private.js +49 -0
- package/dist/rules/no-unknown-files.d.ts +3 -0
- package/dist/rules/no-unknown-files.js +27 -0
- package/dist/rules/no-unknown.d.ts +2 -0
- package/dist/rules/no-unknown.js +21 -0
- package/dist/rules-factories/DependencyRule.types.d.ts +19 -0
- package/dist/rules-factories/DependencyRule.types.js +2 -0
- package/dist/rules-factories/dependency-rule.d.ts +5 -0
- package/dist/rules-factories/dependency-rule.js +55 -0
- package/dist/types/Config.types.d.ts +2 -0
- package/dist/types/Config.types.js +20 -0
- package/dist/types/Rules.types.d.ts +5 -0
- package/dist/types/Rules.types.js +11 -0
- package/dist/types/Settings.types.d.ts +2 -0
- package/dist/types/Settings.types.js +12 -0
- package/dist/types/index.d.ts +3 -0
- package/dist/types/index.js +19 -0
- package/package.json +46 -7
- package/index.js +0 -1
- package/resolver-legacy-alias/index.js +0 -32
- package/src/configs/recommended.js +0 -31
- package/src/configs/strict.js +0 -17
- package/src/constants/plugin.js +0 -7
- package/src/constants/rules.js +0 -9
- package/src/constants/settings.js +0 -90
- package/src/core/cache.js +0 -57
- package/src/core/dependencyInfo.js +0 -88
- package/src/core/elementsInfo.js +0 -307
- package/src/helpers/debug.js +0 -46
- package/src/helpers/messages.js +0 -199
- package/src/helpers/rules.js +0 -276
- package/src/helpers/settings.js +0 -65
- package/src/helpers/utils.js +0 -51
- package/src/helpers/validations.js +0 -274
- package/src/index.js +0 -30
- package/src/rules/element-types.js +0 -74
- package/src/rules/entry-point.js +0 -88
- package/src/rules/external.js +0 -222
- package/src/rules/no-ignored.js +0 -21
- package/src/rules/no-private.js +0 -53
- package/src/rules/no-unknown-files.js +0 -26
- package/src/rules/no-unknown.js +0 -21
- package/src/rules-factories/dependency-rule.js +0 -62
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
[![Build status][build-image]][build-url] [![Coverage Status][coveralls-image]][coveralls-url] [![Quality Gate][quality-gate-image]][quality-gate-url]
|
|
1
|
+
[![Build status][build-image]][build-url] [![Coverage Status][coveralls-image]][coveralls-url] <!-- [![Quality Gate][quality-gate-image]][quality-gate-url] -->
|
|
2
2
|
|
|
3
3
|
[](https://renovatebot.com) [![Last commit][last-commit-image]][last-commit-url] [![Last release][release-image]][release-url]
|
|
4
4
|
|
|
@@ -28,13 +28,15 @@ By default, __the plugin works by checking `import` statements, but it is also a
|
|
|
28
28
|
- [Configuration](#configuration)
|
|
29
29
|
* [Global settings](#global-settings)
|
|
30
30
|
* [Predefined configurations](#predefined-configurations)
|
|
31
|
+
* [createConfig helper](#createconfig-helper)
|
|
31
32
|
* [Rules configuration](#rules-configuration)
|
|
32
33
|
* [Main format of rules options](#main-format-of-rules-options)
|
|
33
|
-
* [Elements
|
|
34
|
+
* [Elements selectors](#elements-selectors)
|
|
34
35
|
* [Error messages](#error-messages)
|
|
35
36
|
* [Advanced example](#advanced-example)
|
|
36
37
|
- [Resolvers](#resolvers)
|
|
37
|
-
- [
|
|
38
|
+
- [TypeScript Support](#typescript-support)
|
|
39
|
+
* [Exported Types](#exported-types)
|
|
38
40
|
- [Migration guides](#migration-guides)
|
|
39
41
|
- [Debug mode](#debug-mode)
|
|
40
42
|
- [Acknowledgements](#acknowledgements)
|
|
@@ -70,7 +72,7 @@ export default [
|
|
|
70
72
|
];
|
|
71
73
|
```
|
|
72
74
|
|
|
73
|
-
> [!NOTE]
|
|
75
|
+
> [!NOTE]
|
|
74
76
|
> From version `5.0.0`, this plugin is compatible with eslint v9 and above. It may be also compatible with previous eslint versions, but you might read the [documentation of the `4.2.2` version](https://github.com/javierbrea/eslint-plugin-boundaries/tree/v4.2.2) to know how to configure it properly using the legacy configuration format.
|
|
75
77
|
|
|
76
78
|
## Overview
|
|
@@ -173,7 +175,7 @@ Read the [docs of the `boundaries/entry-point` rule](docs/rules/entry-point.md)
|
|
|
173
175
|
|
|
174
176
|
#### __`boundaries/elements`__
|
|
175
177
|
|
|
176
|
-
Define
|
|
178
|
+
Define element descriptors to recognize each file in the project as one of this element types. All rules need this setting to be configured properly to work. The plugin tries to identify each file being analyzed or `import` statement in rules as one of the defined element types. The assigned element type will be that with the first matching pattern, in the same order that elements are defined in the array, so you __should sort them from the most accurate patterns to the less ones__. Properties of each `element`:
|
|
177
179
|
|
|
178
180
|
* __`type`__: `<string>` Element type to be assigned to files or imports matching the `pattern`. This type will be used afterwards in the rules configuration.
|
|
179
181
|
* __`pattern`__: `<string>|<array>` [`micromatch` pattern](https://github.com/micromatch/micromatch). __By default the plugin will try to match this pattern progressively starting from the right side of each file path.__ This means that you don't have to define patterns matching from the base project path, but only the last part of the path that you want to be matched. This is made because the plugin supports elements being children of other elements, and otherwise it could wrongly recognize children elements as a part of the parent one. <br/>For example, given a path `src/helpers/awesome-helper/index.js`, it will try to assign the element to a pattern matching `index.js`, then `awesome-helper/index.js`, then `helpers/awesome-helper/index.js`, etc. Once a pattern matches, it assign the correspondent element type, and continues searching for parents elements with the same logic until the full path has been analyzed. __This behavior can be disabled setting the `mode` option to `full`__, then the provided pattern will try to match the full path.
|
|
@@ -328,26 +330,107 @@ We recommend to use this setting if you are applying the plugin to an already ex
|
|
|
328
330
|
|
|
329
331
|
```js
|
|
330
332
|
import boundaries from "eslint-plugin-boundaries";
|
|
333
|
+
import { recommended } from "eslint-plugin-boundaries/config";
|
|
331
334
|
|
|
332
335
|
export default [{
|
|
336
|
+
plugins: {
|
|
337
|
+
boundaries,
|
|
338
|
+
},
|
|
339
|
+
settings: {
|
|
340
|
+
...recommended.settings,
|
|
341
|
+
// Define your own element descriptors here
|
|
342
|
+
"boundaries/elements": [
|
|
343
|
+
{
|
|
344
|
+
type: "helpers",
|
|
345
|
+
pattern: "helpers/*"
|
|
346
|
+
},
|
|
347
|
+
]
|
|
348
|
+
},
|
|
333
349
|
rules: {
|
|
334
|
-
...
|
|
350
|
+
...recommended.rules,
|
|
351
|
+
"boundaries/element-types": [2, {
|
|
352
|
+
// Define your own options here
|
|
353
|
+
}],
|
|
335
354
|
}
|
|
336
355
|
}]
|
|
337
356
|
```
|
|
338
357
|
|
|
339
358
|
#### Strict
|
|
340
359
|
|
|
341
|
-
All rules are enabled, so all elements in the project will be compliant with your architecture boundaries. 😃
|
|
360
|
+
All rules are enabled by default, so all elements in the project will be compliant with your architecture boundaries. 😃
|
|
361
|
+
|
|
362
|
+
Follow the same example as in "recommended" configuration, but importing `strict` instead of `recommended`.
|
|
342
363
|
|
|
343
364
|
```js
|
|
344
|
-
import
|
|
365
|
+
import { strict } from "eslint-plugin-boundaries/config";
|
|
366
|
+
```
|
|
345
367
|
|
|
346
|
-
|
|
368
|
+
### createConfig helper
|
|
369
|
+
|
|
370
|
+
A `createConfig` helper is also available for making configurations easier.
|
|
371
|
+
|
|
372
|
+
It enforces valid types for settings and rules and automatically:
|
|
373
|
+
|
|
374
|
+
* Adds the plugin to the plugins property
|
|
375
|
+
* Includes JavaScript and TypeScript file patterns in the files property
|
|
376
|
+
* Validates that all provided settings and rules belong to the plugin
|
|
377
|
+
|
|
378
|
+
```js
|
|
379
|
+
import { createConfig, recommended } from "eslint-plugin-boundaries/config";
|
|
380
|
+
|
|
381
|
+
const config = createConfig({
|
|
382
|
+
settings: {
|
|
383
|
+
...recommended.settings,
|
|
384
|
+
"boundaries/elements": [],
|
|
385
|
+
"boundaries/ignore": ["**/ignored/**/*.js"],
|
|
386
|
+
},
|
|
347
387
|
rules: {
|
|
348
|
-
...
|
|
388
|
+
...recommended.rules,
|
|
389
|
+
"boundaries/element-types": ["error", { default: "disallow" }],
|
|
349
390
|
}
|
|
350
|
-
}
|
|
391
|
+
});
|
|
392
|
+
|
|
393
|
+
export default [config];
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
You can also rename the plugin by passing a second argument. The helper will rename all rules from `boundaries/` prefix to the provided one, so recommended or strict configs can be used as a base without issues.
|
|
397
|
+
|
|
398
|
+
```js
|
|
399
|
+
import { createConfig, recommended } from "eslint-plugin-boundaries/config";
|
|
400
|
+
|
|
401
|
+
const config = createConfig({
|
|
402
|
+
settings: {
|
|
403
|
+
...recommended.settings,
|
|
404
|
+
"boundaries/elements": [], // Note the original prefix here
|
|
405
|
+
},
|
|
406
|
+
rules: {
|
|
407
|
+
...recommended.rules,
|
|
408
|
+
"custom-boundaries/element-types": ["error", { default: "disallow" }], // Note the renamed prefix here
|
|
409
|
+
"boundaries/entry-point": 0, // The original prefix still works too
|
|
410
|
+
// @ts-expect-error Any other prefix raises an error
|
|
411
|
+
"foo/entry-point": 2, // This rule does not match the new plugin name nor the original one
|
|
412
|
+
}
|
|
413
|
+
}, "custom-boundaries");
|
|
414
|
+
|
|
415
|
+
export default [config];
|
|
416
|
+
```
|
|
417
|
+
|
|
418
|
+
> [!WARNING]
|
|
419
|
+
> Note that the settings still must use the `boundaries/` prefix — ESLint doesn’t namespace settings by plugin name.
|
|
420
|
+
|
|
421
|
+
The plugin also exports constants and type guard methods for settings keys, rule names, and other configuration-related values. You can use them when defining your configuration. For example:
|
|
422
|
+
|
|
423
|
+
```ts
|
|
424
|
+
import {
|
|
425
|
+
RULE_NAMES_MAP,
|
|
426
|
+
isRuleName,
|
|
427
|
+
SETTINGS_KEYS_MAP,
|
|
428
|
+
isSettingsKey,
|
|
429
|
+
ELEMENT_DESCRIPTOR_MODES_MAP,
|
|
430
|
+
isElementDescriptorMode,
|
|
431
|
+
RULE_POLICIES_MAP,
|
|
432
|
+
isRulePolicy,
|
|
433
|
+
} from "eslint-plugin-boundaries/config";
|
|
351
434
|
```
|
|
352
435
|
|
|
353
436
|
### Rules configuration
|
|
@@ -397,26 +480,26 @@ Remember that:
|
|
|
397
480
|
|
|
398
481
|
##### Rules options properties
|
|
399
482
|
|
|
400
|
-
* __`from/target`__: `<element
|
|
401
|
-
* __`disallow/allow`__: `<
|
|
483
|
+
* __`from/target`__: `<element selectors>` Depending of the rule to which the options are for, the rule will be applied only if the file being analyzed matches with this element selector (`from`), or the dependency being imported matches with this element selector (`target`).
|
|
484
|
+
* __`disallow/allow`__: `<selectors>` 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 selector>` has to be provided in order to check the type of the local dependency.
|
|
402
485
|
* __`importKind`__: `<string>` _Optional_. It is useful only when using TypeScript, because it allows to define if the rule applies when the dependency is being imported as a value or as a type. It can be also defined as an array of strings, or a micromatch pattern. Note that possible values to match with are `"value"`, `"type"` or `"typeof"`. For example, you could define that "components" can import "helpers" as a value, but not as a type. So, `import { helper } from "helpers/helper-a"` would be allowed, but `import type { Helper } from "helpers/helper-a"` would be disallowed.
|
|
403
486
|
* __`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.
|
|
404
487
|
|
|
405
|
-
> Tip: Properties `from/target` and `disallow/allow` can receive a single
|
|
488
|
+
> Tip: Properties `from/target` and `disallow/allow` can receive a single selector, or an array of selectors.
|
|
406
489
|
|
|
407
|
-
##### Elements
|
|
490
|
+
##### Elements selectors
|
|
408
491
|
|
|
409
|
-
Elements
|
|
492
|
+
Elements selectors used in the rules options can have the next formats:
|
|
410
493
|
|
|
411
494
|
* __`<string>`__: Will return `true` when the element type matches with this [`micromatch` pattern](https://github.com/micromatch/micromatch). It [supports templating](#templating) for using values from captured values.
|
|
412
|
-
* __`[<string>, <capturedValuesObject>]`__: Will return `true` whe when the element type matches with the first element in the array, and all of the captured values also match. <br/>The `<capturedValuesObject>` has to be an object containing `capture` keys from the [`boundaries/element-types` setting](#boundarieselement-types) of the element as keys, and [`micromatch` patterns](https://github.com/micromatch/micromatch) as values. (values also support [templating](#templating)) <br/>For example, for an element of type "helpers" with settings as `{ type: "helpers", pattern": "helpers/*/*.js", "capture": ["category", "elementName"]}`, you could write element
|
|
495
|
+
* __`[<string>, <capturedValuesObject>]`__: Will return `true` whe when the element type matches with the first element in the array, and all of the captured values also match. <br/>The `<capturedValuesObject>` has to be an object containing `capture` keys from the [`boundaries/element-types` setting](#boundarieselement-types) of the element as keys, and [`micromatch` patterns](https://github.com/micromatch/micromatch) as values. (values also support [templating](#templating)) <br/>For example, for an element of type "helpers" with settings as `{ type: "helpers", pattern": "helpers/*/*.js", "capture": ["category", "elementName"]}`, you could write element selectors as:
|
|
413
496
|
* `["helpers", { category: "data", elementName: "parsers"}]`: Will only match with helpers with category "data" and elementName "parsers" (`helpers/data/parsers.js`).
|
|
414
497
|
* `["helpers", { category: "data" }]`: Will match with all helpers with category "data" (`helpers/data/*.js`)
|
|
415
498
|
* `["data-${from.elementName}", { category: "${from.category}" }]`: Will only match with helpers with the type equals to the `elementName` of the file importing plus a `data-` prefix, and the category being equal to the `category` of the file importing the dependency.
|
|
416
499
|
|
|
417
500
|
##### Templating
|
|
418
501
|
|
|
419
|
-
When defining [__Element
|
|
502
|
+
When defining [__Element selectors__](#elements-selectors), the values captured both from the element importing ("from") and from the imported element ("target") are available to be replaced. They are replaced both in the main string and in the `<capturedValuesObject>`.
|
|
420
503
|
|
|
421
504
|
Templates must be defined with the format `${from.CAPTURED_PROPERTY}` or `${target.CAPTURED_PROPERTY}`.
|
|
422
505
|
|
|
@@ -541,7 +624,7 @@ export default [{
|
|
|
541
624
|
}]
|
|
542
625
|
```
|
|
543
626
|
|
|
544
|
-
##
|
|
627
|
+
## TypeScript Support
|
|
545
628
|
|
|
546
629
|
This plugin can be used also in [TypeScript](https://www.typescriptlang.org/) projects using `@typescript-eslint/eslint-plugin`. Follow next steps to configure it:
|
|
547
630
|
|
|
@@ -580,6 +663,88 @@ export default [{
|
|
|
580
663
|
|
|
581
664
|
In case you face any issue configuring it, you can also [use this repository as a guide](https://github.com/javierbrea/epb-ts-example). It contains a fully working and tested example.
|
|
582
665
|
|
|
666
|
+
### Exported Types
|
|
667
|
+
|
|
668
|
+
The main type exported by the plugin is `Config`, which represents a fully typed [Flat Config](https://eslint.org/docs/latest/use/core-concepts/glossary#flat-config).
|
|
669
|
+
|
|
670
|
+
```ts
|
|
671
|
+
import type { Config } from "eslint-plugin-boundaries";
|
|
672
|
+
|
|
673
|
+
const config: Config = {
|
|
674
|
+
plugins: {
|
|
675
|
+
boundaries,
|
|
676
|
+
},
|
|
677
|
+
settings: {
|
|
678
|
+
"boundaries/elements": [],
|
|
679
|
+
"boundaries/ignore": ["**/ignored/**/*.js"],
|
|
680
|
+
},
|
|
681
|
+
rules: {
|
|
682
|
+
"boundaries/element-types": [
|
|
683
|
+
"error",
|
|
684
|
+
{ default: "disallow", rules: [] },
|
|
685
|
+
],
|
|
686
|
+
},
|
|
687
|
+
};
|
|
688
|
+
```
|
|
689
|
+
|
|
690
|
+
Types also support renaming the plugin when loading it in the `plugins` property, so rules and must be defined using the new name:
|
|
691
|
+
|
|
692
|
+
```ts
|
|
693
|
+
import type { Config } from "eslint-plugin-boundaries";
|
|
694
|
+
|
|
695
|
+
const config: Config<"custom-boundaries"> = {
|
|
696
|
+
plugins: {
|
|
697
|
+
"custom-boundaries": boundaries, // NOTE the renamed prefix here
|
|
698
|
+
},
|
|
699
|
+
settings: {
|
|
700
|
+
"boundaries/elements": [],
|
|
701
|
+
"boundaries/ignore": ["**/ignored/**/*.js"],
|
|
702
|
+
},
|
|
703
|
+
rules: {
|
|
704
|
+
"custom-boundaries/element-types": 2, // NOTE the renamed prefix here
|
|
705
|
+
},
|
|
706
|
+
};
|
|
707
|
+
```
|
|
708
|
+
|
|
709
|
+
> [!WARNING]
|
|
710
|
+
> Note that the settings still use the `boundaries/` prefix — ESLint doesn’t namespace settings by plugin name.
|
|
711
|
+
|
|
712
|
+
In addition, individual subtypes are available for each part of the configuration, such as:
|
|
713
|
+
|
|
714
|
+
* `Settings`, `Rules`, `ElementDescriptor`, `ElementTypesRule`, `ElementTypesRuleOptions`, `ElementSelector`, `IgnoreSetting`, etc.
|
|
715
|
+
|
|
716
|
+
This allows you to import only what you need and get full autocompletion and type safety.
|
|
717
|
+
|
|
718
|
+
```ts
|
|
719
|
+
import type {
|
|
720
|
+
Config,
|
|
721
|
+
Settings,
|
|
722
|
+
Rules,
|
|
723
|
+
ElementDescriptor,
|
|
724
|
+
ElementTypesRuleOptions,
|
|
725
|
+
} from "eslint-plugin-boundaries";
|
|
726
|
+
|
|
727
|
+
const moduleDescriptor: ElementDescriptor = {
|
|
728
|
+
type: "module",
|
|
729
|
+
pattern: "src/modules/*",
|
|
730
|
+
capture: ["module"],
|
|
731
|
+
};
|
|
732
|
+
|
|
733
|
+
const settings: Settings = {
|
|
734
|
+
"boundaries/elements": [moduleDescriptor],
|
|
735
|
+
};
|
|
736
|
+
|
|
737
|
+
const rules: Rules = {
|
|
738
|
+
"boundaries/element-types": ["error", { default: "disallow", rules: [] }],
|
|
739
|
+
};
|
|
740
|
+
|
|
741
|
+
const config: Config = {
|
|
742
|
+
files: ["**/*.js", "**/*.ts"],
|
|
743
|
+
settings,
|
|
744
|
+
rules,
|
|
745
|
+
};
|
|
746
|
+
```
|
|
747
|
+
|
|
583
748
|
## Migration guides
|
|
584
749
|
|
|
585
750
|
### Migrating from v4.x
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { ESLint, Linter, Rule } from "eslint";
|
|
2
|
+
import type { ElementTypesRuleOptions, EntryPointRuleOptions, ExternalRuleOptions, NoPrivateOptions } from "../constants/Options.types";
|
|
3
|
+
import type { PLUGIN_NAME } from "../constants/plugin";
|
|
4
|
+
import type { RuleShortName, ELEMENT_TYPES, ENTRY_POINT, EXTERNAL, NO_IGNORED, NO_PRIVATE, NO_UNKNOWN, NO_UNKNOWN_FILES } from "../constants/rules";
|
|
5
|
+
import type { Settings } from "../constants/settings";
|
|
6
|
+
/**
|
|
7
|
+
* Eslint boundaries plugin rules.
|
|
8
|
+
* By default, rule names are prefixed with "boundaries/", but it can be customized via the `PluginName` generic parameter.
|
|
9
|
+
*
|
|
10
|
+
* @template PluginName - The name of the plugin, defaults to "boundaries". It defines the prefix for the rule names.
|
|
11
|
+
*/
|
|
12
|
+
export type Rules<PluginName extends string = typeof PLUGIN_NAME> = {
|
|
13
|
+
[K in `${PluginName}/${typeof ELEMENT_TYPES | typeof ENTRY_POINT | typeof EXTERNAL | typeof NO_IGNORED | typeof NO_PRIVATE | typeof NO_UNKNOWN_FILES | typeof NO_UNKNOWN}`]?: K extends `${PluginName}/${typeof ELEMENT_TYPES}` ? Linter.RuleEntry<ElementTypesRuleOptions[]> : K extends `${PluginName}/${typeof ENTRY_POINT}` ? Linter.RuleEntry<EntryPointRuleOptions[]> : K extends `${PluginName}/${typeof EXTERNAL}` ? Linter.RuleEntry<ExternalRuleOptions[]> : K extends `${PluginName}/${typeof NO_PRIVATE}` ? Linter.RuleEntry<NoPrivateOptions[]> : Linter.RuleEntry<never>;
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* ESLint configuration with optional settings and rules specific to the boundaries plugin.
|
|
17
|
+
*/
|
|
18
|
+
export interface Config<PluginName extends string = typeof PLUGIN_NAME> extends Linter.Config {
|
|
19
|
+
/**
|
|
20
|
+
* Optional settings specific to the boundaries plugin.
|
|
21
|
+
*/
|
|
22
|
+
settings?: Settings;
|
|
23
|
+
/**
|
|
24
|
+
* Optional rules specific to the boundaries plugin.
|
|
25
|
+
*/
|
|
26
|
+
rules?: Rules<PluginName>;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* ESLint plugin interface for the boundaries plugin, including metadata, rules, and configurations.
|
|
30
|
+
*/
|
|
31
|
+
export interface PluginBoundaries extends ESLint.Plugin {
|
|
32
|
+
meta: {
|
|
33
|
+
name: string;
|
|
34
|
+
version: string;
|
|
35
|
+
};
|
|
36
|
+
rules: Record<RuleShortName, Rule.RuleModule>;
|
|
37
|
+
configs: {
|
|
38
|
+
recommended: Config;
|
|
39
|
+
strict: Config;
|
|
40
|
+
};
|
|
41
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { Linter } from "eslint";
|
|
2
|
+
import { PLUGIN_NAME } from "../constants/plugin";
|
|
3
|
+
import type { PluginBoundaries, Config } from "./Config.types";
|
|
4
|
+
export * from "../types";
|
|
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,116 @@
|
|
|
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 plugin_1 = require("../constants/plugin");
|
|
23
|
+
const rules_1 = require("../constants/rules");
|
|
24
|
+
const settings_1 = require("../constants/settings");
|
|
25
|
+
const index_1 = __importDefault(require("../index"));
|
|
26
|
+
const recommended_1 = __importDefault(require("./recommended"));
|
|
27
|
+
const strict_1 = __importDefault(require("./strict"));
|
|
28
|
+
__exportStar(require("../types"), exports);
|
|
29
|
+
function renamePluginRules(rules, pluginName = plugin_1.PLUGIN_NAME) {
|
|
30
|
+
if (!rules) {
|
|
31
|
+
return {};
|
|
32
|
+
}
|
|
33
|
+
const allowedPrefixes = [plugin_1.PLUGIN_NAME, pluginName];
|
|
34
|
+
// Return the same rules objects, but converting plugin default rule keys with provided plugin name
|
|
35
|
+
return Object.entries(rules).reduce((acc, [key, value]) => {
|
|
36
|
+
if (!key.includes("/")) {
|
|
37
|
+
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 "${plugin_1.PLUGIN_NAME}/", or with the provided plugin name "${pluginName}/".`);
|
|
38
|
+
}
|
|
39
|
+
const splittedRuleKey = key.split("/");
|
|
40
|
+
const rulePrefix = splittedRuleKey[0];
|
|
41
|
+
const ruleName = splittedRuleKey[1];
|
|
42
|
+
if (!allowedPrefixes.includes(rulePrefix)) {
|
|
43
|
+
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 "${plugin_1.PLUGIN_NAME}/", or with the provided plugin name "${pluginName}/".`);
|
|
44
|
+
}
|
|
45
|
+
if (!(0, rules_1.isRuleShortName)(ruleName)) {
|
|
46
|
+
throw new Error(`Invalid rule name "${ruleName}". When using createConfig, all rules must belong to eslint-plugin-boundaries.`);
|
|
47
|
+
}
|
|
48
|
+
const newKey = rulePrefix === plugin_1.PLUGIN_NAME
|
|
49
|
+
? `${pluginName}/${key.slice(`${plugin_1.PLUGIN_NAME}/`.length)}`
|
|
50
|
+
: key;
|
|
51
|
+
acc[newKey] = value;
|
|
52
|
+
return acc;
|
|
53
|
+
}, {});
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Returns an ESLint config object with the boundaries plugin registered, providing default JS and TS file patterns
|
|
57
|
+
* and enforcing valid types for settings and rules. Supports renaming the plugin. Rules can be prefixed with either
|
|
58
|
+
* the original plugin name or the provided plugin name.
|
|
59
|
+
*
|
|
60
|
+
* @param config - ESLint config object without the plugins field.
|
|
61
|
+
* @param name - The name of the plugin to register. Defaults to "boundaries".
|
|
62
|
+
* @returns {Linter.Config} The ESLint config object with the boundaries plugin registered and the provided config merged in.
|
|
63
|
+
* @throws {Error} If settings or rules are not from eslint-plugin-boundaries.
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* ```ts
|
|
67
|
+
* import { createConfig, recommended } from "eslint-plugin-boundaries/config";
|
|
68
|
+
*
|
|
69
|
+
* const config = createConfig({
|
|
70
|
+
* settings: {
|
|
71
|
+
* ...recommended.settings,
|
|
72
|
+
* "boundaries/elements": [],
|
|
73
|
+
* "boundaries/ignore": ["ignored/*.js"],
|
|
74
|
+
* },
|
|
75
|
+
* rules: {
|
|
76
|
+
* ...recommended.rules,
|
|
77
|
+
* "boundaries/element-types": ["error", { default: "disallow" }],
|
|
78
|
+
* }
|
|
79
|
+
* });
|
|
80
|
+
*
|
|
81
|
+
* export default [config];
|
|
82
|
+
* ```
|
|
83
|
+
*/
|
|
84
|
+
function createConfig(config, name = plugin_1.PLUGIN_NAME) {
|
|
85
|
+
const pluginsRegistration = {
|
|
86
|
+
[name]: index_1.default,
|
|
87
|
+
};
|
|
88
|
+
if (Object.prototype.hasOwnProperty.call(config, "plugins")) {
|
|
89
|
+
throw new Error("The 'plugins' field is managed by createConfig and should not be provided in the config argument.");
|
|
90
|
+
}
|
|
91
|
+
if (Object.prototype.hasOwnProperty.call(config, "settings")) {
|
|
92
|
+
const settings = config.settings;
|
|
93
|
+
if (settings) {
|
|
94
|
+
for (const key of Object.keys(settings)) {
|
|
95
|
+
if (!(0, settings_1.isSettingsKey)(key)) {
|
|
96
|
+
throw new Error(`Invalid settings key "${key}". When using createConfig, all settings keys must belong to eslint-plugin-boundaries.`);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return {
|
|
102
|
+
files: [
|
|
103
|
+
"**/*.js",
|
|
104
|
+
"**/*.jsx",
|
|
105
|
+
"**/*.ts",
|
|
106
|
+
"**/*.tsx",
|
|
107
|
+
"**/*.mjs",
|
|
108
|
+
"**/*.cjs",
|
|
109
|
+
],
|
|
110
|
+
...config,
|
|
111
|
+
plugins: pluginsRegistration,
|
|
112
|
+
rules: renamePluginRules(config.rules, name),
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
exports.recommended = recommended_1.default;
|
|
116
|
+
exports.strict = strict_1.default;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Config } from "./Config.types";
|
|
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("../constants/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 "./Config.types";
|
|
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("../constants/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,9 @@
|
|
|
1
|
+
import type { ImportInfo } from "./ElementsInfo.types";
|
|
2
|
+
import type { ImportKind } from "./settings";
|
|
3
|
+
export type ElementsRelationship = "internal" | "child" | "descendant" | "brother" | "parent" | "uncle" | "ancestor" | null;
|
|
4
|
+
export type DependencyInfo = ImportInfo & {
|
|
5
|
+
importKind: ImportKind;
|
|
6
|
+
relationship: ElementsRelationship;
|
|
7
|
+
isInternal: boolean;
|
|
8
|
+
baseModule: string | null;
|
|
9
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { CapturedValues } from "./Options.types";
|
|
2
|
+
export type PathCapturedValues = string[];
|
|
3
|
+
export type ElementInfo = {
|
|
4
|
+
elementPath: string;
|
|
5
|
+
type: string | null;
|
|
6
|
+
parents: Pick<ElementInfo, "elementPath" | "type" | "capture" | "capturedValues">[];
|
|
7
|
+
capture: string[] | null;
|
|
8
|
+
capturedValues: CapturedValues;
|
|
9
|
+
internalPath: string | null;
|
|
10
|
+
};
|
|
11
|
+
export type ImportInfo = {
|
|
12
|
+
source: string;
|
|
13
|
+
path: string;
|
|
14
|
+
isIgnored: boolean;
|
|
15
|
+
isLocal: boolean;
|
|
16
|
+
isBuiltIn: boolean;
|
|
17
|
+
isExternal: boolean;
|
|
18
|
+
baseModule: string | null;
|
|
19
|
+
specifiers?: string[];
|
|
20
|
+
} & ElementInfo;
|
|
21
|
+
export type FileInfo = ElementInfo & {
|
|
22
|
+
path: string;
|
|
23
|
+
isIgnored: boolean;
|
|
24
|
+
};
|