The @nx/powerpack-conformance
plugin allows Nx Powerpack users to write and apply rules for your entire workspace that help with consistency, maintainability, reliability and security.
The conformance plugin allows you to encode your own organization's standards so that they can be enforced automatically. Conformance rules can also complement linting tools by enforcing that those tools are configured in the recommended way. The rules are written in TypeScript but can be applied to any language in the codebase or focus entirely on configuration files.
The plugin also provides the following pre-written rules:
- Enforce Module Boundaries: Similar to the Nx ESLint Enforce Module Boundaries rule, but enforces the boundaries on every project dependency, not just those created from TypeScript imports or
package.json
dependencies. - Ensure Owners: Require every project to have an owner defined for the
@nx/powerpack-owners
plugin
In order to use @nx/powerpack-conformance
, you need to have an active Powerpack license. If you don't have a license or it has expired, the nx conformance
command will fail.
Set Up @nx/powerpack-conformance
Activate Powerpack if you haven't already
Install the package
❯
nx add @nx/powerpack-conformance
Configure Conformance Rules
Configure the
@nx/powerpack-conformance
plugin in thenx.json
file or in individual project configuration files. Consult the Conformance Configuration Reference section for more details.Run the
nx conformance
command in CI
Add nx conformance
to the beginning of the CI process.
1- name: Enforce all conformance rules
2 run: npx nx conformance
3
Conformance Configuration Reference
1{
2 "conformance": {
3 "rules": [{
4 /**
5 * Relative path to a local rule implementation or node_module path.
6 */
7 "rule": "@nx/powerpack-conformance/enforce-module-boundaries";
8 /**
9 * Rule specific configuration options. (Optional)
10 */
11 "options": {}
12 /**
13 * The projects array allows users to opt in or out of violations for specific projects being reported by the current rule.
14 * The array can contain any valid matchers for findMatchingProjects(), by default the implied value is ["*"]. (Optional)
15 */
16 "projects": ["*"];
17 }]
18 }
19}
20
Provided Conformance Rules
The following rules are provided by Nx along with the @nx/powerpack-conformance
plugin.
Enforce Module Boundaries
This rule is similar to the Nx ESLint Enforce Module Boundaries rule, but enforces the boundaries on every project dependency, not just those created from TypeScript imports or package.json
dependencies.
Set the rule
property to: @nx/powerpack-conformance/enforce-module-boundaries
1{
2 "conformance": {
3 "rules": [
4 {
5 "rule": "@nx/powerpack-conformance/enforce-module-boundaries",
6 "options": {
7 // Optional
8 // Can be a boolean or an object with an array of buildTargetNames
9 "requireBuildableDependenciesForBuildableProjects": {
10 // Defaults to ["build"]
11 "buildTargetNames": ["build", "compile"]
12 },
13 // Optional
14 "ignoredCircularDependencies": [["projectA", "projectB"]],
15 // Optional
16 "depConstraints": [
17 {
18 // Must define either `sourceTag` or `allSourceTags`
19 "sourceTag": "string",
20 "allSourceTags": ["string"],
21 // Optional
22 "onlyDependOnLibsWithTags": [],
23 // Optional
24 "notDependOnLibsWithTags": []
25 }
26 ],
27 // Optional
28 "checkDynamicDependenciesExceptions": []
29 }
30 }
31 ]
32 }
33}
34
Options
Property | Type | Default | Description |
---|---|---|---|
ignoredCircularDependencies | Array<[string, string]> | [] | List of project pairs that should be skipped from Circular dependencies checks, including the self-circular dependency check. E.g. ['feature-project-a', 'myapp'] . Project name can be replaced by catch all * for more generic matches. |
checkDynamicDependenciesExceptions | Array<string> | [] | List of imports that should be skipped for Imports of lazy-loaded libraries forbidden checks. E.g. ['@myorg/lazy-project/component/*', '@myorg/other-project'] |
requireBuildableDependenciesForBuildableProjects | boolean | false | Enable to restrict the buildable libs from importing non-buildable libraries |
depConstraints | Array<object> | [] | List of dependency constraints between projects |
Dependency constraints
The depConstraints
is an array of objects representing the constraints defined between source and target projects. A constraint must include sourceTag
or allSourceTags
. The constraints are applied with AND logical operation - for a given source
project the resulting constraints would be all that match its tags.
Property | Type | Description |
---|---|---|
sourceTag | string | Tag that source project must contain to match the constraint |
allSourceTags | Array<string> | List of tags the source project must contain to match the constraint |
onlyDependOnLibsWithTags | Array<string> | The source can depend only on projects that contain at least one of these tags |
notDependOnLibsWithTags | Array<string> | The source can not depend on projects that contain at least one of these tags |
Ensure Owners
This rule requires every project to have an owner defined for the @nx/powerpack-owners
plugin
Set the rule
property to: @nx/powerpack-conformance/ensure-owners
1{
2 "conformance": {
3 "rules": [
4 {
5 "rule": "@nx/powerpack-conformance/ensure-owners"
6 }
7 ]
8 }
9}
10
Custom Conformance Rules
To write your own conformance rule, specify a relative path to a TypeScript or JavaScript file as the rule name:
1{
2 "conformance": {
3 "rules": [
4 {
5 "rule": "./tools/local-conformance-rule.ts"
6 }
7 ]
8 }
9}
10
The rule definition file should look like this:
1import type {
2 ConformanceRule,
3 ConformanceRuleResult,
4 createConformanceRule,
5} from '@nx/powerpack-conformance';
6
7const rule = createConformanceRule({
8 name: 'local-conformance-rule-example',
9 category: 'security', // `consistency`, `maintainability`, `reliability` or `security`
10 reporter: 'project-reporter', // `project-reporter` or `project-files-reporter`
11 implementation: async (context): Promise<ConformanceRuleResult> => {
12 const { projectGraph, ruleOptions } = context;
13 // Your rule logic goes here
14 return {
15 severity: 'low', // 'high', 'medium' or 'low'
16 details: {
17 violations: [
18 // Return an empty array if the rule passes
19 {
20 sourceProject: 'my-project',
21 message: 'This is an informative error message.',
22 },
23 ],
24 },
25 };
26 },
27});
28
29export default rule;
30
Note that the severity of the error is defined by the rule author and can be adjusted based on the specific violations that are found.