eslint-plugin-import-next 2.3.9 → 2.3.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (123) hide show
  1. package/README.md +47 -0
  2. package/package.json +16 -12
  3. package/src/files/foo.js +0 -5
  4. package/src/files/no-default.js +0 -5
  5. package/src/index.d.ts +15 -2812
  6. package/src/index.js +5 -147
  7. package/src/oxlint.d.ts +17 -20
  8. package/src/oxlint.js +0 -18
  9. package/src/rules/consistent-type-specifier-style.js +0 -19
  10. package/src/rules/default.js +0 -7
  11. package/src/rules/dynamic-import-chunkname.js +0 -8
  12. package/src/rules/enforce-dependency-direction.js +2 -39
  13. package/src/rules/enforce-import-order.js +3 -33
  14. package/src/rules/enforce-team-boundaries.js +0 -49
  15. package/src/rules/export.js +0 -9
  16. package/src/rules/exports-last.js +0 -10
  17. package/src/rules/extensions.js +2 -11
  18. package/src/rules/first.js +0 -6
  19. package/src/rules/group-exports.js +0 -13
  20. package/src/rules/max-dependencies.js +0 -16
  21. package/src/rules/named.js +1 -10
  22. package/src/rules/namespace.js +1 -11
  23. package/src/rules/newline-after-import.js +2 -13
  24. package/src/rules/no-absolute-path.js +0 -7
  25. package/src/rules/no-amd.js +1 -18
  26. package/src/rules/no-anonymous-default-export.js +0 -13
  27. package/src/rules/no-barrel-file.js +0 -32
  28. package/src/rules/no-barrel-import.js +0 -25
  29. package/src/rules/no-commonjs.js +0 -18
  30. package/src/rules/no-cross-domain-imports.js +2 -47
  31. package/src/rules/no-cycle.js +2 -135
  32. package/src/rules/no-default-export.js +0 -28
  33. package/src/rules/no-deprecated.js +0 -32
  34. package/src/rules/no-duplicates.js +2 -10
  35. package/src/rules/no-dynamic-require.js +0 -6
  36. package/src/rules/no-empty-named-blocks.js +1 -17
  37. package/src/rules/no-extraneous-dependencies.js +0 -38
  38. package/src/rules/no-full-package-import.js +0 -19
  39. package/src/rules/no-import-module-exports.js +0 -8
  40. package/src/rules/no-internal-modules.js +0 -40
  41. package/src/rules/no-legacy-imports.js +1 -11
  42. package/src/rules/no-mutable-exports.js +0 -14
  43. package/src/rules/no-named-as-default-member.js +0 -11
  44. package/src/rules/no-named-as-default.js +0 -17
  45. package/src/rules/no-named-default.js +0 -5
  46. package/src/rules/no-named-export.js +1 -22
  47. package/src/rules/no-namespace.js +0 -10
  48. package/src/rules/no-nodejs-modules.js +0 -15
  49. package/src/rules/no-relative-packages.js +0 -15
  50. package/src/rules/no-relative-parent-imports.js +0 -11
  51. package/src/rules/no-restricted-paths.js +0 -6
  52. package/src/rules/no-self-import.js +0 -22
  53. package/src/rules/no-unassigned-import.js +0 -14
  54. package/src/rules/no-unresolved.js +0 -16
  55. package/src/rules/no-unused-modules.js +0 -7
  56. package/src/rules/no-useless-path-segments.js +0 -15
  57. package/src/rules/prefer-default-export.js +0 -18
  58. package/src/rules/prefer-direct-import.js +1 -21
  59. package/src/rules/prefer-modern-api.js +0 -21
  60. package/src/rules/prefer-node-protocol.js +0 -15
  61. package/src/rules/prefer-tree-shakeable-imports.js +0 -14
  62. package/src/rules/require-import-approval.js +0 -21
  63. package/src/rules/unambiguous.js +0 -11
  64. package/src/types/index.js +0 -5
  65. package/AGENTS.md +0 -95
  66. package/CHANGELOG.md +0 -170
  67. package/src/files/foo.d.ts +0 -7
  68. package/src/files/no-default.d.ts +0 -6
  69. package/src/rules/consistent-type-specifier-style.d.ts +0 -13
  70. package/src/rules/default.d.ts +0 -9
  71. package/src/rules/dynamic-import-chunkname.d.ts +0 -26
  72. package/src/rules/enforce-dependency-direction.d.ts +0 -27
  73. package/src/rules/enforce-import-order.d.ts +0 -29
  74. package/src/rules/enforce-team-boundaries.d.ts +0 -47
  75. package/src/rules/export.d.ts +0 -17
  76. package/src/rules/exports-last.d.ts +0 -15
  77. package/src/rules/extensions.d.ts +0 -17
  78. package/src/rules/first.d.ts +0 -13
  79. package/src/rules/group-exports.d.ts +0 -15
  80. package/src/rules/max-dependencies.d.ts +0 -26
  81. package/src/rules/named.d.ts +0 -13
  82. package/src/rules/namespace.d.ts +0 -13
  83. package/src/rules/newline-after-import.d.ts +0 -13
  84. package/src/rules/no-absolute-path.d.ts +0 -25
  85. package/src/rules/no-amd.d.ts +0 -21
  86. package/src/rules/no-anonymous-default-export.d.ts +0 -24
  87. package/src/rules/no-barrel-file.d.ts +0 -55
  88. package/src/rules/no-barrel-import.d.ts +0 -48
  89. package/src/rules/no-commonjs.d.ts +0 -28
  90. package/src/rules/no-cross-domain-imports.d.ts +0 -41
  91. package/src/rules/no-cycle.d.ts +0 -102
  92. package/src/rules/no-default-export.d.ts +0 -24
  93. package/src/rules/no-deprecated.d.ts +0 -26
  94. package/src/rules/no-duplicates.d.ts +0 -13
  95. package/src/rules/no-dynamic-require.d.ts +0 -22
  96. package/src/rules/no-empty-named-blocks.d.ts +0 -17
  97. package/src/rules/no-extraneous-dependencies.d.ts +0 -45
  98. package/src/rules/no-full-package-import.d.ts +0 -42
  99. package/src/rules/no-import-module-exports.d.ts +0 -21
  100. package/src/rules/no-internal-modules.d.ts +0 -28
  101. package/src/rules/no-legacy-imports.d.ts +0 -47
  102. package/src/rules/no-mutable-exports.d.ts +0 -22
  103. package/src/rules/no-named-as-default-member.d.ts +0 -15
  104. package/src/rules/no-named-as-default.d.ts +0 -15
  105. package/src/rules/no-named-default.d.ts +0 -15
  106. package/src/rules/no-named-export.d.ts +0 -26
  107. package/src/rules/no-namespace.d.ts +0 -21
  108. package/src/rules/no-nodejs-modules.d.ts +0 -24
  109. package/src/rules/no-relative-packages.d.ts +0 -21
  110. package/src/rules/no-relative-parent-imports.d.ts +0 -22
  111. package/src/rules/no-restricted-paths.d.ts +0 -20
  112. package/src/rules/no-self-import.d.ts +0 -15
  113. package/src/rules/no-unassigned-import.d.ts +0 -20
  114. package/src/rules/no-unresolved.d.ts +0 -20
  115. package/src/rules/no-unused-modules.d.ts +0 -19
  116. package/src/rules/no-useless-path-segments.d.ts +0 -23
  117. package/src/rules/prefer-default-export.d.ts +0 -24
  118. package/src/rules/prefer-direct-import.d.ts +0 -51
  119. package/src/rules/prefer-modern-api.d.ts +0 -47
  120. package/src/rules/prefer-node-protocol.d.ts +0 -19
  121. package/src/rules/prefer-tree-shakeable-imports.d.ts +0 -49
  122. package/src/rules/require-import-approval.d.ts +0 -52
  123. package/src/rules/unambiguous.d.ts +0 -15
