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,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.noDeprecated = void 0;
9
4
  const eslint_devkit_1 = require("@interlace/eslint-devkit");
@@ -88,7 +83,6 @@ exports.noDeprecated = (0, eslint_devkit_1.createRule)({
88
83
  if (!filename) {
89
84
  return {};
90
85
  }
91
- // Track deprecated items found in the current file
92
86
  const deprecatedItems = new Map();
93
87
  function isAllowed(name) {
94
88
  return allow.includes(name);
@@ -97,24 +91,19 @@ exports.noDeprecated = (0, eslint_devkit_1.createRule)({
97
91
  const lines = comment.split('\n');
98
92
  for (const line of lines) {
99
93
  const trimmed = line.trim();
100
- // Check for @deprecated tag
101
94
  for (const marker of deprecationMarkers) {
102
95
  if (trimmed.includes(marker)) {
103
96
  const afterMarker = trimmed
104
97
  .substring(trimmed.indexOf(marker) + marker.length)
105
98
  .trim();
106
- // Try to extract reason and replacement
107
99
  let reason;
108
100
  let replacement;
109
- // Look for common patterns like "Use X instead" or "Replaced by Y"
110
101
  const insteadMatch = afterMarker.match(/(?:use|replaced by|see)\s+([^\s]+(?:\s+[^\s]+)*?)(?:\s|$)/i);
111
102
  if (insteadMatch) {
112
- // Remove common trailing words
113
103
  replacement = insteadMatch[1]
114
104
  .trim()
115
105
  .replace(/\s+instead$|\s+or$|\s+as$|\s+with$/i, '');
116
106
  }
117
- // The rest is usually the reason
118
107
  const reasonText = afterMarker
119
108
  .replace(/use\s+[^.]*[.]?/i, '')
120
109
  .replace(/replaced by\s+[^.]*[.]?/i, '')
@@ -133,14 +122,12 @@ exports.noDeprecated = (0, eslint_devkit_1.createRule)({
133
122
  return;
134
123
  const sourceCode = context.sourceCode;
135
124
  const comments = sourceCode.getCommentsBefore(node);
136
- // Also check leading comments attached to the node
137
125
  const allComments = [...comments];
138
126
  if ('leadingComments' in node && Array.isArray(node.leadingComments)) {
139
127
  allComments.push(...node.leadingComments);
140
128
  }
141
129
  for (const comment of allComments) {
142
130
  if (comment.type === 'Block' && comment.value.includes('*')) {
143
- // JSDoc comment
144
131
  const deprecationInfo = parseJSDocDeprecated(comment.value);
145
132
  if (deprecationInfo.deprecated) {
146
133
  deprecatedItems.set(name, {
@@ -156,10 +143,8 @@ exports.noDeprecated = (0, eslint_devkit_1.createRule)({
156
143
  function checkDecoratorsForDeprecation(node, name) {
157
144
  if (!checkDecorators)
158
145
  return;
159
- // Check for @deprecated decorator in TypeScript
160
146
  if ('decorators' in node &&
161
147
  Array.isArray(node.decorators)) {
162
- // The Array.isArray guard above proves decorators is an array.
163
148
  const decorators = node.decorators;
164
149
  for (const decorator of decorators) {
165
150
  const dec = decorator;
@@ -214,7 +199,6 @@ exports.noDeprecated = (0, eslint_devkit_1.createRule)({
214
199
  });
215
200
  }
216
201
  return {
217
- // Check for deprecated declarations in the current file
218
202
  VariableDeclaration(node) {
219
203
  node.declarations.forEach((decl) => {
220
204
  if (decl.id.type === 'Identifier') {
@@ -237,13 +221,11 @@ exports.noDeprecated = (0, eslint_devkit_1.createRule)({
237
221
  },
238
222
  MethodDefinition(node) {
239
223
  if (node.key.type === 'Identifier') {
240
- // For methods, check comments on both the method node and the key
241
224
  checkComments(node, node.key.name);
242
225
  checkComments(node.key, node.key.name);
243
226
  checkDecoratorsForDeprecation(node, node.key.name);
244
227
  }
245
228
  },
246
- // Check for deprecated exports in the current file
247
229
  ExportNamedDeclaration(node) {
248
230
  if (node.declaration) {
249
231
  if (node.declaration.type === 'VariableDeclaration') {
@@ -265,7 +247,6 @@ exports.noDeprecated = (0, eslint_devkit_1.createRule)({
265
247
  checkDecoratorsForDeprecation(node.declaration, node.declaration.id.name);
266
248
  }
267
249
  }
268
- // Check exported specifiers
269
250
  if (node.specifiers) {
270
251
  node.specifiers.forEach((specifier) => {
271
252
  if (specifier.exported.type === 'Identifier') {
@@ -278,16 +259,9 @@ exports.noDeprecated = (0, eslint_devkit_1.createRule)({
278
259
  checkComments(node, 'default');
279
260
  checkDecoratorsForDeprecation(node, 'default');
280
261
  },
281
- // Check for usage of deprecated imported items
282
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
283
262
  ImportDeclaration(node) {
284
- // This would need cross-file analysis to check if imported items are deprecated
285
- // For now, we'll focus on deprecated items within the same file
286
263
  },
287
- // Check for usage of deprecated items
288
264
  MemberExpression(node) {
289
- // No has() pre-check: reportDeprecatedUsage bails out when the
290
- // object name has no recorded deprecation info.
291
265
  if (node.object.type === 'Identifier' &&
292
266
  node.property.type === 'Identifier') {
293
267
  reportDeprecatedUsage(node, node.object.name, `${node.object.name}.${node.property.name}`);
@@ -306,9 +280,7 @@ exports.noDeprecated = (0, eslint_devkit_1.createRule)({
306
280
  }
307
281
  },
308
282
  Identifier(node) {
309
- // Check if this identifier references a deprecated item
310
283
  if (deprecatedItems.has(node.name)) {
311
- // Only report if it's not part of a declaration
312
284
  const parent = node.parent;
313
285
  if (parent &&
314
286
  ![
@@ -319,22 +291,18 @@ exports.noDeprecated = (0, eslint_devkit_1.createRule)({
319
291
  'ExportSpecifier',
320
292
  'MethodDefinition',
321
293
  ].includes(parent.type)) {
322
- // Don't report if this identifier is the callee of a CallExpression (handled separately)
323
294
  if (parent.type === 'CallExpression' &&
324
295
  parent.callee === node) {
325
296
  return;
326
297
  }
327
- // Don't report if this identifier is the callee of a NewExpression (handled separately)
328
298
  if (parent.type === 'NewExpression' &&
329
299
  parent.callee === node) {
330
300
  return;
331
301
  }
332
- // Don't report if this identifier is the object of a MemberExpression (handled separately)
333
302
  if (parent.type === 'MemberExpression' &&
334
303
  parent.object === node) {
335
304
  return;
336
305
  }
337
- // Don't report if this identifier is the property of a MemberExpression (handled separately)
338
306
  if (parent.type === 'MemberExpression' &&
339
307
  parent.property === node) {
340
308
  return;
@@ -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.noDuplicates = void 0;
9
4
  const eslint_devkit_1 = require("@interlace/eslint-devkit");
@@ -51,22 +46,19 @@ exports.noDuplicates = (0, eslint_devkit_1.createRule)({
51
46
  node: duplicate,
52
47
  messageId: 'noDuplicates',
53
48
  fix(fixer) {
54
- // Simple fix: if both are named imports, merge them
55
49
  const firstHasDefault = first.specifiers.some((s) => s.type === 'ImportDefaultSpecifier');
56
50
  const duplicateHasDefault = duplicate.specifiers.some((s) => s.type === 'ImportDefaultSpecifier');
57
51
  const firstHasNamespace = first.specifiers.some((s) => s.type === 'ImportNamespaceSpecifier');
58
52
  const duplicateHasNamespace = duplicate.specifiers.some((s) => s.type === 'ImportNamespaceSpecifier');
59
53
  if (firstHasNamespace || duplicateHasNamespace) {
60
- return null; // Too complex to merge namespace imports automatically
54
+ return null;
61
55
  }
62
56
  if (firstHasDefault && duplicateHasDefault) {
63
- return null; // Cannot have two default imports
57
+ return null;
64
58
  }
65
- // If duplicate is empty (side-effect), just remove it
66
59
  if (duplicate.specifiers.length === 0) {
67
60
  return fixer.remove(duplicate);
68
61
  }
69
- // If first is empty (side-effect), we can't easily merge into it without more logic
70
62
  if (first.specifiers.length === 0) {
71
63
  return null;
72
64
  }
@@ -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.noDynamicRequire = void 0;
9
4
  const eslint_devkit_1 = require("@interlace/eslint-devkit");
@@ -58,7 +53,6 @@ exports.noDynamicRequire = (0, eslint_devkit_1.createRule)({
58
53
  }
59
54
  return {
60
55
  CallExpression(node) {
61
- // Check require() calls
62
56
  if (node.callee.type === eslint_devkit_1.AST_NODE_TYPES.Identifier &&
63
57
  node.callee.name === 'require' &&
64
58
  node.arguments.length >= 1) {
@@ -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.noEmptyNamedBlocks = void 0;
9
4
  const eslint_devkit_1 = require("@interlace/eslint-devkit");
@@ -37,24 +32,18 @@ exports.noEmptyNamedBlocks = (0, eslint_devkit_1.createRule)({
37
32
  create(context) {
38
33
  return {
39
34
  ImportDeclaration(node) {
40
- // Check if this import has empty named imports: import {} from 'foo'
41
- // or import Foo, {} from 'foo'
42
35
  const hasDefaultImport = node.specifiers.some((spec) => spec.type === 'ImportDefaultSpecifier');
43
36
  const hasNamespaceImport = node.specifiers.some((spec) => spec.type === 'ImportNamespaceSpecifier');
44
37
  const namedImports = node.specifiers.filter((spec) => spec.type === 'ImportSpecifier');
45
- // Get the source code
46
38
  const sourceCode = context.sourceCode;
47
39
  const importText = sourceCode.getText(node);
48
- // Check for empty braces pattern: {}
49
40
  const hasEmptyBraces = /\{\s*\}/.test(importText);
50
41
  if (hasEmptyBraces && namedImports.length === 0) {
51
- // If there's only empty braces (no default, no namespace)
52
42
  if (!hasDefaultImport && !hasNamespaceImport) {
53
43
  context.report({
54
44
  node,
55
45
  messageId: 'emptyNamedBlock',
56
46
  fix(fixer) {
57
- // Remove the entire import statement
58
47
  return fixer.remove(node);
59
48
  },
60
49
  suggest: [
@@ -68,13 +57,10 @@ exports.noEmptyNamedBlocks = (0, eslint_devkit_1.createRule)({
68
57
  });
69
58
  }
70
59
  else if (hasDefaultImport) {
71
- // Has default import with empty braces: import Foo, {} from 'bar'
72
- // Fix to: import Foo from 'bar'
73
60
  context.report({
74
61
  node,
75
62
  messageId: 'emptyNamedBlock',
76
63
  fix(fixer) {
77
- // Remove the ", {}" part
78
64
  const fixedText = importText.replace(/,\s*\{\s*\}/, '');
79
65
  return fixer.replaceText(node, fixedText);
80
66
  },
@@ -92,11 +78,9 @@ exports.noEmptyNamedBlocks = (0, eslint_devkit_1.createRule)({
92
78
  }
93
79
  },
94
80
  ExportNamedDeclaration(node) {
95
- // Check for: export {} from 'foo' or export {}
96
81
  if (node.specifiers.length === 0 &&
97
82
  !node.declaration &&
98
- node.source // Only for re-exports, local `export {}` is technically valid but useless
99
- ) {
83
+ node.source) {
100
84
  context.report({
101
85
  node,
102
86
  messageId: 'emptyNamedBlock',
@@ -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.noExtraneousDependencies = void 0;
9
4
  const eslint_devkit_1 = require("@interlace/eslint-devkit");
@@ -139,67 +134,49 @@ exports.noExtraneousDependencies = (0, eslint_devkit_1.createRule)({
139
134
  if (!filename) {
140
135
  return {};
141
136
  }
142
- // Use provided package.json if available (for testing)
143
137
  let resolvedPackageJson = null;
144
138
  if (packageJson) {
145
- // Use directly provided package.json (for testing)
146
139
  resolvedPackageJson = packageJson;
147
140
  }
148
141
  else if (packageJsonPath) {
149
- // Use specified package.json file
150
142
  resolvedPackageJson = (0, eslint_devkit_3.readJsonFileSync)(packageJsonPath);
151
143
  if (!resolvedPackageJson) {
152
- // Invalid package.json - skip
153
144
  return {};
154
145
  }
155
146
  }
156
147
  else {
157
- // Find package.json automatically
158
148
  const packageJsonFile = (0, eslint_devkit_3.findFileUpward)('package.json', (0, eslint_devkit_4.getDirname)(filename));
159
149
  if (!packageJsonFile) {
160
- // No package.json found - skip this rule
161
150
  return {};
162
151
  }
163
- // Read and parse package.json
164
152
  resolvedPackageJson = (0, eslint_devkit_3.readJsonFileSync)(packageJsonFile);
165
153
  if (!resolvedPackageJson) {
166
- // Invalid package.json - skip
167
154
  return {};
168
155
  }
169
156
  }
170
- // Build allowed packages map
171
157
  const allowedPackages = new Set();
172
- // Add dependencies
173
158
  if (resolvedPackageJson?.dependencies) {
174
159
  Object.keys(resolvedPackageJson.dependencies).forEach((pkg) => allowedPackages.add(pkg));
175
160
  }
176
- // Add dev dependencies if allowed
177
161
  if (devDependencies && resolvedPackageJson?.devDependencies) {
178
162
  Object.keys(resolvedPackageJson.devDependencies).forEach((pkg) => allowedPackages.add(pkg));
179
163
  }
180
- // Add optional dependencies if allowed
181
164
  if (optionalDependencies && resolvedPackageJson?.optionalDependencies) {
182
165
  Object.keys(resolvedPackageJson.optionalDependencies).forEach((pkg) => allowedPackages.add(pkg));
183
166
  }
184
- // Add peer dependencies if allowed
185
167
  if (peerDependencies && resolvedPackageJson?.peerDependencies) {
186
168
  Object.keys(resolvedPackageJson.peerDependencies).forEach((pkg) => allowedPackages.add(pkg));
187
169
  }
188
- // Add bundled dependencies if allowed
189
170
  if (bundledDependencies && resolvedPackageJson?.bundledDependencies) {
190
171
  resolvedPackageJson.bundledDependencies.forEach((pkg) => allowedPackages.add(pkg));
191
172
  }
192
- // oxlint-disable-next-line consistent-function-scoping
193
173
  function isExternalPackage(importPath) {
194
- // Skip relative imports
195
174
  if (importPath.startsWith('./') || importPath.startsWith('../')) {
196
175
  return null;
197
176
  }
198
- // Skip absolute paths
199
177
  if (importPath.startsWith('/')) {
200
178
  return null;
201
179
  }
202
- // Skip Node.js built-ins
203
180
  const nodeBuiltins = [
204
181
  'assert',
205
182
  'buffer',
@@ -261,15 +238,12 @@ exports.noExtraneousDependencies = (0, eslint_devkit_1.createRule)({
261
238
  if (nodeBuiltins.includes(importPath)) {
262
239
  return null;
263
240
  }
264
- // Extract package name from scoped packages or regular packages
265
241
  const packageName = importPath.startsWith('@')
266
242
  ? importPath.split('/').slice(0, 2).join('/')
267
243
  : importPath.split('/')[0];
268
244
  return packageName;
269
245
  }
270
- // oxlint-disable-next-line consistent-function-scoping
271
246
  function isWorkspacePackage(packageName) {
272
- // For testing purposes, consider packages with @workspace/ or @company/ as workspace packages
273
247
  return (packageName.startsWith('@workspace/') ||
274
248
  packageName.startsWith('@company/'));
275
249
  }
@@ -278,7 +252,6 @@ exports.noExtraneousDependencies = (0, eslint_devkit_1.createRule)({
278
252
  if (!packageName) {
279
253
  return;
280
254
  }
281
- // Check allow patterns first
282
255
  const isAllowedByPattern = allowPatterns.some((pattern) => {
283
256
  try {
284
257
  const regex = new RegExp(pattern);
@@ -291,15 +264,12 @@ exports.noExtraneousDependencies = (0, eslint_devkit_1.createRule)({
291
264
  if (isAllowedByPattern) {
292
265
  return;
293
266
  }
294
- // Apply resolution strategy
295
267
  const shouldCheckDependency = () => {
296
268
  switch (resolutionStrategy) {
297
269
  case 'workspace':
298
- // Allow packages that are in dependencies OR are workspace packages
299
270
  return (!allowedPackages.has(packageName) &&
300
271
  !isWorkspacePackage(packageName));
301
272
  case 'monorepo':
302
- // Allow cross-package imports in monorepos
303
273
  return (!allowedPackages.has(packageName) &&
304
274
  !isWorkspacePackage(packageName));
305
275
  case 'strict':
@@ -308,11 +278,9 @@ exports.noExtraneousDependencies = (0, eslint_devkit_1.createRule)({
308
278
  }
309
279
  };
310
280
  if (shouldCheckDependency()) {
311
- // Check if it's in devDependencies but we're in production code
312
281
  const isInDevDeps = resolvedPackageJson?.devDependencies &&
313
282
  resolvedPackageJson.devDependencies[packageName];
314
283
  if (isInDevDeps && !devDependencies) {
315
- // Dev dependency used in production code
316
284
  context.report({
317
285
  node,
318
286
  messageId: 'devDependencyInProduction',
@@ -325,7 +293,6 @@ exports.noExtraneousDependencies = (0, eslint_devkit_1.createRule)({
325
293
  {
326
294
  messageId: 'moveToDependencies',
327
295
  fix(fixer) {
328
- // Find the parent statement to insert before
329
296
  let parentStatement = node;
330
297
  while (parentStatement &&
331
298
  parentStatement.type !== 'ImportDeclaration' &&
@@ -343,7 +310,6 @@ exports.noExtraneousDependencies = (0, eslint_devkit_1.createRule)({
343
310
  });
344
311
  }
345
312
  else {
346
- // Completely missing dependency
347
313
  context.report({
348
314
  node,
349
315
  messageId: 'missingDependency',
@@ -358,7 +324,6 @@ exports.noExtraneousDependencies = (0, eslint_devkit_1.createRule)({
358
324
  {
359
325
  messageId: 'addToDependencies',
360
326
  fix(fixer) {
361
- // Find the parent statement to insert before
362
327
  let parentStatement = node;
363
328
  while (parentStatement &&
364
329
  parentStatement.type !== 'ImportDeclaration' &&
@@ -375,7 +340,6 @@ exports.noExtraneousDependencies = (0, eslint_devkit_1.createRule)({
375
340
  {
376
341
  messageId: 'addToDevDependencies',
377
342
  fix(fixer) {
378
- // Find the parent statement to insert before
379
343
  let parentStatement = node;
380
344
  while (parentStatement &&
381
345
  parentStatement.type !== 'ImportDeclaration' &&
@@ -401,7 +365,6 @@ exports.noExtraneousDependencies = (0, eslint_devkit_1.createRule)({
401
365
  }
402
366
  },
403
367
  CallExpression(node) {
404
- // Check require() calls
405
368
  if (node.callee.type === 'Identifier' &&
406
369
  node.callee.name === 'require' &&
407
370
  node.arguments.length === 1) {
@@ -412,7 +375,6 @@ exports.noExtraneousDependencies = (0, eslint_devkit_1.createRule)({
412
375
  }
413
376
  },
414
377
  ImportExpression(node) {
415
- // Check dynamic imports
416
378
  if (node.source.type === 'Literal' &&
417
379
  typeof node.source.value === 'string') {
418
380
  checkImport(node.source.value, node.source);
@@ -1,13 +1,7 @@
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.noFullPackageImport = void 0;
9
4
  const eslint_devkit_1 = require("@interlace/eslint-devkit");
10
- // Known large packages that should use subpath/named imports
11
5
  const DEFAULT_BLOCKED_PACKAGES = [
12
6
  {
13
7
  name: 'lodash',
@@ -55,22 +49,12 @@ const DEFAULT_BLOCKED_PACKAGES = [
55
49
  example: "import { S3Client } from '@aws-sdk/client-s3';",
56
50
  },
57
51
  ];
58
- /**
59
- * Check if import is a full package import (not a subpath)
60
- */
61
52
  function isFullPackageImport(importPath, packageName) {
62
- // Exact match means full package import
63
53
  return importPath === packageName;
64
54
  }
65
- /**
66
- * Check if import uses namespace pattern
67
- */
68
55
  function hasNamespaceImport(node) {
69
56
  return node.specifiers.some((spec) => spec.type === eslint_devkit_1.AST_NODE_TYPES.ImportNamespaceSpecifier);
70
57
  }
71
- /**
72
- * Check if import uses default pattern
73
- */
74
58
  function hasDefaultImport(node) {
75
59
  return node.specifiers.some((spec) => spec.type === eslint_devkit_1.AST_NODE_TYPES.ImportDefaultSpecifier);
76
60
  }
@@ -128,13 +112,10 @@ exports.noFullPackageImport = (0, eslint_devkit_1.createRule)({
128
112
  const importPath = node.source.value;
129
113
  if (typeof importPath !== 'string')
130
114
  return;
131
- // Check against blocked packages
132
115
  for (const blocked of blockedPackages) {
133
116
  if (!isFullPackageImport(importPath, blocked.name)) {
134
117
  continue;
135
118
  }
136
- // Only flag namespace or default imports from full package path
137
- // Named imports might be tree-shakeable depending on the package
138
119
  if (hasNamespaceImport(node) || hasDefaultImport(node)) {
139
120
  context.report({
140
121
  node,
@@ -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.noImportModuleExports = void 0;
9
4
  const eslint_devkit_1 = require("@interlace/eslint-devkit");
@@ -52,7 +47,6 @@ exports.noImportModuleExports = (0, eslint_devkit_1.createRule)({
52
47
  importNodes.push(node);
53
48
  },
54
49
  MemberExpression(node) {
55
- // Check for module.exports
56
50
  if (node.object.type === eslint_devkit_1.AST_NODE_TYPES.Identifier &&
57
51
  node.object.name === 'module' &&
58
52
  node.property.type === eslint_devkit_1.AST_NODE_TYPES.Identifier &&
@@ -61,7 +55,6 @@ exports.noImportModuleExports = (0, eslint_devkit_1.createRule)({
61
55
  }
62
56
  },
63
57
  AssignmentExpression(node) {
64
- // Check for exports.xxx = ...
65
58
  if (node.left.type === eslint_devkit_1.AST_NODE_TYPES.MemberExpression &&
66
59
  node.left.object.type === eslint_devkit_1.AST_NODE_TYPES.Identifier &&
67
60
  node.left.object.name === 'exports') {
@@ -69,7 +62,6 @@ exports.noImportModuleExports = (0, eslint_devkit_1.createRule)({
69
62
  }
70
63
  },
71
64
  'Program:exit'() {
72
- // If we have both imports and module.exports, report on module.exports
73
65
  if (hasImport && moduleExportsNodes.length > 0) {
74
66
  moduleExportsNodes.forEach((node) => {
75
67
  context.report({
@@ -1,19 +1,9 @@
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.noInternalModules = void 0;
9
4
  const eslint_devkit_1 = require("@interlace/eslint-devkit");
10
5
  const eslint_devkit_2 = require("@interlace/eslint-devkit");
11
- /**
12
- * Simple glob pattern matching
13
- * Supports * (any chars) and ** (any path segments)
14
- */
15
6
  function matchGlob(pattern, path) {
16
- // Escape special regex chars except *
17
7
  const regexPattern = pattern
18
8
  .replace(/[.+^${}()|[\]\\]/g, '\\$&')
19
9
  .replace(/\*\*/g, '{{DOUBLE_STAR}}')
@@ -24,35 +14,18 @@ function matchGlob(pattern, path) {
24
14
  function matchesAnyPattern(path, patterns) {
25
15
  return patterns.some((pattern) => matchGlob(pattern, path));
26
16
  }
27
- /**
28
- * Calculate import depth
29
- * - 'lodash' => 0
30
- * - 'lodash/get' => 1
31
- * - '@company/ui' => 0 (scoped package root)
32
- * - '@company/ui/components' => 1
33
- * - '@company/ui/components/Button' => 2
34
- * - './utils' => 1
35
- * - './utils/helpers' => 2
36
- */
37
17
  function getImportDepth(importPath) {
38
- // Handle relative imports
39
18
  if (importPath.startsWith('./') || importPath.startsWith('../')) {
40
19
  const parts = importPath.split('/').filter((p) => p !== '.' && p !== '..');
41
20
  return parts.length;
42
21
  }
43
- // Handle scoped packages (@org/package)
44
22
  if (importPath.startsWith('@')) {
45
23
  const parts = importPath.split('/');
46
- // @org/package = 0 depth, @org/package/sub = 1 depth
47
24
  return Math.max(0, parts.length - 2);
48
25
  }
49
- // Handle regular packages
50
26
  const parts = importPath.split('/');
51
27
  return parts.length - 1;
52
28
  }
53
- /**
54
- * Get the root/base import path
55
- */
56
29
  function getRootImport(importPath) {
57
30
  if (importPath.startsWith('./') || importPath.startsWith('../')) {
58
31
  return '.';
@@ -63,9 +36,6 @@ function getRootImport(importPath) {
63
36
  }
64
37
  return importPath.split('/')[0];
65
38
  }
66
- /**
67
- * Get import path trimmed to specific depth
68
- */
69
39
  function getImportAtDepth(importPath, maxDepth) {
70
40
  if (importPath.startsWith('./') || importPath.startsWith('../')) {
71
41
  if (maxDepth === 0)
@@ -76,7 +46,6 @@ function getImportAtDepth(importPath, maxDepth) {
76
46
  }
77
47
  if (importPath.startsWith('@')) {
78
48
  const parts = importPath.split('/');
79
- // @org/package is depth 0
80
49
  return parts.slice(0, 2 + maxDepth).join('/');
81
50
  }
82
51
  const parts = importPath.split('/');
@@ -170,18 +139,15 @@ exports.noInternalModules = (0, eslint_devkit_1.createRule)({
170
139
  const [options] = context.options;
171
140
  const { maxDepth = 1, allow = [], forbid = [], ignorePaths = [], strategy = 'error', } = options || {};
172
141
  function checkImport(importPath, node) {
173
- // Skip if path should be ignored
174
142
  if (matchesAnyPattern(importPath, ignorePaths)) {
175
143
  return;
176
144
  }
177
- // Skip if path is explicitly allowed
178
145
  if (matchesAnyPattern(importPath, allow)) {
179
146
  return;
180
147
  }
181
148
  const depth = getImportDepth(importPath);
182
149
  const isForbidden = forbid.length > 0 && matchesAnyPattern(importPath, forbid);
183
150
  const exceedsDepth = depth > maxDepth;
184
- // No violation
185
151
  if (!isForbidden && !exceedsDepth) {
186
152
  return;
187
153
  }
@@ -204,8 +170,6 @@ exports.noInternalModules = (0, eslint_devkit_1.createRule)({
204
170
  messageId: 'internalModuleImport',
205
171
  data: reportData,
206
172
  fix(fixer) {
207
- // Find the string literal node to replace
208
- // Autofix always goes to the root package for safety
209
173
  const sourceNode = node.type === 'Literal'
210
174
  ? node
211
175
  : node.source;
@@ -229,7 +193,6 @@ exports.noInternalModules = (0, eslint_devkit_1.createRule)({
229
193
  return fixer.replaceText(sourceNode, `'${rootImport}'`);
230
194
  },
231
195
  },
232
- // Add barrel export suggestion if different from root
233
196
  ...(barrelPath !== rootImport && barrelPath !== suggestedPath
234
197
  ? [
235
198
  {
@@ -248,7 +211,6 @@ exports.noInternalModules = (0, eslint_devkit_1.createRule)({
248
211
  });
249
212
  }
250
213
  else {
251
- // 'error' or 'warn' strategy - just report
252
214
  context.report({
253
215
  node,
254
216
  messageId: 'internalModuleImport',
@@ -274,7 +236,6 @@ exports.noInternalModules = (0, eslint_devkit_1.createRule)({
274
236
  }
275
237
  },
276
238
  CallExpression(node) {
277
- // Check require() calls
278
239
  if (node.callee.type === 'Identifier' &&
279
240
  node.callee.name === 'require' &&
280
241
  node.arguments.length === 1) {
@@ -284,7 +245,6 @@ exports.noInternalModules = (0, eslint_devkit_1.createRule)({
284
245
  }
285
246
  }
286
247
  },
287
- // Handle dynamic imports: import('path')
288
248
  ImportExpression(node) {
289
249
  if (node.source.type === 'Literal' &&
290
250
  typeof node.source.value === 'string') {