eslint-plugin-import-next 2.3.15 → 2.3.17

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 (63) hide show
  1. package/README.md +1 -1
  2. package/package.json +3 -3
  3. package/src/files/foo.js +1 -6
  4. package/src/files/no-default.js +1 -4
  5. package/src/index.js +1 -273
  6. package/src/oxlint.js +1 -3
  7. package/src/rules/consistent-type-specifier-style.js +1 -109
  8. package/src/rules/default.js +1 -56
  9. package/src/rules/dynamic-import-chunkname.js +1 -115
  10. package/src/rules/enforce-dependency-direction.js +1 -213
  11. package/src/rules/enforce-import-order.js +1 -299
  12. package/src/rules/enforce-team-boundaries.js +1 -191
  13. package/src/rules/export.js +1 -111
  14. package/src/rules/exports-last.js +1 -67
  15. package/src/rules/extensions.js +1 -107
  16. package/src/rules/first.js +1 -53
  17. package/src/rules/group-exports.js +1 -69
  18. package/src/rules/max-dependencies.js +1 -241
  19. package/src/rules/named.js +1 -67
  20. package/src/rules/namespace.js +1 -64
  21. package/src/rules/newline-after-import.js +1 -57
  22. package/src/rules/no-absolute-path.js +1 -139
  23. package/src/rules/no-amd.js +1 -108
  24. package/src/rules/no-anonymous-default-export.js +1 -135
  25. package/src/rules/no-barrel-file.js +1 -194
  26. package/src/rules/no-barrel-import.js +1 -135
  27. package/src/rules/no-commonjs.js +1 -312
  28. package/src/rules/no-cross-domain-imports.js +1 -233
  29. package/src/rules/no-cycle.js +2 -396
  30. package/src/rules/no-default-export.js +2 -213
  31. package/src/rules/no-deprecated.js +1 -316
  32. package/src/rules/no-duplicates.js +1 -81
  33. package/src/rules/no-dynamic-require.js +1 -78
  34. package/src/rules/no-empty-named-blocks.js +1 -103
  35. package/src/rules/no-extraneous-dependencies.js +7 -385
  36. package/src/rules/no-full-package-import.js +1 -134
  37. package/src/rules/no-import-module-exports.js +1 -76
  38. package/src/rules/no-internal-modules.js +1 -256
  39. package/src/rules/no-legacy-imports.js +1 -125
  40. package/src/rules/no-mutable-exports.js +1 -146
  41. package/src/rules/no-named-as-default-member.js +1 -73
  42. package/src/rules/no-named-as-default.js +1 -90
  43. package/src/rules/no-named-default.js +1 -48
  44. package/src/rules/no-named-export.js +1 -174
  45. package/src/rules/no-namespace.js +1 -71
  46. package/src/rules/no-nodejs-modules.js +1 -229
  47. package/src/rules/no-relative-packages.js +1 -161
  48. package/src/rules/no-relative-parent-imports.js +1 -118
  49. package/src/rules/no-restricted-paths.js +1 -89
  50. package/src/rules/no-self-import.js +1 -145
  51. package/src/rules/no-unassigned-import.js +1 -115
  52. package/src/rules/no-unresolved.js +1 -189
  53. package/src/rules/no-unused-modules.js +1 -82
  54. package/src/rules/no-useless-path-segments.js +1 -139
  55. package/src/rules/prefer-default-export.js +1 -188
  56. package/src/rules/prefer-direct-import.js +1 -170
  57. package/src/rules/prefer-modern-api.js +1 -212
  58. package/src/rules/prefer-node-protocol.js +1 -174
  59. package/src/rules/prefer-tree-shakeable-imports.js +1 -134
  60. package/src/rules/require-import-approval.js +1 -174
  61. package/src/rules/unambiguous.js +1 -70
  62. package/src/types/index.js +1 -2
  63. package/src/utils/typescript-peer.js +1 -23
