eslint-plugin-import-boundaries 0.2.1 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -116,8 +116,8 @@ Prevent violations of your architecture:
116
116
  {
117
117
  dir: 'application',
118
118
  alias: '@application',
119
- allowImportsFrom: ['@domain'], // Only allow imports from @domain
120
- denyImportsFrom: ['@infrastructure'], // Deny imports from @infrastructure (dependency inversion)
119
+ allowImportsFrom: ['@domain'], // Only allow imports from @domain (deny-all by default)
120
+ // Note: denyImportsFrom is redundant here - anything not in allowImportsFrom is already denied
121
121
  }
122
122
  ```
123
123
 
@@ -151,7 +151,7 @@ Boundaries can be nested, and each boundary must explicitly declare its import r
151
151
  dir: 'interface',
152
152
  alias: '@interface',
153
153
  allowImportsFrom: ['@application', '@public-use-cases'],
154
- denyImportsFrom: ['@use-cases'], // Can allow parent and specific child, but deny intermediate boundary
154
+ denyImportsFrom: ['@use-cases'], // Deny specific sub-boundary even though parent @application is allowed
155
155
  },
156
156
  ],
157
157
  }
@@ -159,11 +159,19 @@ Boundaries can be nested, and each boundary must explicitly declare its import r
159
159
 
160
160
  **Key behaviors:**
161
161
 
162
- - Each boundary must explicitly declare its rules (no inheritance)
163
- - Files in boundaries without rules resolve to their nearest ancestor with rules (or are rejected if no ancestor has rules)
162
+ - Each boundary has rules: explicit (via `allowImportsFrom`/`denyImportsFrom`) or implicit "deny all" (if neither is specified)
163
+ - Each boundary uses its own rules directly (no inheritance from parent boundaries)
164
164
  - Rules work the same regardless of nesting depth (flat rule checking)
165
165
  - You can selectively allow/deny specific nested boundaries
166
- - A boundary is considered to have rules if it defines `allowImportsFrom`, `denyImportsFrom`, or `allowTypeImportsFrom` (even if empty arrays)
166
+ - Files resolve to their most specific boundary (longest matching path), which determines the rules to apply
167
+
168
+ **Rule semantics:**
169
+
170
+ - If both `allowImportsFrom` and `denyImportsFrom` exist: `allowImportsFrom` takes precedence (items in allow list are allowed even if also in deny list)
171
+ - If only `allowImportsFrom`: deny-all by default (only items in allow list are allowed)
172
+ - If only `denyImportsFrom`: allow-all by default (everything except deny list is allowed)
173
+ - If neither: deny-all by default (strictest)
174
+ - **Important**: When `allowImportsFrom` is specified, `denyImportsFrom` can deny specific sub-boundaries (e.g. deny `@utils` within allowed `@application`), but is otherwise redundant since anything not in the allow list is already denied by default. Note that this works recursively: It is possible to allow a boundary within a denied boundary within an allowed boundary, and so on.
167
175
 
168
176
  ### 4. Type-Only Imports
169
177
 
@@ -220,8 +228,8 @@ import { something } from "@application"; // When inside @application boundary
220
228
  {
221
229
  dir: 'application',
222
230
  alias: '@application',
223
- allowImportsFrom: ['@domain'], // Application uses domain
224
- denyImportsFrom: ['@infrastructure', '@interface', '@composition'], // Dependency inversion
231
+ allowImportsFrom: ['@domain'], // Application uses domain (deny-all by default)
232
+ // Note: denyImportsFrom is redundant here - those boundaries are already denied
225
233
  },
226
234
  {
227
235
  dir: 'infrastructure',
@@ -100,22 +100,6 @@ function resolveToBoundary(filename, boundaries) {
100
100
  return null;
101
101
  }
102
102
  /**
103
- * Resolve a file to the nearest boundary that has rules specified.
104
- * If no boundaries with rules are found, returns null.
105
- * Used for file boundaries - allows inheritance from ancestors with rules.
106
- *
107
- * @param filename - Absolute filename
108
- * @param boundaries - Array of all boundaries
109
- * @returns The nearest boundary with rules, or null if none found
110
- */
111
- function resolveToSpecifiedBoundary(filename, boundaries) {
112
- const specifiedBoundaries = boundaries.filter((b) => isInsideDir(b.absDir, filename)).filter((b) => b.allowImportsFrom !== void 0 || b.denyImportsFrom !== void 0 || b.allowTypeImportsFrom !== void 0);
113
- if (specifiedBoundaries.length > 0) return specifiedBoundaries.sort((a, b) => b.absDir.length - a.absDir.length)[0];
114
- const ancestors = boundaries.filter((b) => b.allowImportsFrom !== void 0 || b.denyImportsFrom !== void 0 || b.allowTypeImportsFrom !== void 0).filter((b) => isInsideDir(b.absDir, filename));
115
- if (ancestors.length > 0) return ancestors.sort((a, b) => b.absDir.length - a.absDir.length)[0];
116
- return null;
117
- }
118
- /**
119
103
  * Get metadata about the current file being linted.
120
104
  * Results are cached per file to avoid recomputation.
121
105
  *
@@ -128,7 +112,7 @@ function getFileData(filename, boundaries) {
128
112
  return {
129
113
  isValid: true,
130
114
  fileDir: path.dirname(filename),
131
- fileBoundary: resolveToSpecifiedBoundary(filename, boundaries)
115
+ fileBoundary: resolveToBoundary(filename, boundaries)
132
116
  };
133
117
  }
134
118
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "eslint-plugin-import-boundaries",
3
3
  "type": "module",
4
- "version": "0.2.1",
4
+ "version": "0.2.2",
5
5
  "description": "Enforce architectural boundaries with deterministic import paths",
6
6
  "author": "ClassicalMoser",
7
7
  "license": "ISC",