@@ -1,29 +1,17 @@
1
1
  "use strict";
2
- /**
3
- * Copyright (c) 2025 Ofri Peretz
4
- * Licensed under the MIT License. Use of this source code is governed by the
5
- * MIT license that can be found in the LICENSE file.
6
- */
7
2
  Object.defineProperty(exports, "__esModule", { value: true });
8
3
  exports.enforceDependencyDirection = void 0;
9
4
  const eslint_devkit_1 = require("@interlace/eslint-devkit");
10
5
  const eslint_devkit_2 = require("@interlace/eslint-devkit");
11
6
  const eslint_devkit_3 = require("@interlace/eslint-devkit");
12
- /**
13
- * Check if two arrays are equal
14
- */
15
7
  function arraysEqual(a, b) {
16
8
  if (a.length !== b.length)
17
9
  return false;
18
10
  return a.every((val, index) => val === b[index]);
19
11
  }
20
- /**
21
- * Extract layer from file path
22
- */
23
12
  function extractLayer(filePath, layerPatterns) {
24
13
  const normalizedPath = (0, eslint_devkit_3.normalizePath)(filePath);
25
14
  for (const pattern of layerPatterns) {
26
- // Check for layer in path segments (handles both /layer/ and layer/ at start)
27
15
  if (normalizedPath.includes(`/${pattern}/`) ||
28
16
  normalizedPath.includes(`\\${pattern}\\`) ||
29
17
  normalizedPath.startsWith(`${pattern}/`) ||
@@ -33,12 +21,9 @@ function extractLayer(filePath, layerPatterns) {
33
21
  }
34
22
  return null;
35
23
  }
36
- /**
37
- * Get layer order index
38
- */
39
24
  function getLayerOrder(layer, layers) {
40
25
  if (!layer) {
41
- return -1; // Unknown layer
26
+ return -1;
42
27
  }
43
28
  const index = layers.indexOf(layer);
44
29
  return index >= 0 ? index : -1;
@@ -132,14 +117,12 @@ exports.enforceDependencyDirection = (0, eslint_devkit_2.createRule)({
132
117
  create(context, [options = {}]) {
133
118
  const filename = context.filename;
134
119
  const { layers: providedLayers, layerPatterns: providedLayerPatterns, allowSameLayer = true, } = options || {};
135
- // Use provided layers or defaults
136
120
  const layers = providedLayers || [
137
121
  'domain',
138
122
  'application',
139
123
  'infrastructure',
140
124
  'presentation',
141
125
  ];
142
- // Default layer patterns
143
126
  const defaultLayerPatterns = [
144
127
  'domain',
145
128
  'application',
@@ -148,26 +131,19 @@ exports.enforceDependencyDirection = (0, eslint_devkit_2.createRule)({
148
131
  'ui',
149
132
  'api',
150
133
  ];
151
- // Use provided layerPatterns, or if layers were provided but layerPatterns weren't (i.e., layerPatterns is still default), use layers
152
134
  let layerPatterns;
153
135
  if (providedLayerPatterns &&
154
136
  !arraysEqual(providedLayerPatterns, defaultLayerPatterns)) {
155
- // layerPatterns was explicitly provided and is different from default
156
137
  layerPatterns = providedLayerPatterns;
157
138
  }
158
139
  else if (providedLayers) {
159
- // layers were provided but layerPatterns weren't, so use layers
160
140
  layerPatterns = providedLayers;
161
141
  }
162
142
  else {
163
- // neither were provided, use defaults
164
143
  layerPatterns = defaultLayerPatterns;
165
144
  }
166
145
  const sourceLayer = extractLayer(filename, layerPatterns);
167
146
  const sourceOrder = getLayerOrder(sourceLayer, layers);
168
- /**
169
- * Check import declarations
170
- */
171
147
  function checkImport(node) {
172
148
  let importPath = '';
173
149
  if (node.type === 'ImportDeclaration') {
@@ -178,19 +154,13 @@ exports.enforceDependencyDirection = (0, eslint_devkit_2.createRule)({
178
154
  importPath = node.source.value;
179
155
  }
180
156
  else {
181
- return; // Dynamic import
157
+ return;
182
158
  }
183
159
  }
184
- // Only check relative imports
185
160
  if (!importPath.startsWith('.')) {
186
161
  return;
187
162
  }
188
- // For relative imports, check the import path string directly for layer patterns
189
- // This works for test cases where paths like '../infrastructure/repository' contain the layer
190
- // The early return above guarantees importPath starts with '.' here.
191
163
  let targetLayer = null;
192
- // Check if import path contains layer patterns
193
- // e.g., '../infrastructure/repository' -> extract 'infrastructure'
194
164
  const segments = importPath.split(/[/\\]/);
195
165
  for (const segment of segments) {
196
166
  if (layerPatterns.includes(segment.toLowerCase())) {
@@ -198,7 +168,6 @@ exports.enforceDependencyDirection = (0, eslint_devkit_2.createRule)({
198
168
  break;
199
169
  }
200
170
  }
201
- // Fallback: try regex matching
202
171
  if (!targetLayer) {
203
172
  for (const pattern of layerPatterns) {
204
173
  const regex = new RegExp(`[/\\\\]${pattern}[/\\\\]`, 'i');
@@ -209,23 +178,17 @@ exports.enforceDependencyDirection = (0, eslint_devkit_2.createRule)({
209
178
  }
210
179
  }
211
180
  const targetOrder = getLayerOrder(targetLayer, layers);
212
- // Skip if layers are unknown
213
181
  if (sourceOrder < 0 || targetOrder < 0) {
214
182
  return;
215
183
  }
216
- // Check if same layer (allowed by default)
217
184
  if (allowSameLayer && sourceLayer === targetLayer) {
218
185
  return;
219
186
  }
220
- // Check dependency direction: lower layers should not depend on higher layers
221
- // Domain (0) should not depend on Application (1), etc.
222
187
  if (targetOrder > sourceOrder) {
223
188
  context.report({
224
189
  node,
225
190
  messageId: 'dependencyDirectionViolation',
226
191
  data: {
227
- // Both are guaranteed non-null here: sourceOrder/targetOrder >= 0
228
- // implies the layers were resolved (see the guard above).
229
192
  sourceLayer: sourceLayer,
230
193
  targetLayer: targetLayer,
231
194
  },
@@ -1,9 +1,4 @@
1
1
  "use strict";
2
- /**
3
- * Copyright (c) 2025 Ofri Peretz
4
- * Licensed under the MIT License. Use of this source code is governed by the
5
- * MIT license that can be found in the LICENSE file.
6
- */
7
2
  Object.defineProperty(exports, "__esModule", { value: true });
8
3
  exports.enforceImportOrder = void 0;
9
4
  const eslint_devkit_1 = require("@interlace/eslint-devkit");
@@ -126,13 +121,9 @@ exports.enforceImportOrder = (0, eslint_devkit_1.createRule)({
126
121
  const imports = [];
127
122
  function getImportType(node) {
128
123
  const source = node.source.value;
129
- // console.log(`DEBUG: getImportType for ${source}`);
130
- // Side-effect imports (no specifiers)
131
- // import 'foo.css';
132
124
  if (node.specifiers.length === 0) {
133
125
  return 'side-effect';
134
126
  }
135
- // Built-in modules (node:)
136
127
  if (source.startsWith('node:') ||
137
128
  [
138
129
  'fs',
@@ -145,10 +136,8 @@ exports.enforceImportOrder = (0, eslint_devkit_1.createRule)({
145
136
  'stream',
146
137
  'child_process',
147
138
  ].includes(source)) {
148
- // console.log('DEBUG: identified as builtin');
149
139
  return 'builtin';
150
140
  }
151
- // Relative imports
152
141
  if (source.startsWith('.')) {
153
142
  if (source.startsWith('../')) {
154
143
  return 'parent';
@@ -158,7 +147,6 @@ exports.enforceImportOrder = (0, eslint_devkit_1.createRule)({
158
147
  }
159
148
  return 'sibling';
160
149
  }
161
- // Internal imports (based on patterns)
162
150
  if (options.internalPatterns && options.internalPatterns.length > 0) {
163
151
  for (const pattern of options.internalPatterns) {
164
152
  if (new RegExp(pattern).test(source)) {
@@ -166,7 +154,6 @@ exports.enforceImportOrder = (0, eslint_devkit_1.createRule)({
166
154
  }
167
155
  }
168
156
  }
169
- // External imports (default)
170
157
  return 'external';
171
158
  }
172
159
  function getGroupRank(importType) {
@@ -177,18 +164,13 @@ exports.enforceImportOrder = (0, eslint_devkit_1.createRule)({
177
164
  let start = node.range[0];
178
165
  let end = node.range[1];
179
166
  const commentsBefore = sourceCode.getCommentsBefore(node);
180
- // getCommentsBefore only returns comments strictly between the previous
181
- // non-comment token and this node, so they always belong to this import —
182
- // include them all in the range.
183
167
  if (commentsBefore.length > 0) {
184
168
  start = commentsBefore[0].range[0];
185
169
  }
186
- // Include semicolon if present
187
170
  const tokenAfter = sourceCode.getTokenAfter(node);
188
171
  if (tokenAfter && tokenAfter.value === ';') {
189
172
  end = tokenAfter.range[1];
190
173
  }
191
- // Include trailing comment on the same line
192
174
  const commentsAfter = sourceCode.getCommentsAfter(node);
193
175
  const sameLineComment = commentsAfter.find((c) => c.loc.start.line === node.loc.end.line);
194
176
  if (sameLineComment) {
@@ -208,8 +190,6 @@ exports.enforceImportOrder = (0, eslint_devkit_1.createRule)({
208
190
  if (imports.length === 0) {
209
191
  return;
210
192
  }
211
- // 1. Check for contiguousness
212
- // Verify no non-whitespace code between imports
213
193
  for (let i = 0; i < imports.length - 1; i++) {
214
194
  const current = imports[i];
215
195
  const next = imports[i + 1];
@@ -217,9 +197,6 @@ exports.enforceImportOrder = (0, eslint_devkit_1.createRule)({
217
197
  includeComments: true,
218
198
  });
219
199
  if (tokensBetween.length > 0) {
220
- // Found something between imports that isn't a comment?
221
- // getTokensBetween includes comments if includeComments: true
222
- // We want to know if there is CODE.
223
200
  const codeTokens = sourceCode.getTokensBetween(current, next, {
224
201
  includeComments: false,
225
202
  });
@@ -228,12 +205,11 @@ exports.enforceImportOrder = (0, eslint_devkit_1.createRule)({
228
205
  node: next,
229
206
  messageId: 'importsNotContiguous',
230
207
  });
231
- return; // Don't try to sort if interspersed with code
208
+ return;
232
209
  }
233
210
  }
234
211
  }
235
212
  const originalImports = [...imports];
236
- // oxlint-disable-next-line unicorn/no-array-sort
237
213
  const sortedImports = Array.from(imports).sort((a, b) => {
238
214
  const typeA = getImportType(a);
239
215
  const typeB = getImportType(b);
@@ -254,7 +230,6 @@ exports.enforceImportOrder = (0, eslint_devkit_1.createRule)({
254
230
  }
255
231
  return 0;
256
232
  });
257
- // Check if order is correct
258
233
  let isSorted = true;
259
234
  for (let i = 0; i < originalImports.length; i++) {
260
235
  if (originalImports[i] !== sortedImports[i]) {
@@ -262,7 +237,6 @@ exports.enforceImportOrder = (0, eslint_devkit_1.createRule)({
262
237
  break;
263
238
  }
264
239
  }
265
- // Check for newlines if sorted
266
240
  if (isSorted && options.newlinesBetween !== 'ignore') {
267
241
  for (let i = 0; i < imports.length - 1; i++) {
268
242
  const current = imports[i];
@@ -272,16 +246,13 @@ exports.enforceImportOrder = (0, eslint_devkit_1.createRule)({
272
246
  const rankCurrent = getGroupRank(typeCurrent);
273
247
  const rankNext = getGroupRank(typeNext);
274
248
  if (rankCurrent !== rankNext) {
275
- // Check lines between
276
249
  const linesBetween = next.loc.start.line - current.loc.end.line;
277
- // console.log(`DEBUG: linesBetween ${linesBetween} | options.newlinesBetween ${options.newlinesBetween}`);
278
250
  if (options.newlinesBetween === 'always' && linesBetween < 2) {
279
- // console.log('DEBUG: Triggering fix due to missing newline');
280
- isSorted = false; // Trigger fix
251
+ isSorted = false;
281
252
  break;
282
253
  }
283
254
  if (options.newlinesBetween === 'never' && linesBetween > 1) {
284
- isSorted = false; // Trigger fix
255
+ isSorted = false;
285
256
  break;
286
257
  }
287
258
  }
@@ -317,7 +288,6 @@ exports.enforceImportOrder = (0, eslint_devkit_1.createRule)({
317
288
  }
318
289
  newCode += getImportText(node) + '\n';
319
290
  }
320
- // Remove last newline
321
291
  newCode = newCode.trimEnd();
322
292
  return fixer.replaceTextRange([rangeStart, rangeEnd], newCode);
323
293
  },
@@ -1,37 +1,13 @@
1
1
  "use strict";
2
- /**
3
- * Copyright (c) 2025 Ofri Peretz
4
- * Licensed under the MIT License. Use of this source code is governed by the
5
- * MIT license that can be found in the LICENSE file.
6
- */
7
2
  Object.defineProperty(exports, "__esModule", { value: true });
8
3
  exports.enforceTeamBoundaries = void 0;
9
4
  const eslint_devkit_1 = require("@interlace/eslint-devkit");
10
- /**
11
- * Translate a user-supplied glob (`foo/**\/*.ts`) into a RegExp.
12
- *
13
- * Important: regex metacharacters in the input must be escaped BEFORE the
14
- * glob tokens are translated. Without escaping, a pattern like `lib\foo` is
15
- * interpreted as `\f` (form feed) and `lib.foo` matches `libXfoo` rather
16
- * than the literal dot the user wrote. CodeQL flags the un-escaped backslash
17
- * specifically (`js/incomplete-sanitization`).
18
- *
19
- * Algorithm: escape all regex metas (including `\`), then unescape and
20
- * translate just the glob tokens `**` and `*` back to their regex form.
21
- */
22
5
  function globToRegex(pattern) {
23
- // Escape regex metacharacters INCLUDING `*`, so the subsequent replaces
24
- // can find the now-escaped `\*\*` / `\*` and translate them back to their
25
- // glob meanings. Without escaping `*`, the `**` in `src/platform/**`
26
- // reaches `new RegExp()` raw and throws "Nothing to repeat".
27
6
  const escaped = pattern.replace(/[.+?^${}()|[\]\\*]/g, '\\$&');
28
7
  return new RegExp(escaped
29
8
  .replace(/\\\*\\\*/g, '.*')
30
9
  .replace(/\\\*/g, '[^/]*'));
31
10
  }
32
- /**
33
- * Determine which team owns this file based on path patterns
34
- */
35
11
  function getFileTeam(filePath, teams) {
36
12
  for (const team of teams) {
37
13
  for (const pattern of team.paths) {
@@ -42,9 +18,6 @@ function getFileTeam(filePath, teams) {
42
18
  }
43
19
  return null;
44
20
  }
45
- /**
46
- * Determine which team owns the imported module
47
- */
48
21
  function getImportTeam(importPath, teams) {
49
22
  for (const team of teams) {
50
23
  for (const pattern of team.paths) {
@@ -52,7 +25,6 @@ function getImportTeam(importPath, teams) {
52
25
  return team;
53
26
  }
54
27
  }
55
- // Check public packages
56
28
  if (team.publicPackages) {
57
29
  for (const pkg of team.publicPackages) {
58
30
  if (importPath.startsWith(pkg)) {
@@ -63,31 +35,21 @@ function getImportTeam(importPath, teams) {
63
35
  }
64
36
  return null;
65
37
  }
66
- /**
67
- * Check if import path is external (node_modules)
68
- */
69
38
  function isExternalImport(importPath) {
70
- // Relative imports start with . or ..
71
39
  if (importPath.startsWith('.') || importPath.startsWith('/')) {
72
40
  return false;
73
41
  }
74
- // Alias imports (configurable patterns)
75
42
  if (importPath.startsWith('@/') || importPath.startsWith('~/')) {
76
43
  return false;
77
44
  }
78
- // Internal project paths (src/, lib/, packages/, apps/)
79
45
  if (importPath.startsWith('src/') ||
80
46
  importPath.startsWith('lib/') ||
81
47
  importPath.startsWith('packages/') ||
82
48
  importPath.startsWith('apps/')) {
83
49
  return false;
84
50
  }
85
- // Otherwise, likely external package
86
51
  return true;
87
52
  }
88
- /**
89
- * Check if path is in shared paths
90
- */
91
53
  function isSharedPath(importPath, sharedPaths) {
92
54
  for (const shared of sharedPaths) {
93
55
  if (globToRegex(shared).test(importPath)) {
@@ -163,15 +125,11 @@ exports.enforceTeamBoundaries = (0, eslint_devkit_1.createRule)({
163
125
  ],
164
126
  create(context, [options]) {
165
127
  const { teams, sharedPaths = [], allowExternalPackages = true } = options;
166
- // Get the file's team ownership
167
128
  const filename = context.filename;
168
129
  const sourceTeam = getFileTeam(filename, teams);
169
- // If file doesn't belong to any team, skip checking
170
130
  if (!sourceTeam) {
171
131
  return {};
172
132
  }
173
- // Narrowed binding: the early return above guarantees sourceTeam is non-null,
174
- // and closures cannot rely on that narrowing without re-checking.
175
133
  const owningTeam = sourceTeam;
176
134
  function checkImport(node) {
177
135
  let importPath = null;
@@ -192,30 +150,23 @@ exports.enforceTeamBoundaries = (0, eslint_devkit_1.createRule)({
192
150
  }
193
151
  if (!importPath)
194
152
  return;
195
- // Allow external packages
196
153
  if (allowExternalPackages && isExternalImport(importPath)) {
197
154
  return;
198
155
  }
199
- // Allow shared paths
200
156
  if (isSharedPath(importPath, sharedPaths)) {
201
157
  return;
202
158
  }
203
- // Get target team
204
159
  const targetTeam = getImportTeam(importPath, teams);
205
- // If import doesn't belong to any team, allow it (might be shared code)
206
160
  if (!targetTeam) {
207
161
  return;
208
162
  }
209
- // Same team - always allowed
210
163
  if (targetTeam.team === owningTeam.team) {
211
164
  return;
212
165
  }
213
- // Check if target team is in allowed dependencies
214
166
  const allowedDeps = owningTeam.allowedDependencies || [];
215
167
  if (allowedDeps.includes(targetTeam.team)) {
216
168
  return;
217
169
  }
218
- // Unauthorized cross-team import!
219
170
  context.report({
220
171
  node,
221
172
  messageId: 'unauthorizedTeamImport',
@@ -1,9 +1,4 @@
1
1
  "use strict";
2
- /**
3
- * Copyright (c) 2025 Ofri Peretz
4
- * Licensed under the MIT License. Use of this source code is governed by the
5
- * MIT license that can be found in the LICENSE file.
6
- */
7
2
  Object.defineProperty(exports, "__esModule", { value: true });
8
3
  exports.exportRule = void 0;
9
4
  const eslint_devkit_1 = require("@interlace/eslint-devkit");
@@ -71,7 +66,6 @@ exports.exportRule = (0, eslint_devkit_1.createRule)({
71
66
  checkDefaultExport(node);
72
67
  },
73
68
  ExportNamedDeclaration(node) {
74
- // Export with declaration: export const foo = 1;
75
69
  if (node.declaration) {
76
70
  if (node.declaration.type === eslint_devkit_1.AST_NODE_TYPES.VariableDeclaration) {
77
71
  node.declaration.declarations.forEach((decl) => {
@@ -94,7 +88,6 @@ exports.exportRule = (0, eslint_devkit_1.createRule)({
94
88
  }
95
89
  }
96
90
  }
97
- // Export specifiers: export { foo, bar };
98
91
  node.specifiers.forEach((spec) => {
99
92
  const exportedName = spec.exported.type === eslint_devkit_1.AST_NODE_TYPES.Identifier
100
93
  ? spec.exported.name
@@ -108,12 +101,10 @@ exports.exportRule = (0, eslint_devkit_1.createRule)({
108
101
  });
109
102
  },
110
103
  ExportAllDeclaration(node) {
111
- // export * as name from '...'
112
104
  if (node.exported) {
113
105
  const exportedName = node.exported.name;
114
106
  checkAndAddExport(exportedName, node);
115
107
  }
116
- // Regular export * doesn't create named conflicts we can statically detect
117
108
  },
118
109
  };
119
110
  },
@@ -1,9 +1,4 @@
1
1
  "use strict";
2
- /**
3
- * Copyright (c) 2025 Ofri Peretz
4
- * Licensed under the MIT License. Use of this source code is governed by the
5
- * MIT license that can be found in the LICENSE file.
6
- */
7
2
  Object.defineProperty(exports, "__esModule", { value: true });
8
3
  exports.exportsLast = void 0;
9
4
  const eslint_devkit_1 = require("@interlace/eslint-devkit");
@@ -36,7 +31,6 @@ exports.exportsLast = (0, eslint_devkit_1.createRule)({
36
31
  'Program:exit'(node) {
37
32
  const body = node.body;
38
33
  let lastNonExportIndex = -1;
39
- // Find all export statements and non-export statements
40
34
  const exportIndices = [];
41
35
  const nonExportIndices = [];
42
36
  body.forEach((statement, index) => {
@@ -44,11 +38,8 @@ exports.exportsLast = (0, eslint_devkit_1.createRule)({
44
38
  statement.type === eslint_devkit_1.AST_NODE_TYPES.ExportNamedDeclaration ||
45
39
  statement.type === eslint_devkit_1.AST_NODE_TYPES.ExportAllDeclaration;
46
40
  if (isExport) {
47
- // Skip export declarations that are also declarations (export const x = 1)
48
- // These often need to appear where they're declared
49
41
  if (statement.type === eslint_devkit_1.AST_NODE_TYPES.ExportNamedDeclaration &&
50
42
  statement.declaration) {
51
- // This is an inline export, treat as non-export for ordering
52
43
  nonExportIndices.push(index);
53
44
  }
54
45
  else {
@@ -62,7 +53,6 @@ exports.exportsLast = (0, eslint_devkit_1.createRule)({
62
53
  if (nonExportIndices.length > 0) {
63
54
  lastNonExportIndex = Math.max(...nonExportIndices);
64
55
  }
65
- // Check if any export appears before the last non-export
66
56
  for (const exportIndex of exportIndices) {
67
57
  if (exportIndex < lastNonExportIndex) {
68
58
  context.report({
@@ -1,9 +1,4 @@
1
1
  "use strict";
2
- /**
3
- * Copyright (c) 2025 Ofri Peretz
4
- * Licensed under the MIT License. Use of this source code is governed by the
5
- * MIT license that can be found in the LICENSE file.
6
- */
7
2
  Object.defineProperty(exports, "__esModule", { value: true });
8
3
  exports.extensions = void 0;
9
4
  const tslib_1 = require("tslib");
@@ -84,8 +79,8 @@ exports.extensions = (0, eslint_devkit_1.createRule)({
84
79
  ImportDeclaration(node) {
85
80
  const source = node.source.value;
86
81
  if (!source.startsWith('.'))
87
- return; // Only check relative imports
88
- const ext = node_path_1.default.extname(source).slice(1); // remove dot
82
+ return;
83
+ const ext = node_path_1.default.extname(source).slice(1);
89
84
  const expected = pattern[ext] || defaultBehavior;
90
85
  if (ext && expected === 'never') {
91
86
  context.report({
@@ -97,14 +92,10 @@ exports.extensions = (0, eslint_devkit_1.createRule)({
97
92
  });
98
93
  }
99
94
  else if (!ext) {
100
- // Hard to know what the extension *should* be without checking file system
101
- // But if default is 'always', we might flag it.
102
- // For now, let's assume if it's missing and we expect 'always', it's a problem.
103
95
  if (defaultBehavior === 'always') {
104
96
  context.report({
105
97
  node: node.source,
106
98
  messageId: 'missingExtension',
107
- // Can't fix without knowing extension
108
99
  });
109
100
  }
110
101
  }
@@ -1,9 +1,4 @@
1
1
  "use strict";
2
- /**
3
- * Copyright (c) 2025 Ofri Peretz
4
- * Licensed under the MIT License. Use of this source code is governed by the
5
- * MIT license that can be found in the LICENSE file.
6
- */
7
2
  Object.defineProperty(exports, "__esModule", { value: true });
8
3
  exports.first = void 0;
9
4
  const eslint_devkit_1 = require("@interlace/eslint-devkit");
@@ -48,7 +43,6 @@ exports.first = (0, eslint_devkit_1.createRule)({
48
43
  }
49
44
  },
50
45
  };
51
- // oxlint-disable-next-line consistent-function-scoping
52
46
  function isDirective(node) {
53
47
  return (node.type === 'ExpressionStatement' &&
54
48
  node.expression.type === 'Literal' &&
@@ -1,9 +1,4 @@
1
1
  "use strict";
2
- /**
3
- * Copyright (c) 2025 Ofri Peretz
4
- * Licensed under the MIT License. Use of this source code is governed by the
5
- * MIT license that can be found in the LICENSE file.
6
- */
7
2
  Object.defineProperty(exports, "__esModule", { value: true });
8
3
  exports.groupExports = void 0;
9
4
  const eslint_devkit_1 = require("@interlace/eslint-devkit");
@@ -32,15 +27,12 @@ exports.groupExports = (0, eslint_devkit_1.createRule)({
32
27
  },
33
28
  defaultOptions: [],
34
29
  create(context) {
35
- // Track separate export statements (not counting inline exports)
36
30
  const separateExports = [];
37
31
  const reExportSources = new Map();
38
32
  return {
39
33
  ExportNamedDeclaration(node) {
40
- // Only track export specifier lists, not inline declarations
41
34
  if (!node.declaration && node.specifiers.length > 0) {
42
35
  if (node.source) {
43
- // Re-export from another module
44
36
  const source = node.source.value;
45
37
  if (!reExportSources.has(source)) {
46
38
  reExportSources.set(source, []);
@@ -48,15 +40,12 @@ exports.groupExports = (0, eslint_devkit_1.createRule)({
48
40
  reExportSources.get(source)?.push(node);
49
41
  }
50
42
  else {
51
- // Local export
52
43
  separateExports.push(node);
53
44
  }
54
45
  }
55
46
  },
56
47
  'Program:exit'() {
57
- // Report if there are multiple separate local exports that could be combined
58
48
  if (separateExports.length > 1) {
59
- // Report all but the first one
60
49
  for (let i = 1; i < separateExports.length; i++) {
61
50
  context.report({
62
51
  node: separateExports[i],
@@ -64,10 +53,8 @@ exports.groupExports = (0, eslint_devkit_1.createRule)({
64
53
  });
65
54
  }
66
55
  }
67
- // Report if there are multiple re-exports from the same source
68
56
  for (const [, exports] of reExportSources) {
69
57
  if (exports.length > 1) {
70
- // Report all but the first one
71
58
  for (let i = 1; i < exports.length; i++) {
72
59
  context.report({
73
60
  node: exports[i],
@@ -1,9 +1,4 @@
1
1
  "use strict";
2
- /**
3
- * Copyright (c) 2025 Ofri Peretz
4
- * Licensed under the MIT License. Use of this source code is governed by the
5
- * MIT license that can be found in the LICENSE file.
6
- */
7
2
  Object.defineProperty(exports, "__esModule", { value: true });
8
3
  exports.maxDependencies = void 0;
9
4
  const eslint_devkit_1 = require("@interlace/eslint-devkit");
@@ -92,7 +87,6 @@ exports.maxDependencies = (0, eslint_devkit_1.createRule)({
92
87
  if (!filename) {
93
88
  return {};
94
89
  }
95
- // Check if file should be ignored
96
90
  const shouldIgnoreFile = ignoreFiles.some((pattern) => {
97
91
  if (pattern.includes('*')) {
98
92
  const regex = new RegExp(pattern.replace(/\*/g, '.*'));
@@ -105,19 +99,15 @@ exports.maxDependencies = (0, eslint_devkit_1.createRule)({
105
99
  }
106
100
  const dependencies = new Set();
107
101
  function shouldCountImport(importPath, node) {
108
- // Skip ignored imports
109
102
  if (ignoreImports.includes(importPath)) {
110
103
  return false;
111
104
  }
112
- // Skip type-only imports if configured
113
105
  if (ignoreTypeImports && node.importKind === 'type') {
114
106
  return false;
115
107
  }
116
- // Skip relative imports (internal modules)
117
108
  if (importPath.startsWith('./') || importPath.startsWith('../')) {
118
109
  return false;
119
110
  }
120
- // Skip Node.js built-ins
121
111
  const nodeBuiltins = [
122
112
  'assert',
123
113
  'buffer',
@@ -154,15 +144,12 @@ exports.maxDependencies = (0, eslint_devkit_1.createRule)({
154
144
  return true;
155
145
  }
156
146
  function shouldCountRequire(importPath) {
157
- // Skip ignored imports
158
147
  if (ignoreImports.includes(importPath)) {
159
148
  return false;
160
149
  }
161
- // Skip relative imports
162
150
  if (importPath.startsWith('./') || importPath.startsWith('../')) {
163
151
  return false;
164
152
  }
165
- // Skip Node.js built-ins
166
153
  const nodeBuiltins = [
167
154
  'assert',
168
155
  'buffer',
@@ -199,7 +186,6 @@ exports.maxDependencies = (0, eslint_devkit_1.createRule)({
199
186
  return true;
200
187
  }
201
188
  function addDependency(importPath) {
202
- // Extract package name from scoped packages or regular packages
203
189
  const packageName = importPath.startsWith('@')
204
190
  ? importPath.split('/').slice(0, 2).join('/')
205
191
  : importPath.split('/')[0];
@@ -214,7 +200,6 @@ exports.maxDependencies = (0, eslint_devkit_1.createRule)({
214
200
  }
215
201
  },
216
202
  CallExpression(node) {
217
- // Check require() calls
218
203
  if (node.callee.type === 'Identifier' &&
219
204
  node.callee.name === 'require' &&
220
205
  node.arguments.length === 1) {
@@ -226,7 +211,6 @@ exports.maxDependencies = (0, eslint_devkit_1.createRule)({
226
211
  }
227
212
  }
228
213
  },
229
- // Handle dynamic imports (import() expressions)
230
214
  ImportExpression(node) {
231
215
  const source = node.source;
232
216
  if (source.type === 'Literal' && typeof source.value === 'string') {