@@ -1,115 +1 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.dynamicImportChunkname = void 0;
4
- const eslint_devkit_1 = require("@interlace/eslint-devkit");
5
- exports.dynamicImportChunkname = (0, eslint_devkit_1.createRule)({
6
- name: 'dynamic-import-chunkname',
7
- meta: {
8
- type: 'suggestion',
9
- docs: {
10
- url: 'https://github.com/ofri-peretz/eslint/blob/main/packages/eslint-plugin-import-next/docs/rules/dynamic-import-chunkname.md',
11
- description: 'Enforce a leading comment with the webpackChunkName for dynamic imports',
12
- cwe: 'CWE-1078',
13
- cvss: 2.5,
14
- },
15
- hasSuggestions: true,
16
- messages: {
17
- missingChunkName: (0, eslint_devkit_1.formatLLMMessage)({
18
- icon: eslint_devkit_1.MessageIcons.ARCHITECTURE,
19
- issueName: 'Missing Chunk Name',
20
- cwe: 'CWE-1078',
21
- description: 'Dynamic import is missing webpackChunkName comment',
22
- severity: 'LOW',
23
- fix: 'Add /* webpackChunkName: "chunk-name" */ before the import path',
24
- documentationLink: 'https://github.com/import-js/eslint-plugin-import/blob/main/docs/rules/dynamic-import-chunkname.md',
25
- }),
26
- invalidChunkName: (0, eslint_devkit_1.formatLLMMessage)({
27
- icon: eslint_devkit_1.MessageIcons.ARCHITECTURE,
28
- issueName: 'Invalid Chunk Name',
29
- cwe: 'CWE-1078',
30
- description: 'webpackChunkName "{{chunkName}}" does not match pattern',
31
- severity: 'LOW',
32
- fix: 'Update chunk name to match the required pattern',
33
- documentationLink: 'https://github.com/import-js/eslint-plugin-import/blob/main/docs/rules/dynamic-import-chunkname.md',
34
- }),
35
- suggestChunkName: 'Add webpackChunkName comment',
36
- },
37
- schema: [
38
- {
39
- type: 'object',
40
- properties: {
41
- importFunctions: {
42
- type: 'array',
43
- items: { type: 'string' },
44
- },
45
- allowEmpty: { type: 'boolean', default: false },
46
- webpackChunknameFormat: { type: 'string' },
47
- },
48
- additionalProperties: false,
49
- },
50
- ],
51
- },
52
- defaultOptions: [
53
- {
54
- importFunctions: [],
55
- allowEmpty: false,
56
- webpackChunknameFormat: '[a-zA-Z0-9-_/.]+',
57
- },
58
- ],
59
- create(context) {
60
- const options = context.options[0] || {};
61
- const { allowEmpty = false, webpackChunknameFormat = '[a-zA-Z0-9-_/.]+' } = options;
62
- const chunkNamePattern = new RegExp(`^${webpackChunknameFormat}$`);
63
- const sourceCode = context.sourceCode;
64
- function checkChunkName(node) {
65
- const comments = sourceCode.getCommentsBefore(node.source);
66
- let foundChunkName = null;
67
- let hasWebpackComment = false;
68
- for (const comment of comments) {
69
- const text = comment.value.trim();
70
- const match = text.match(/webpackChunkName:\s*["']([^"']+)["']/);
71
- if (match) {
72
- hasWebpackComment = true;
73
- foundChunkName = match[1];
74
- break;
75
- }
76
- }
77
- if (!hasWebpackComment) {
78
- if (!allowEmpty) {
79
- context.report({
80
- node,
81
- messageId: 'missingChunkName',
82
- suggest: [
83
- {
84
- messageId: 'suggestChunkName',
85
- fix(fixer) {
86
- const source = node.source;
87
- if (source.type === 'Literal' && typeof source.value === 'string') {
88
- const chunkName = source.value
89
- .split('/')
90
- .pop()
91
- ?.replace(/[^a-zA-Z0-9-_]/g, '-') || 'chunk';
92
- return fixer.insertTextBefore(source, `/* webpackChunkName: "${chunkName}" */ `);
93
- }
94
- return null;
95
- },
96
- },
97
- ],
98
- });
99
- }
100
- }
101
- else if (foundChunkName && !chunkNamePattern.test(foundChunkName)) {
102
- context.report({
103
- node,
104
- messageId: 'invalidChunkName',
105
- data: { chunkName: foundChunkName },
106
- });
107
- }
108
- }
109
- return {
110
- ImportExpression(node) {
111
- checkChunkName(node);
112
- },
113
- };
114
- },
115
- });
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.dynamicImportChunkname=void 0;const eslint_devkit_1=require("@interlace/eslint-devkit");exports.dynamicImportChunkname=(0,eslint_devkit_1.createRule)({name:"dynamic-import-chunkname",meta:{type:"suggestion",docs:{url:"https://github.com/ofri-peretz/eslint/blob/main/packages/eslint-plugin-import-next/docs/rules/dynamic-import-chunkname.md",description:"Enforce a leading comment with the webpackChunkName for dynamic imports",cwe:"CWE-1078",cvss:2.5},hasSuggestions:true,messages:{missingChunkName:(0,eslint_devkit_1.formatLLMMessage)({icon:eslint_devkit_1.MessageIcons.ARCHITECTURE,issueName:"Missing Chunk Name",cwe:"CWE-1078",description:"Dynamic import is missing webpackChunkName comment",severity:"LOW",fix:'Add /* webpackChunkName: "chunk-name" */ before the import path',documentationLink:"https://github.com/import-js/eslint-plugin-import/blob/main/docs/rules/dynamic-import-chunkname.md"}),invalidChunkName:(0,eslint_devkit_1.formatLLMMessage)({icon:eslint_devkit_1.MessageIcons.ARCHITECTURE,issueName:"Invalid Chunk Name",cwe:"CWE-1078",description:'webpackChunkName "{{chunkName}}" does not match pattern',severity:"LOW",fix:"Update chunk name to match the required pattern",documentationLink:"https://github.com/import-js/eslint-plugin-import/blob/main/docs/rules/dynamic-import-chunkname.md"}),suggestChunkName:"Add webpackChunkName comment"},schema:[{type:"object",properties:{importFunctions:{type:"array",items:{type:"string"}},allowEmpty:{type:"boolean",default:false},webpackChunknameFormat:{type:"string"}},additionalProperties:false}]},defaultOptions:[{importFunctions:[],allowEmpty:false,webpackChunknameFormat:"[a-zA-Z0-9-_/.]+"}],create(context){const options=context.options[0]||{};const{allowEmpty=false,webpackChunknameFormat="[a-zA-Z0-9-_/.]+"}=options;const chunkNamePattern=new RegExp(`^${webpackChunknameFormat}$`);const sourceCode=context.sourceCode;function checkChunkName(node){const comments=sourceCode.getCommentsBefore(node.source);let foundChunkName=null;let hasWebpackComment=false;for(const comment of comments){const text=comment.value.trim();const match=text.match(/webpackChunkName:\s*["']([^"']+)["']/);if(match){hasWebpackComment=true;foundChunkName=match[1];break}}if(!hasWebpackComment){if(!allowEmpty){context.report({node,messageId:"missingChunkName",suggest:[{messageId:"suggestChunkName",fix(fixer){const source=node.source;if(source.type==="Literal"&&typeof source.value==="string"){const chunkName=source.value.split("/").pop()?.replace(/[^a-zA-Z0-9-_]/g,"-")||"chunk";return fixer.insertTextBefore(source,`/* webpackChunkName: "${chunkName}" */ `)}return null}}]})}}else if(foundChunkName&&!chunkNamePattern.test(foundChunkName)){context.report({node,messageId:"invalidChunkName",data:{chunkName:foundChunkName}})}}return{ImportExpression(node){checkChunkName(node)}}}});
@@ -1,213 +1 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.enforceDependencyDirection = void 0;
4
- const eslint_devkit_1 = require("@interlace/eslint-devkit");
5
- const eslint_devkit_2 = require("@interlace/eslint-devkit");
6
- const eslint_devkit_3 = require("@interlace/eslint-devkit");
7
- function arraysEqual(a, b) {
8
- if (a.length !== b.length)
9
- return false;
10
- return a.every((val, index) => val === b[index]);
11
- }
12
- function extractLayer(filePath, layerPatterns) {
13
- const normalizedPath = (0, eslint_devkit_3.normalizePath)(filePath);
14
- for (const pattern of layerPatterns) {
15
- if (normalizedPath.includes(`/${pattern}/`) ||
16
- normalizedPath.includes(`\\${pattern}\\`) ||
17
- normalizedPath.startsWith(`${pattern}/`) ||
18
- normalizedPath.startsWith(`${pattern}\\`)) {
19
- return pattern;
20
- }
21
- }
22
- return null;
23
- }
24
- function getLayerOrder(layer, layers) {
25
- if (!layer) {
26
- return -1;
27
- }
28
- const index = layers.indexOf(layer);
29
- return index >= 0 ? index : -1;
30
- }
31
- exports.enforceDependencyDirection = (0, eslint_devkit_2.createRule)({
32
- name: 'enforce-dependency-direction',
33
- meta: {
34
- type: 'problem',
35
- docs: {
36
- url: 'https://github.com/ofri-peretz/eslint/blob/main/packages/eslint-plugin-import-next/docs/rules/enforce-dependency-direction.md',
37
- description: 'Ensures dependencies flow in the correct architectural direction',
38
- },
39
- messages: {
40
- dependencyDirectionViolation: (0, eslint_devkit_1.formatLLMMessage)({
41
- icon: eslint_devkit_1.MessageIcons.ARCHITECTURE,
42
- issueName: 'Dependency direction violation',
43
- description: 'Import from {{targetLayer}} to {{sourceLayer}} violates dependency direction',
44
- severity: 'HIGH',
45
- fix: 'Use dependency inversion or refactor dependency',
46
- documentationLink: 'https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html',
47
- }),
48
- useDependencyInversion: (0, eslint_devkit_1.formatLLMMessage)({
49
- icon: eslint_devkit_1.MessageIcons.INFO,
50
- issueName: 'Use Dependency Inversion',
51
- description: 'Use dependency inversion principle',
52
- severity: 'LOW',
53
- fix: 'Depend on interfaces/abstractions, not implementations',
54
- documentationLink: 'https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html',
55
- }),
56
- refactorDependency: (0, eslint_devkit_1.formatLLMMessage)({
57
- icon: eslint_devkit_1.MessageIcons.INFO,
58
- issueName: 'Refactor Dependency',
59
- description: 'Refactor to respect dependency direction',
60
- severity: 'LOW',
61
- fix: 'Move import to correct layer',
62
- documentationLink: 'https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html',
63
- }),
64
- },
65
- schema: [
66
- {
67
- type: 'object',
68
- properties: {
69
- layers: {
70
- type: 'array',
71
- items: { type: 'string' },
72
- default: [
73
- 'domain',
74
- 'application',
75
- 'infrastructure',
76
- 'presentation',
77
- ],
78
- description: 'Layer definitions with dependency order',
79
- },
80
- layerPatterns: {
81
- type: 'array',
82
- items: { type: 'string' },
83
- default: [
84
- 'domain',
85
- 'application',
86
- 'infrastructure',
87
- 'presentation',
88
- 'ui',
89
- 'api',
90
- ],
91
- description: 'Layer directory patterns',
92
- },
93
- allowSameLayer: {
94
- type: 'boolean',
95
- default: true,
96
- description: 'Allow same-layer imports',
97
- },
98
- },
99
- additionalProperties: false,
100
- },
101
- ],
102
- },
103
- defaultOptions: [
104
- {
105
- layers: ['domain', 'application', 'infrastructure', 'presentation'],
106
- layerPatterns: [
107
- 'domain',
108
- 'application',
109
- 'infrastructure',
110
- 'presentation',
111
- 'ui',
112
- 'api',
113
- ],
114
- allowSameLayer: true,
115
- },
116
- ],
117
- create(context, [options = {}]) {
118
- const filename = context.filename;
119
- const { layers: providedLayers, layerPatterns: providedLayerPatterns, allowSameLayer = true, } = options || {};
120
- const layers = providedLayers || [
121
- 'domain',
122
- 'application',
123
- 'infrastructure',
124
- 'presentation',
125
- ];
126
- const defaultLayerPatterns = [
127
- 'domain',
128
- 'application',
129
- 'infrastructure',
130
- 'presentation',
131
- 'ui',
132
- 'api',
133
- ];
134
- let layerPatterns;
135
- if (providedLayerPatterns &&
136
- !arraysEqual(providedLayerPatterns, defaultLayerPatterns)) {
137
- layerPatterns = providedLayerPatterns;
138
- }
139
- else if (providedLayers) {
140
- layerPatterns = providedLayers;
141
- }
142
- else {
143
- layerPatterns = defaultLayerPatterns;
144
- }
145
- const sourceLayer = extractLayer(filename, layerPatterns);
146
- const sourceOrder = getLayerOrder(sourceLayer, layers);
147
- function checkImport(node) {
148
- let importPath = '';
149
- if (node.type === 'ImportDeclaration') {
150
- importPath = node.source.value;
151
- }
152
- else if (node.type === 'ImportExpression') {
153
- if (node.source.type === 'Literal') {
154
- importPath = node.source.value;
155
- }
156
- else {
157
- return;
158
- }
159
- }
160
- if (!importPath.startsWith('.')) {
161
- return;
162
- }
163
- let targetLayer = null;
164
- const segments = importPath.split(/[/\\]/);
165
- for (const segment of segments) {
166
- if (layerPatterns.includes(segment.toLowerCase())) {
167
- targetLayer = segment.toLowerCase();
168
- break;
169
- }
170
- }
171
- if (!targetLayer) {
172
- for (const pattern of layerPatterns) {
173
- const regex = new RegExp(`[/\\\\]${pattern}[/\\\\]`, 'i');
174
- if (regex.test(importPath)) {
175
- targetLayer = pattern;
176
- break;
177
- }
178
- }
179
- }
180
- const targetOrder = getLayerOrder(targetLayer, layers);
181
- if (sourceOrder < 0 || targetOrder < 0) {
182
- return;
183
- }
184
- if (allowSameLayer && sourceLayer === targetLayer) {
185
- return;
186
- }
187
- if (targetOrder > sourceOrder) {
188
- context.report({
189
- node,
190
- messageId: 'dependencyDirectionViolation',
191
- data: {
192
- sourceLayer: sourceLayer,
193
- targetLayer: targetLayer,
194
- },
195
- suggest: [
196
- {
197
- messageId: 'useDependencyInversion',
198
- fix: () => null,
199
- },
200
- {
201
- messageId: 'refactorDependency',
202
- fix: () => null,
203
- },
204
- ],
205
- });
206
- }
207
- }
208
- return {
209
- ImportDeclaration: checkImport,
210
- ImportExpression: checkImport,
211
- };
212
- },
213
- });
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.enforceDependencyDirection=void 0;const eslint_devkit_1=require("@interlace/eslint-devkit");const eslint_devkit_2=require("@interlace/eslint-devkit");const eslint_devkit_3=require("@interlace/eslint-devkit");function arraysEqual(a,b){if(a.length!==b.length)return false;return a.every((val,index)=>val===b[index])}function extractLayer(filePath,layerPatterns){const normalizedPath=(0,eslint_devkit_3.normalizePath)(filePath);for(const pattern of layerPatterns){if(normalizedPath.includes(`/${pattern}/`)||normalizedPath.includes(`\\${pattern}\\`)||normalizedPath.startsWith(`${pattern}/`)||normalizedPath.startsWith(`${pattern}\\`)){return pattern}}return null}function getLayerOrder(layer,layers){if(!layer){return-1}const index=layers.indexOf(layer);return index>=0?index:-1}exports.enforceDependencyDirection=(0,eslint_devkit_2.createRule)({name:"enforce-dependency-direction",meta:{type:"problem",docs:{url:"https://github.com/ofri-peretz/eslint/blob/main/packages/eslint-plugin-import-next/docs/rules/enforce-dependency-direction.md",description:"Ensures dependencies flow in the correct architectural direction"},hasSuggestions:true,messages:{dependencyDirectionViolation:(0,eslint_devkit_1.formatLLMMessage)({icon:eslint_devkit_1.MessageIcons.ARCHITECTURE,issueName:"Dependency direction violation",description:"Import from {{targetLayer}} to {{sourceLayer}} violates dependency direction",severity:"HIGH",fix:"Use dependency inversion or refactor dependency",documentationLink:"https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html"}),useDependencyInversion:(0,eslint_devkit_1.formatLLMMessage)({icon:eslint_devkit_1.MessageIcons.INFO,issueName:"Use Dependency Inversion",description:"Use dependency inversion principle",severity:"LOW",fix:"Depend on interfaces/abstractions, not implementations",documentationLink:"https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html"}),refactorDependency:(0,eslint_devkit_1.formatLLMMessage)({icon:eslint_devkit_1.MessageIcons.INFO,issueName:"Refactor Dependency",description:"Refactor to respect dependency direction",severity:"LOW",fix:"Move import to correct layer",documentationLink:"https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html"})},schema:[{type:"object",properties:{layers:{type:"array",items:{type:"string"},default:["domain","application","infrastructure","presentation"],description:"Layer definitions with dependency order"},layerPatterns:{type:"array",items:{type:"string"},default:["domain","application","infrastructure","presentation","ui","api"],description:"Layer directory patterns"},allowSameLayer:{type:"boolean",default:true,description:"Allow same-layer imports"}},additionalProperties:false}]},defaultOptions:[{layers:["domain","application","infrastructure","presentation"],layerPatterns:["domain","application","infrastructure","presentation","ui","api"],allowSameLayer:true}],create(context,[options={}]){const filename=context.filename;const{layers:providedLayers,layerPatterns:providedLayerPatterns,allowSameLayer=true}=options||{};const layers=providedLayers||["domain","application","infrastructure","presentation"];const defaultLayerPatterns=["domain","application","infrastructure","presentation","ui","api"];let layerPatterns;if(providedLayerPatterns&&!arraysEqual(providedLayerPatterns,defaultLayerPatterns)){layerPatterns=providedLayerPatterns}else if(providedLayers){layerPatterns=providedLayers}else{layerPatterns=defaultLayerPatterns}const sourceLayer=extractLayer(filename,layerPatterns);const sourceOrder=getLayerOrder(sourceLayer,layers);function checkImport(node){let importPath="";if(node.type==="ImportDeclaration"){importPath=node.source.value}else if(node.type==="ImportExpression"){if(node.source.type==="Literal"){importPath=node.source.value}else{return}}if(!importPath.startsWith(".")){return}let targetLayer=null;const segments=importPath.split(/[/\\]/);for(const segment of segments){if(layerPatterns.includes(segment.toLowerCase())){targetLayer=segment.toLowerCase();break}}if(!targetLayer){for(const pattern of layerPatterns){const regex=new RegExp(`[/\\\\]${pattern}[/\\\\]`,"i");if(regex.test(importPath)){targetLayer=pattern;break}}}const targetOrder=getLayerOrder(targetLayer,layers);if(sourceOrder<0||targetOrder<0){return}if(allowSameLayer&&sourceLayer===targetLayer){return}if(targetOrder>sourceOrder){context.report({node,messageId:"dependencyDirectionViolation",data:{sourceLayer,targetLayer},suggest:[{messageId:"useDependencyInversion",fix:()=>null},{messageId:"refactorDependency",fix:()=>null}]})}}return{ImportDeclaration:checkImport,ImportExpression:checkImport}}});
@@ -1,299 +1 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.enforceImportOrder = void 0;
4
- const eslint_devkit_1 = require("@interlace/eslint-devkit");
5
- const eslint_devkit_2 = require("@interlace/eslint-devkit");
6
- const defaultOptions = {
7
- groups: [
8
- 'builtin',
9
- 'external',
10
- 'internal',
11
- 'parent',
12
- 'sibling',
13
- 'index',
14
- 'side-effect',
15
- ],
16
- internalPatterns: ['^@/'],
17
- alphabetize: {
18
- order: 'asc',
19
- caseInsensitive: true,
20
- },
21
- newlinesBetween: 'always',
22
- };
23
- exports.enforceImportOrder = (0, eslint_devkit_1.createRule)({
24
- name: 'enforce-import-order',
25
- meta: {
26
- type: 'suggestion',
27
- docs: {
28
- url: 'https://github.com/ofri-peretz/eslint/blob/main/packages/eslint-plugin-import-next/docs/rules/enforce-import-order.md',
29
- description: 'Enforces a specific order for import statements',
30
- },
31
- fixable: 'code',
32
- messages: {
33
- importOrder: (0, eslint_devkit_2.formatLLMMessage)({
34
- icon: eslint_devkit_2.MessageIcons.ARCHITECTURE,
35
- issueName: 'Import Order',
36
- description: 'Imports are not ordered correctly',
37
- severity: 'LOW',
38
- fix: 'Reorder imports to match the configured group order',
39
- documentationLink: 'https://github.com/import-js/eslint-plugin-import/blob/main/docs/rules/order.md',
40
- }),
41
- alphabeticalOrder: (0, eslint_devkit_2.formatLLMMessage)({
42
- icon: eslint_devkit_2.MessageIcons.ARCHITECTURE,
43
- issueName: 'Alphabetical Order',
44
- description: 'Imports within the same group are not alphabetized',
45
- severity: 'LOW',
46
- fix: 'Sort imports alphabetically within groups',
47
- documentationLink: 'https://github.com/import-js/eslint-plugin-import/blob/main/docs/rules/order.md',
48
- }),
49
- importsNotContiguous: (0, eslint_devkit_2.formatLLMMessage)({
50
- icon: eslint_devkit_2.MessageIcons.ARCHITECTURE,
51
- issueName: 'Imports Not Contiguous',
52
- description: 'Code found between import statements',
53
- severity: 'MEDIUM',
54
- fix: 'Move all imports to the top of the file',
55
- documentationLink: 'https://github.com/import-js/eslint-plugin-import/blob/main/docs/rules/first.md',
56
- }),
57
- },
58
- schema: [
59
- {
60
- type: 'object',
61
- properties: {
62
- groups: {
63
- type: 'array',
64
- items: {
65
- type: 'string',
66
- enum: [
67
- 'builtin',
68
- 'external',
69
- 'internal',
70
- 'parent',
71
- 'sibling',
72
- 'index',
73
- 'object',
74
- 'type',
75
- 'side-effect',
76
- ],
77
- },
78
- },
79
- internalPatterns: {
80
- type: 'array',
81
- items: {
82
- type: 'string',
83
- },
84
- },
85
- alphabetize: {
86
- type: 'object',
87
- properties: {
88
- order: {
89
- type: 'string',
90
- enum: ['asc', 'desc', 'ignore'],
91
- },
92
- caseInsensitive: {
93
- type: 'boolean',
94
- },
95
- },
96
- additionalProperties: false,
97
- },
98
- newlinesBetween: {
99
- type: 'string',
100
- enum: ['always', 'never', 'ignore'],
101
- },
102
- },
103
- additionalProperties: false,
104
- },
105
- ],
106
- },
107
- defaultOptions: [defaultOptions],
108
- create(context) {
109
- const userOptions = context.options[0] || {};
110
- const options = {
111
- groups: userOptions.groups ?? defaultOptions.groups,
112
- internalPatterns: userOptions.internalPatterns ?? defaultOptions.internalPatterns,
113
- newlinesBetween: userOptions.newlinesBetween ?? defaultOptions.newlinesBetween,
114
- alphabetize: {
115
- order: userOptions.alphabetize?.order ?? defaultOptions.alphabetize.order,
116
- caseInsensitive: userOptions.alphabetize?.caseInsensitive ??
117
- defaultOptions.alphabetize.caseInsensitive,
118
- },
119
- };
120
- const sourceCode = context.sourceCode;
121
- const imports = [];
122
- function getImportType(node) {
123
- const source = node.source.value;
124
- if (node.specifiers.length === 0) {
125
- return 'side-effect';
126
- }
127
- if (source.startsWith('node:') ||
128
- [
129
- 'fs',
130
- 'path',
131
- 'os',
132
- 'util',
133
- 'http',
134
- 'https',
135
- 'events',
136
- 'stream',
137
- 'child_process',
138
- ].includes(source)) {
139
- return 'builtin';
140
- }
141
- if (source.startsWith('.')) {
142
- if (source.startsWith('../')) {
143
- return 'parent';
144
- }
145
- if (source === './index' || source === '.') {
146
- return 'index';
147
- }
148
- return 'sibling';
149
- }
150
- if (options.internalPatterns && options.internalPatterns.length > 0) {
151
- for (const pattern of options.internalPatterns) {
152
- if (new RegExp(pattern).test(source)) {
153
- return 'internal';
154
- }
155
- }
156
- }
157
- return 'external';
158
- }
159
- function getGroupRank(importType) {
160
- const index = options.groups.indexOf(importType);
161
- return index !== -1 ? index : 999;
162
- }
163
- function getExtendedRange(node) {
164
- let start = node.range[0];
165
- let end = node.range[1];
166
- const commentsBefore = sourceCode.getCommentsBefore(node);
167
- if (commentsBefore.length > 0) {
168
- start = commentsBefore[0].range[0];
169
- }
170
- const tokenAfter = sourceCode.getTokenAfter(node);
171
- if (tokenAfter && tokenAfter.value === ';') {
172
- end = tokenAfter.range[1];
173
- }
174
- const commentsAfter = sourceCode.getCommentsAfter(node);
175
- const sameLineComment = commentsAfter.find((c) => c.loc.start.line === node.loc.end.line);
176
- if (sameLineComment) {
177
- end = sameLineComment.range[1];
178
- }
179
- return [start, end];
180
- }
181
- function getImportText(node) {
182
- const [start, end] = getExtendedRange(node);
183
- return sourceCode.text.slice(start, end);
184
- }
185
- return {
186
- ImportDeclaration(node) {
187
- imports.push(node);
188
- },
189
- 'Program:exit'() {
190
- if (imports.length === 0) {
191
- return;
192
- }
193
- for (let i = 0; i < imports.length - 1; i++) {
194
- const current = imports[i];
195
- const next = imports[i + 1];
196
- const tokensBetween = sourceCode.getTokensBetween(current, next, {
197
- includeComments: true,
198
- });
199
- if (tokensBetween.length > 0) {
200
- const codeTokens = sourceCode.getTokensBetween(current, next, {
201
- includeComments: false,
202
- });
203
- if (codeTokens.length > 0) {
204
- context.report({
205
- node: next,
206
- messageId: 'importsNotContiguous',
207
- });
208
- return;
209
- }
210
- }
211
- }
212
- const originalImports = [...imports];
213
- const sortedImports = Array.from(imports).sort((a, b) => {
214
- const typeA = getImportType(a);
215
- const typeB = getImportType(b);
216
- const rankA = getGroupRank(typeA);
217
- const rankB = getGroupRank(typeB);
218
- if (rankA !== rankB) {
219
- return rankA - rankB;
220
- }
221
- if (options.alphabetize?.order !== 'ignore') {
222
- const sourceA = a.source.value;
223
- const sourceB = b.source.value;
224
- const compareResult = options.alphabetize?.caseInsensitive
225
- ? sourceA.toLowerCase().localeCompare(sourceB.toLowerCase())
226
- : sourceA.localeCompare(sourceB);
227
- return options.alphabetize?.order === 'asc'
228
- ? compareResult
229
- : -compareResult;
230
- }
231
- return 0;
232
- });
233
- let isSorted = true;
234
- for (let i = 0; i < originalImports.length; i++) {
235
- if (originalImports[i] !== sortedImports[i]) {
236
- isSorted = false;
237
- break;
238
- }
239
- }
240
- if (isSorted && options.newlinesBetween !== 'ignore') {
241
- for (let i = 0; i < imports.length - 1; i++) {
242
- const current = imports[i];
243
- const next = imports[i + 1];
244
- const typeCurrent = getImportType(current);
245
- const typeNext = getImportType(next);
246
- const rankCurrent = getGroupRank(typeCurrent);
247
- const rankNext = getGroupRank(typeNext);
248
- if (rankCurrent !== rankNext) {
249
- const linesBetween = next.loc.start.line - current.loc.end.line;
250
- if (options.newlinesBetween === 'always' && linesBetween < 2) {
251
- isSorted = false;
252
- break;
253
- }
254
- if (options.newlinesBetween === 'never' && linesBetween > 1) {
255
- isSorted = false;
256
- break;
257
- }
258
- }
259
- }
260
- }
261
- if (!isSorted) {
262
- const firstImport = imports[0];
263
- const lastImport = imports[imports.length - 1];
264
- const firstExtended = getExtendedRange(firstImport);
265
- const lastExtended = getExtendedRange(lastImport);
266
- context.report({
267
- node: firstImport,
268
- loc: {
269
- start: firstImport.loc.start,
270
- end: lastImport.loc.end,
271
- },
272
- messageId: 'importOrder',
273
- fix(fixer) {
274
- const rangeStart = firstExtended[0];
275
- const rangeEnd = lastExtended[1];
276
- let newCode = '';
277
- for (let i = 0; i < sortedImports.length; i++) {
278
- const node = sortedImports[i];
279
- const importType = getImportType(node);
280
- if (i > 0 && options.newlinesBetween === 'always') {
281
- const prevNode = sortedImports[i - 1];
282
- const prevType = getImportType(prevNode);
283
- const prevRank = getGroupRank(prevType);
284
- const currRank = getGroupRank(importType);
285
- if (prevRank !== currRank) {
286
- newCode += '\n';
287
- }
288
- }
289
- newCode += getImportText(node) + '\n';
290
- }
291
- newCode = newCode.trimEnd();
292
- return fixer.replaceTextRange([rangeStart, rangeEnd], newCode);
293
- },
294
- });
295
- }
296
- },
297
- };
298
- },
299
- });
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.enforceImportOrder=void 0;const eslint_devkit_1=require("@interlace/eslint-devkit");const eslint_devkit_2=require("@interlace/eslint-devkit");const defaultOptions={groups:["builtin","external","internal","parent","sibling","index","side-effect"],internalPatterns:["^@/"],alphabetize:{order:"asc",caseInsensitive:true},newlinesBetween:"always"};exports.enforceImportOrder=(0,eslint_devkit_1.createRule)({name:"enforce-import-order",meta:{type:"suggestion",docs:{url:"https://github.com/ofri-peretz/eslint/blob/main/packages/eslint-plugin-import-next/docs/rules/enforce-import-order.md",description:"Enforces a specific order for import statements"},fixable:"code",messages:{importOrder:(0,eslint_devkit_2.formatLLMMessage)({icon:eslint_devkit_2.MessageIcons.ARCHITECTURE,issueName:"Import Order",description:"Imports are not ordered correctly",severity:"LOW",fix:"Reorder imports to match the configured group order",documentationLink:"https://github.com/import-js/eslint-plugin-import/blob/main/docs/rules/order.md"}),alphabeticalOrder:(0,eslint_devkit_2.formatLLMMessage)({icon:eslint_devkit_2.MessageIcons.ARCHITECTURE,issueName:"Alphabetical Order",description:"Imports within the same group are not alphabetized",severity:"LOW",fix:"Sort imports alphabetically within groups",documentationLink:"https://github.com/import-js/eslint-plugin-import/blob/main/docs/rules/order.md"}),importsNotContiguous:(0,eslint_devkit_2.formatLLMMessage)({icon:eslint_devkit_2.MessageIcons.ARCHITECTURE,issueName:"Imports Not Contiguous",description:"Code found between import statements",severity:"MEDIUM",fix:"Move all imports to the top of the file",documentationLink:"https://github.com/import-js/eslint-plugin-import/blob/main/docs/rules/first.md"})},schema:[{type:"object",properties:{groups:{type:"array",items:{type:"string",enum:["builtin","external","internal","parent","sibling","index","object","type","side-effect"]}},internalPatterns:{type:"array",items:{type:"string"}},alphabetize:{type:"object",properties:{order:{type:"string",enum:["asc","desc","ignore"]},caseInsensitive:{type:"boolean"}},additionalProperties:false},newlinesBetween:{type:"string",enum:["always","never","ignore"]}},additionalProperties:false}]},defaultOptions:[defaultOptions],create(context){const userOptions=context.options[0]||{};const options={groups:userOptions.groups??defaultOptions.groups,internalPatterns:userOptions.internalPatterns??defaultOptions.internalPatterns,newlinesBetween:userOptions.newlinesBetween??defaultOptions.newlinesBetween,alphabetize:{order:userOptions.alphabetize?.order??defaultOptions.alphabetize.order,caseInsensitive:userOptions.alphabetize?.caseInsensitive??defaultOptions.alphabetize.caseInsensitive}};const sourceCode=context.sourceCode;const imports=[];function getImportType(node){const source=node.source.value;if(node.specifiers.length===0){return"side-effect"}if(source.startsWith("node:")||["fs","path","os","util","http","https","events","stream","child_process"].includes(source)){return"builtin"}if(source.startsWith(".")){if(source.startsWith("../")){return"parent"}if(source==="./index"||source==="."){return"index"}return"sibling"}if(options.internalPatterns&&options.internalPatterns.length>0){for(const pattern of options.internalPatterns){if(new RegExp(pattern).test(source)){return"internal"}}}return"external"}function getGroupRank(importType){const index=options.groups.indexOf(importType);return index!==-1?index:999}function getExtendedRange(node){let start=node.range[0];let end=node.range[1];const commentsBefore=sourceCode.getCommentsBefore(node);if(commentsBefore.length>0){start=commentsBefore[0].range[0]}const tokenAfter=sourceCode.getTokenAfter(node);if(tokenAfter&&tokenAfter.value===";"){end=tokenAfter.range[1]}const commentsAfter=sourceCode.getCommentsAfter(node);const sameLineComment=commentsAfter.find(c=>c.loc.start.line===node.loc.end.line);if(sameLineComment){end=sameLineComment.range[1]}return[start,end]}function getImportText(node){const[start,end]=getExtendedRange(node);return sourceCode.text.slice(start,end)}return{ImportDeclaration(node){imports.push(node)},"Program:exit"(){if(imports.length===0){return}for(let i=0;i<imports.length-1;i++){const current=imports[i];const next=imports[i+1];const tokensBetween=sourceCode.getTokensBetween(current,next,{includeComments:true});if(tokensBetween.length>0){const codeTokens=sourceCode.getTokensBetween(current,next,{includeComments:false});if(codeTokens.length>0){context.report({node:next,messageId:"importsNotContiguous"});return}}}const originalImports=[...imports];const sortedImports=Array.from(imports).sort((a,b)=>{const typeA=getImportType(a);const typeB=getImportType(b);const rankA=getGroupRank(typeA);const rankB=getGroupRank(typeB);if(rankA!==rankB){return rankA-rankB}if(options.alphabetize?.order!=="ignore"){const sourceA=a.source.value;const sourceB=b.source.value;const compareResult=options.alphabetize?.caseInsensitive?sourceA.toLowerCase().localeCompare(sourceB.toLowerCase()):sourceA.localeCompare(sourceB);return options.alphabetize?.order==="asc"?compareResult:-compareResult}return 0});let isSorted=true;for(let i=0;i<originalImports.length;i++){if(originalImports[i]!==sortedImports[i]){isSorted=false;break}}if(isSorted&&options.newlinesBetween!=="ignore"){for(let i=0;i<imports.length-1;i++){const current=imports[i];const next=imports[i+1];const typeCurrent=getImportType(current);const typeNext=getImportType(next);const rankCurrent=getGroupRank(typeCurrent);const rankNext=getGroupRank(typeNext);if(rankCurrent!==rankNext){const linesBetween=next.loc.start.line-current.loc.end.line;if(options.newlinesBetween==="always"&&linesBetween<2){isSorted=false;break}if(options.newlinesBetween==="never"&&linesBetween>1){isSorted=false;break}}}}if(!isSorted){const firstImport=imports[0];const lastImport=imports[imports.length-1];const firstExtended=getExtendedRange(firstImport);const lastExtended=getExtendedRange(lastImport);context.report({node:firstImport,loc:{start:firstImport.loc.start,end:lastImport.loc.end},messageId:"importOrder",fix(fixer){const rangeStart=firstExtended[0];const rangeEnd=lastExtended[1];let newCode="";for(let i=0;i<sortedImports.length;i++){const node=sortedImports[i];const importType=getImportType(node);if(i>0&&options.newlinesBetween==="always"){const prevNode=sortedImports[i-1];const prevType=getImportType(prevNode);const prevRank=getGroupRank(prevType);const currRank=getGroupRank(importType);if(prevRank!==currRank){newCode+="\n"}}newCode+=getImportText(node)+"\n"}newCode=newCode.trimEnd();return fixer.replaceTextRange([rangeStart,rangeEnd],newCode)}})}}}}});