eslint-plugin-import-next 2.3.14 → 2.3.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +9 -4
- package/src/files/foo.js +1 -6
- package/src/files/no-default.js +1 -4
- package/src/index.js +1 -326
- package/src/oxlint.js +1 -3
- package/src/rules/consistent-type-specifier-style.js +1 -109
- package/src/rules/default.js +1 -56
- package/src/rules/dynamic-import-chunkname.js +1 -115
- package/src/rules/enforce-dependency-direction.js +1 -213
- package/src/rules/enforce-import-order.js +1 -299
- package/src/rules/enforce-team-boundaries.js +1 -191
- package/src/rules/export.js +1 -111
- package/src/rules/exports-last.js +1 -67
- package/src/rules/extensions.js +1 -105
- package/src/rules/first.js +1 -53
- package/src/rules/group-exports.js +1 -69
- package/src/rules/max-dependencies.js +1 -241
- package/src/rules/named.js +1 -67
- package/src/rules/namespace.js +1 -64
- package/src/rules/newline-after-import.js +1 -57
- package/src/rules/no-absolute-path.js +1 -107
- package/src/rules/no-amd.js +1 -108
- package/src/rules/no-anonymous-default-export.js +1 -135
- package/src/rules/no-barrel-file.js +1 -194
- package/src/rules/no-barrel-import.js +1 -135
- package/src/rules/no-commonjs.js +1 -312
- package/src/rules/no-cross-domain-imports.js +1 -233
- package/src/rules/no-cycle.js +2 -396
- package/src/rules/no-default-export.js +2 -213
- package/src/rules/no-deprecated.js +1 -316
- package/src/rules/no-duplicates.js +1 -81
- package/src/rules/no-dynamic-require.js +1 -78
- package/src/rules/no-empty-named-blocks.js +1 -103
- package/src/rules/no-extraneous-dependencies.js +7 -385
- package/src/rules/no-full-package-import.js +1 -134
- package/src/rules/no-import-module-exports.js +1 -76
- package/src/rules/no-internal-modules.js +1 -256
- package/src/rules/no-legacy-imports.js +1 -125
- package/src/rules/no-mutable-exports.js +1 -146
- package/src/rules/no-named-as-default-member.js +1 -73
- package/src/rules/no-named-as-default.js +1 -90
- package/src/rules/no-named-default.js +1 -48
- package/src/rules/no-named-export.js +1 -174
- package/src/rules/no-namespace.js +1 -71
- package/src/rules/no-nodejs-modules.js +1 -229
- package/src/rules/no-relative-packages.js +1 -129
- package/src/rules/no-relative-parent-imports.js +1 -118
- package/src/rules/no-restricted-paths.js +1 -89
- package/src/rules/no-self-import.js +1 -113
- package/src/rules/no-unassigned-import.js +1 -115
- package/src/rules/no-unresolved.js +1 -189
- package/src/rules/no-unused-modules.js +1 -82
- package/src/rules/no-useless-path-segments.js +1 -107
- package/src/rules/prefer-default-export.js +1 -188
- package/src/rules/prefer-direct-import.js +1 -170
- package/src/rules/prefer-modern-api.js +1 -212
- package/src/rules/prefer-node-protocol.js +1 -174
- package/src/rules/prefer-tree-shakeable-imports.js +1 -134
- package/src/rules/require-import-approval.js +1 -174
- package/src/rules/unambiguous.js +1 -70
- package/src/types/index.js +1 -2
- package/src/utils/typescript-peer.js +1 -23
|
@@ -1,191 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.enforceTeamBoundaries = void 0;
|
|
4
|
-
const eslint_devkit_1 = require("@interlace/eslint-devkit");
|
|
5
|
-
function globToRegex(pattern) {
|
|
6
|
-
const escaped = pattern.replace(/[.+?^${}()|[\]\\*]/g, '\\$&');
|
|
7
|
-
return new RegExp(escaped
|
|
8
|
-
.replace(/\\\*\\\*/g, '.*')
|
|
9
|
-
.replace(/\\\*/g, '[^/]*'));
|
|
10
|
-
}
|
|
11
|
-
function getFileTeam(filePath, teams) {
|
|
12
|
-
for (const team of teams) {
|
|
13
|
-
for (const pattern of team.paths) {
|
|
14
|
-
if (globToRegex(pattern).test(filePath)) {
|
|
15
|
-
return team;
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
return null;
|
|
20
|
-
}
|
|
21
|
-
function getImportTeam(importPath, teams) {
|
|
22
|
-
for (const team of teams) {
|
|
23
|
-
for (const pattern of team.paths) {
|
|
24
|
-
if (globToRegex(pattern).test(importPath)) {
|
|
25
|
-
return team;
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
if (team.publicPackages) {
|
|
29
|
-
for (const pkg of team.publicPackages) {
|
|
30
|
-
if (importPath.startsWith(pkg)) {
|
|
31
|
-
return team;
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
return null;
|
|
37
|
-
}
|
|
38
|
-
function isExternalImport(importPath) {
|
|
39
|
-
if (importPath.startsWith('.') || importPath.startsWith('/')) {
|
|
40
|
-
return false;
|
|
41
|
-
}
|
|
42
|
-
if (importPath.startsWith('@/') || importPath.startsWith('~/')) {
|
|
43
|
-
return false;
|
|
44
|
-
}
|
|
45
|
-
if (importPath.startsWith('src/') ||
|
|
46
|
-
importPath.startsWith('lib/') ||
|
|
47
|
-
importPath.startsWith('packages/') ||
|
|
48
|
-
importPath.startsWith('apps/')) {
|
|
49
|
-
return false;
|
|
50
|
-
}
|
|
51
|
-
return true;
|
|
52
|
-
}
|
|
53
|
-
function isSharedPath(importPath, sharedPaths) {
|
|
54
|
-
for (const shared of sharedPaths) {
|
|
55
|
-
if (globToRegex(shared).test(importPath)) {
|
|
56
|
-
return true;
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
return false;
|
|
60
|
-
}
|
|
61
|
-
exports.enforceTeamBoundaries = (0, eslint_devkit_1.createRule)({
|
|
62
|
-
name: 'enforce-team-boundaries',
|
|
63
|
-
meta: {
|
|
64
|
-
type: 'problem',
|
|
65
|
-
docs: {
|
|
66
|
-
url: 'https://github.com/ofri-peretz/eslint/blob/main/packages/eslint-plugin-import-next/docs/rules/enforce-team-boundaries.md',
|
|
67
|
-
description: 'Prevent unauthorized cross-team imports in large codebases',
|
|
68
|
-
},
|
|
69
|
-
messages: {
|
|
70
|
-
unauthorizedTeamImport: (0, eslint_devkit_1.formatLLMMessage)({
|
|
71
|
-
icon: eslint_devkit_1.MessageIcons.SECURITY,
|
|
72
|
-
issueName: 'Unauthorized Cross-Team Import',
|
|
73
|
-
description: "Team '{{sourceTeam}}' is importing from team '{{targetTeam}}' " +
|
|
74
|
-
"without explicit permission. This creates tight coupling between teams. " +
|
|
75
|
-
"Module: '{{importPath}}'",
|
|
76
|
-
severity: 'HIGH',
|
|
77
|
-
fix: 'Either:\n' +
|
|
78
|
-
" 1. Add '{{targetTeam}}' to allowedDependencies in ESLint config\n" +
|
|
79
|
-
" 2. Move shared code to a public package\n" +
|
|
80
|
-
' 3. Request API from target team via approved interface',
|
|
81
|
-
documentationLink: 'https://nx.dev/concepts/enforce-project-boundaries',
|
|
82
|
-
}),
|
|
83
|
-
},
|
|
84
|
-
schema: [
|
|
85
|
-
{
|
|
86
|
-
type: 'object',
|
|
87
|
-
properties: {
|
|
88
|
-
teams: {
|
|
89
|
-
type: 'array',
|
|
90
|
-
items: {
|
|
91
|
-
type: 'object',
|
|
92
|
-
properties: {
|
|
93
|
-
team: { type: 'string' },
|
|
94
|
-
paths: { type: 'array', items: { type: 'string' } },
|
|
95
|
-
allowedDependencies: {
|
|
96
|
-
type: 'array',
|
|
97
|
-
items: { type: 'string' },
|
|
98
|
-
},
|
|
99
|
-
publicPackages: { type: 'array', items: { type: 'string' } },
|
|
100
|
-
},
|
|
101
|
-
required: ['team', 'paths'],
|
|
102
|
-
},
|
|
103
|
-
},
|
|
104
|
-
sharedPaths: {
|
|
105
|
-
type: 'array',
|
|
106
|
-
items: { type: 'string' },
|
|
107
|
-
default: [],
|
|
108
|
-
},
|
|
109
|
-
allowExternalPackages: {
|
|
110
|
-
type: 'boolean',
|
|
111
|
-
default: true,
|
|
112
|
-
},
|
|
113
|
-
},
|
|
114
|
-
required: ['teams'],
|
|
115
|
-
additionalProperties: false,
|
|
116
|
-
},
|
|
117
|
-
],
|
|
118
|
-
},
|
|
119
|
-
defaultOptions: [
|
|
120
|
-
{
|
|
121
|
-
teams: [],
|
|
122
|
-
sharedPaths: [],
|
|
123
|
-
allowExternalPackages: true,
|
|
124
|
-
},
|
|
125
|
-
],
|
|
126
|
-
create(context, [options]) {
|
|
127
|
-
const { teams, sharedPaths = [], allowExternalPackages = true } = options;
|
|
128
|
-
const filename = context.filename;
|
|
129
|
-
const sourceTeam = getFileTeam(filename, teams);
|
|
130
|
-
if (!sourceTeam) {
|
|
131
|
-
return {};
|
|
132
|
-
}
|
|
133
|
-
const owningTeam = sourceTeam;
|
|
134
|
-
function checkImport(node) {
|
|
135
|
-
let importPath = null;
|
|
136
|
-
if (node.type === eslint_devkit_1.AST_NODE_TYPES.ImportDeclaration) {
|
|
137
|
-
importPath = typeof node.source.value === 'string' ? node.source.value : null;
|
|
138
|
-
}
|
|
139
|
-
else if (node.type === eslint_devkit_1.AST_NODE_TYPES.ImportExpression) {
|
|
140
|
-
if (node.source.type === eslint_devkit_1.AST_NODE_TYPES.Literal) {
|
|
141
|
-
importPath = typeof node.source.value === 'string' ? node.source.value : null;
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
else if (node.type === eslint_devkit_1.AST_NODE_TYPES.CallExpression &&
|
|
145
|
-
node.callee.type === eslint_devkit_1.AST_NODE_TYPES.Identifier &&
|
|
146
|
-
node.callee.name === 'require' &&
|
|
147
|
-
node.arguments.length > 0 &&
|
|
148
|
-
node.arguments[0].type === eslint_devkit_1.AST_NODE_TYPES.Literal) {
|
|
149
|
-
importPath = typeof node.arguments[0].value === 'string' ? node.arguments[0].value : null;
|
|
150
|
-
}
|
|
151
|
-
if (!importPath)
|
|
152
|
-
return;
|
|
153
|
-
if (allowExternalPackages && isExternalImport(importPath)) {
|
|
154
|
-
return;
|
|
155
|
-
}
|
|
156
|
-
if (isSharedPath(importPath, sharedPaths)) {
|
|
157
|
-
return;
|
|
158
|
-
}
|
|
159
|
-
const targetTeam = getImportTeam(importPath, teams);
|
|
160
|
-
if (!targetTeam) {
|
|
161
|
-
return;
|
|
162
|
-
}
|
|
163
|
-
if (targetTeam.team === owningTeam.team) {
|
|
164
|
-
return;
|
|
165
|
-
}
|
|
166
|
-
const allowedDeps = owningTeam.allowedDependencies || [];
|
|
167
|
-
if (allowedDeps.includes(targetTeam.team)) {
|
|
168
|
-
return;
|
|
169
|
-
}
|
|
170
|
-
context.report({
|
|
171
|
-
node,
|
|
172
|
-
messageId: 'unauthorizedTeamImport',
|
|
173
|
-
data: {
|
|
174
|
-
sourceTeam: owningTeam.team,
|
|
175
|
-
targetTeam: targetTeam.team,
|
|
176
|
-
importPath,
|
|
177
|
-
},
|
|
178
|
-
});
|
|
179
|
-
}
|
|
180
|
-
return {
|
|
181
|
-
ImportDeclaration: checkImport,
|
|
182
|
-
ImportExpression: checkImport,
|
|
183
|
-
CallExpression(node) {
|
|
184
|
-
if (node.callee.type === eslint_devkit_1.AST_NODE_TYPES.Identifier &&
|
|
185
|
-
node.callee.name === 'require') {
|
|
186
|
-
checkImport(node);
|
|
187
|
-
}
|
|
188
|
-
},
|
|
189
|
-
};
|
|
190
|
-
},
|
|
191
|
-
});
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.enforceTeamBoundaries=void 0;const eslint_devkit_1=require("@interlace/eslint-devkit");function globToRegex(pattern){const escaped=pattern.replace(/[.+?^${}()|[\]\\*]/g,"\\$&");return new RegExp(escaped.replace(/\\\*\\\*/g,".*").replace(/\\\*/g,"[^/]*"))}function getFileTeam(filePath,teams){for(const team of teams){for(const pattern of team.paths){if(globToRegex(pattern).test(filePath)){return team}}}return null}function getImportTeam(importPath,teams){for(const team of teams){for(const pattern of team.paths){if(globToRegex(pattern).test(importPath)){return team}}if(team.publicPackages){for(const pkg of team.publicPackages){if(importPath.startsWith(pkg)){return team}}}}return null}function isExternalImport(importPath){if(importPath.startsWith(".")||importPath.startsWith("/")){return false}if(importPath.startsWith("@/")||importPath.startsWith("~/")){return false}if(importPath.startsWith("src/")||importPath.startsWith("lib/")||importPath.startsWith("packages/")||importPath.startsWith("apps/")){return false}return true}function isSharedPath(importPath,sharedPaths){for(const shared of sharedPaths){if(globToRegex(shared).test(importPath)){return true}}return false}exports.enforceTeamBoundaries=(0,eslint_devkit_1.createRule)({name:"enforce-team-boundaries",meta:{type:"problem",docs:{url:"https://github.com/ofri-peretz/eslint/blob/main/packages/eslint-plugin-import-next/docs/rules/enforce-team-boundaries.md",description:"Prevent unauthorized cross-team imports in large codebases"},messages:{unauthorizedTeamImport:(0,eslint_devkit_1.formatLLMMessage)({icon:eslint_devkit_1.MessageIcons.SECURITY,issueName:"Unauthorized Cross-Team Import",description:"Team '{{sourceTeam}}' is importing from team '{{targetTeam}}' without explicit permission. This creates tight coupling between teams. Module: '{{importPath}}'",severity:"HIGH",fix:"Either:\n 1. Add '{{targetTeam}}' to allowedDependencies in ESLint config\n 2. Move shared code to a public package\n 3. Request API from target team via approved interface",documentationLink:"https://nx.dev/concepts/enforce-project-boundaries"})},schema:[{type:"object",properties:{teams:{type:"array",items:{type:"object",properties:{team:{type:"string"},paths:{type:"array",items:{type:"string"}},allowedDependencies:{type:"array",items:{type:"string"}},publicPackages:{type:"array",items:{type:"string"}}},required:["team","paths"]}},sharedPaths:{type:"array",items:{type:"string"},default:[]},allowExternalPackages:{type:"boolean",default:true}},required:["teams"],additionalProperties:false}]},defaultOptions:[{teams:[],sharedPaths:[],allowExternalPackages:true}],create(context,[options]){const{teams,sharedPaths=[],allowExternalPackages=true}=options;const filename=context.filename;const sourceTeam=getFileTeam(filename,teams);if(!sourceTeam){return{}}const owningTeam=sourceTeam;function checkImport(node){let importPath=null;if(node.type===eslint_devkit_1.AST_NODE_TYPES.ImportDeclaration){importPath=typeof node.source.value==="string"?node.source.value:null}else if(node.type===eslint_devkit_1.AST_NODE_TYPES.ImportExpression){if(node.source.type===eslint_devkit_1.AST_NODE_TYPES.Literal){importPath=typeof node.source.value==="string"?node.source.value:null}}else if(node.type===eslint_devkit_1.AST_NODE_TYPES.CallExpression&&node.callee.type===eslint_devkit_1.AST_NODE_TYPES.Identifier&&node.callee.name==="require"&&node.arguments.length>0&&node.arguments[0].type===eslint_devkit_1.AST_NODE_TYPES.Literal){importPath=typeof node.arguments[0].value==="string"?node.arguments[0].value:null}if(!importPath)return;if(allowExternalPackages&&isExternalImport(importPath)){return}if(isSharedPath(importPath,sharedPaths)){return}const targetTeam=getImportTeam(importPath,teams);if(!targetTeam){return}if(targetTeam.team===owningTeam.team){return}const allowedDeps=owningTeam.allowedDependencies||[];if(allowedDeps.includes(targetTeam.team)){return}context.report({node,messageId:"unauthorizedTeamImport",data:{sourceTeam:owningTeam.team,targetTeam:targetTeam.team,importPath}})}return{ImportDeclaration:checkImport,ImportExpression:checkImport,CallExpression(node){if(node.callee.type===eslint_devkit_1.AST_NODE_TYPES.Identifier&&node.callee.name==="require"){checkImport(node)}}}}});
|
package/src/rules/export.js
CHANGED
|
@@ -1,111 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.exportRule = void 0;
|
|
4
|
-
const eslint_devkit_1 = require("@interlace/eslint-devkit");
|
|
5
|
-
exports.exportRule = (0, eslint_devkit_1.createRule)({
|
|
6
|
-
name: 'export',
|
|
7
|
-
meta: {
|
|
8
|
-
type: 'problem',
|
|
9
|
-
docs: {
|
|
10
|
-
url: 'https://github.com/ofri-peretz/eslint/blob/main/packages/eslint-plugin-import-next/docs/rules/export.md',
|
|
11
|
-
description: 'Forbid any invalid exports, i.e. re-export of the same name',
|
|
12
|
-
cwe: 'CWE-694',
|
|
13
|
-
cvss: 7.5,
|
|
14
|
-
},
|
|
15
|
-
messages: {
|
|
16
|
-
duplicateExport: (0, eslint_devkit_1.formatLLMMessage)({
|
|
17
|
-
icon: eslint_devkit_1.MessageIcons.ARCHITECTURE,
|
|
18
|
-
issueName: 'Duplicate Export',
|
|
19
|
-
cwe: 'CWE-694',
|
|
20
|
-
description: 'Multiple exports of name "{{name}}"',
|
|
21
|
-
severity: 'HIGH',
|
|
22
|
-
fix: 'Remove duplicate export or rename one of them',
|
|
23
|
-
documentationLink: 'https://github.com/import-js/eslint-plugin-import/blob/main/docs/rules/export.md',
|
|
24
|
-
}),
|
|
25
|
-
duplicateDefault: (0, eslint_devkit_1.formatLLMMessage)({
|
|
26
|
-
icon: eslint_devkit_1.MessageIcons.ARCHITECTURE,
|
|
27
|
-
issueName: 'Duplicate Default Export',
|
|
28
|
-
cwe: 'CWE-694',
|
|
29
|
-
description: 'Multiple default exports',
|
|
30
|
-
severity: 'HIGH',
|
|
31
|
-
fix: 'A module can only have one default export',
|
|
32
|
-
documentationLink: 'https://github.com/import-js/eslint-plugin-import/blob/main/docs/rules/export.md',
|
|
33
|
-
}),
|
|
34
|
-
},
|
|
35
|
-
schema: [],
|
|
36
|
-
},
|
|
37
|
-
defaultOptions: [],
|
|
38
|
-
create(context) {
|
|
39
|
-
const exportedNames = new Map();
|
|
40
|
-
let hasDefaultExport = null;
|
|
41
|
-
function checkAndAddExport(name, node) {
|
|
42
|
-
if (exportedNames.has(name)) {
|
|
43
|
-
context.report({
|
|
44
|
-
node,
|
|
45
|
-
messageId: 'duplicateExport',
|
|
46
|
-
data: { name },
|
|
47
|
-
});
|
|
48
|
-
}
|
|
49
|
-
else {
|
|
50
|
-
exportedNames.set(name, node);
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
function checkDefaultExport(node) {
|
|
54
|
-
if (hasDefaultExport) {
|
|
55
|
-
context.report({
|
|
56
|
-
node,
|
|
57
|
-
messageId: 'duplicateDefault',
|
|
58
|
-
});
|
|
59
|
-
}
|
|
60
|
-
else {
|
|
61
|
-
hasDefaultExport = node;
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
return {
|
|
65
|
-
ExportDefaultDeclaration(node) {
|
|
66
|
-
checkDefaultExport(node);
|
|
67
|
-
},
|
|
68
|
-
ExportNamedDeclaration(node) {
|
|
69
|
-
if (node.declaration) {
|
|
70
|
-
if (node.declaration.type === eslint_devkit_1.AST_NODE_TYPES.VariableDeclaration) {
|
|
71
|
-
node.declaration.declarations.forEach((decl) => {
|
|
72
|
-
if (decl.id.type === eslint_devkit_1.AST_NODE_TYPES.Identifier) {
|
|
73
|
-
checkAndAddExport(decl.id.name, node);
|
|
74
|
-
}
|
|
75
|
-
});
|
|
76
|
-
}
|
|
77
|
-
else if (node.declaration.type === eslint_devkit_1.AST_NODE_TYPES.FunctionDeclaration ||
|
|
78
|
-
node.declaration.type === eslint_devkit_1.AST_NODE_TYPES.ClassDeclaration) {
|
|
79
|
-
if (node.declaration.id) {
|
|
80
|
-
checkAndAddExport(node.declaration.id.name, node);
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
else if (node.declaration.type === eslint_devkit_1.AST_NODE_TYPES.TSEnumDeclaration ||
|
|
84
|
-
node.declaration.type === eslint_devkit_1.AST_NODE_TYPES.TSInterfaceDeclaration ||
|
|
85
|
-
node.declaration.type === eslint_devkit_1.AST_NODE_TYPES.TSTypeAliasDeclaration) {
|
|
86
|
-
if (node.declaration.id) {
|
|
87
|
-
checkAndAddExport(node.declaration.id.name, node);
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
node.specifiers.forEach((spec) => {
|
|
92
|
-
const exportedName = spec.exported.type === eslint_devkit_1.AST_NODE_TYPES.Identifier
|
|
93
|
-
? spec.exported.name
|
|
94
|
-
: spec.exported.value;
|
|
95
|
-
if (exportedName === 'default') {
|
|
96
|
-
checkDefaultExport(spec);
|
|
97
|
-
}
|
|
98
|
-
else {
|
|
99
|
-
checkAndAddExport(exportedName, spec);
|
|
100
|
-
}
|
|
101
|
-
});
|
|
102
|
-
},
|
|
103
|
-
ExportAllDeclaration(node) {
|
|
104
|
-
if (node.exported) {
|
|
105
|
-
const exportedName = node.exported.name;
|
|
106
|
-
checkAndAddExport(exportedName, node);
|
|
107
|
-
}
|
|
108
|
-
},
|
|
109
|
-
};
|
|
110
|
-
},
|
|
111
|
-
});
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.exportRule=void 0;const eslint_devkit_1=require("@interlace/eslint-devkit");exports.exportRule=(0,eslint_devkit_1.createRule)({name:"export",meta:{type:"problem",docs:{url:"https://github.com/ofri-peretz/eslint/blob/main/packages/eslint-plugin-import-next/docs/rules/export.md",description:"Forbid any invalid exports, i.e. re-export of the same name",cwe:"CWE-694",cvss:7.5},messages:{duplicateExport:(0,eslint_devkit_1.formatLLMMessage)({icon:eslint_devkit_1.MessageIcons.ARCHITECTURE,issueName:"Duplicate Export",cwe:"CWE-694",description:'Multiple exports of name "{{name}}"',severity:"HIGH",fix:"Remove duplicate export or rename one of them",documentationLink:"https://github.com/import-js/eslint-plugin-import/blob/main/docs/rules/export.md"}),duplicateDefault:(0,eslint_devkit_1.formatLLMMessage)({icon:eslint_devkit_1.MessageIcons.ARCHITECTURE,issueName:"Duplicate Default Export",cwe:"CWE-694",description:"Multiple default exports",severity:"HIGH",fix:"A module can only have one default export",documentationLink:"https://github.com/import-js/eslint-plugin-import/blob/main/docs/rules/export.md"})},schema:[]},defaultOptions:[],create(context){const exportedNames=new Map;let hasDefaultExport=null;function checkAndAddExport(name,node){if(exportedNames.has(name)){context.report({node,messageId:"duplicateExport",data:{name}})}else{exportedNames.set(name,node)}}function checkDefaultExport(node){if(hasDefaultExport){context.report({node,messageId:"duplicateDefault"})}else{hasDefaultExport=node}}return{ExportDefaultDeclaration(node){checkDefaultExport(node)},ExportNamedDeclaration(node){if(node.declaration){if(node.declaration.type===eslint_devkit_1.AST_NODE_TYPES.VariableDeclaration){node.declaration.declarations.forEach(decl=>{if(decl.id.type===eslint_devkit_1.AST_NODE_TYPES.Identifier){checkAndAddExport(decl.id.name,node)}})}else if(node.declaration.type===eslint_devkit_1.AST_NODE_TYPES.FunctionDeclaration||node.declaration.type===eslint_devkit_1.AST_NODE_TYPES.ClassDeclaration){if(node.declaration.id){checkAndAddExport(node.declaration.id.name,node)}}else if(node.declaration.type===eslint_devkit_1.AST_NODE_TYPES.TSEnumDeclaration||node.declaration.type===eslint_devkit_1.AST_NODE_TYPES.TSInterfaceDeclaration||node.declaration.type===eslint_devkit_1.AST_NODE_TYPES.TSTypeAliasDeclaration){if(node.declaration.id){checkAndAddExport(node.declaration.id.name,node)}}}node.specifiers.forEach(spec=>{const exportedName=spec.exported.type===eslint_devkit_1.AST_NODE_TYPES.Identifier?spec.exported.name:spec.exported.value;if(exportedName==="default"){checkDefaultExport(spec)}else{checkAndAddExport(exportedName,spec)}})},ExportAllDeclaration(node){if(node.exported){const exportedName=node.exported.name;checkAndAddExport(exportedName,node)}}}}});
|
|
@@ -1,67 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.exportsLast = void 0;
|
|
4
|
-
const eslint_devkit_1 = require("@interlace/eslint-devkit");
|
|
5
|
-
exports.exportsLast = (0, eslint_devkit_1.createRule)({
|
|
6
|
-
name: 'exports-last',
|
|
7
|
-
meta: {
|
|
8
|
-
type: 'suggestion',
|
|
9
|
-
docs: {
|
|
10
|
-
url: 'https://github.com/ofri-peretz/eslint/blob/main/packages/eslint-plugin-import-next/docs/rules/exports-last.md',
|
|
11
|
-
description: 'Ensure all exports appear after other statements',
|
|
12
|
-
cwe: 'CWE-1078',
|
|
13
|
-
cvss: 2.5,
|
|
14
|
-
},
|
|
15
|
-
messages: {
|
|
16
|
-
exportNotLast: (0, eslint_devkit_1.formatLLMMessage)({
|
|
17
|
-
icon: eslint_devkit_1.MessageIcons.ARCHITECTURE,
|
|
18
|
-
issueName: 'Export Not Last',
|
|
19
|
-
cwe: 'CWE-1078',
|
|
20
|
-
description: 'Export statements should appear at the end of the file',
|
|
21
|
-
severity: 'LOW',
|
|
22
|
-
fix: 'Move this export to the end of the file',
|
|
23
|
-
documentationLink: 'https://github.com/import-js/eslint-plugin-import/blob/main/docs/rules/exports-last.md',
|
|
24
|
-
}),
|
|
25
|
-
},
|
|
26
|
-
schema: [],
|
|
27
|
-
},
|
|
28
|
-
defaultOptions: [],
|
|
29
|
-
create(context) {
|
|
30
|
-
return {
|
|
31
|
-
'Program:exit'(node) {
|
|
32
|
-
const body = node.body;
|
|
33
|
-
let lastNonExportIndex = -1;
|
|
34
|
-
const exportIndices = [];
|
|
35
|
-
const nonExportIndices = [];
|
|
36
|
-
body.forEach((statement, index) => {
|
|
37
|
-
const isExport = statement.type === eslint_devkit_1.AST_NODE_TYPES.ExportDefaultDeclaration ||
|
|
38
|
-
statement.type === eslint_devkit_1.AST_NODE_TYPES.ExportNamedDeclaration ||
|
|
39
|
-
statement.type === eslint_devkit_1.AST_NODE_TYPES.ExportAllDeclaration;
|
|
40
|
-
if (isExport) {
|
|
41
|
-
if (statement.type === eslint_devkit_1.AST_NODE_TYPES.ExportNamedDeclaration &&
|
|
42
|
-
statement.declaration) {
|
|
43
|
-
nonExportIndices.push(index);
|
|
44
|
-
}
|
|
45
|
-
else {
|
|
46
|
-
exportIndices.push(index);
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
else {
|
|
50
|
-
nonExportIndices.push(index);
|
|
51
|
-
}
|
|
52
|
-
});
|
|
53
|
-
if (nonExportIndices.length > 0) {
|
|
54
|
-
lastNonExportIndex = Math.max(...nonExportIndices);
|
|
55
|
-
}
|
|
56
|
-
for (const exportIndex of exportIndices) {
|
|
57
|
-
if (exportIndex < lastNonExportIndex) {
|
|
58
|
-
context.report({
|
|
59
|
-
node: body[exportIndex],
|
|
60
|
-
messageId: 'exportNotLast',
|
|
61
|
-
});
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
},
|
|
65
|
-
};
|
|
66
|
-
},
|
|
67
|
-
});
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.exportsLast=void 0;const eslint_devkit_1=require("@interlace/eslint-devkit");exports.exportsLast=(0,eslint_devkit_1.createRule)({name:"exports-last",meta:{type:"suggestion",docs:{url:"https://github.com/ofri-peretz/eslint/blob/main/packages/eslint-plugin-import-next/docs/rules/exports-last.md",description:"Ensure all exports appear after other statements",cwe:"CWE-1078",cvss:2.5},messages:{exportNotLast:(0,eslint_devkit_1.formatLLMMessage)({icon:eslint_devkit_1.MessageIcons.ARCHITECTURE,issueName:"Export Not Last",cwe:"CWE-1078",description:"Export statements should appear at the end of the file",severity:"LOW",fix:"Move this export to the end of the file",documentationLink:"https://github.com/import-js/eslint-plugin-import/blob/main/docs/rules/exports-last.md"})},schema:[]},defaultOptions:[],create(context){return{"Program:exit"(node){const body=node.body;let lastNonExportIndex=-1;const exportIndices=[];const nonExportIndices=[];body.forEach((statement,index)=>{const isExport=statement.type===eslint_devkit_1.AST_NODE_TYPES.ExportDefaultDeclaration||statement.type===eslint_devkit_1.AST_NODE_TYPES.ExportNamedDeclaration||statement.type===eslint_devkit_1.AST_NODE_TYPES.ExportAllDeclaration;if(isExport){if(statement.type===eslint_devkit_1.AST_NODE_TYPES.ExportNamedDeclaration&&statement.declaration){nonExportIndices.push(index)}else{exportIndices.push(index)}}else{nonExportIndices.push(index)}});if(nonExportIndices.length>0){lastNonExportIndex=Math.max(...nonExportIndices)}for(const exportIndex of exportIndices){if(exportIndex<lastNonExportIndex){context.report({node:body[exportIndex],messageId:"exportNotLast"})}}}}}});
|
package/src/rules/extensions.js
CHANGED
|
@@ -1,105 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.extensions = void 0;
|
|
4
|
-
const tslib_1 = require("tslib");
|
|
5
|
-
const eslint_devkit_1 = require("@interlace/eslint-devkit");
|
|
6
|
-
const eslint_devkit_2 = require("@interlace/eslint-devkit");
|
|
7
|
-
const node_path_1 = tslib_1.__importDefault(require("node:path"));
|
|
8
|
-
exports.extensions = (0, eslint_devkit_1.createRule)({
|
|
9
|
-
name: 'extensions',
|
|
10
|
-
meta: {
|
|
11
|
-
type: 'suggestion',
|
|
12
|
-
docs: {
|
|
13
|
-
url: 'https://github.com/ofri-peretz/eslint/blob/main/packages/eslint-plugin-import-next/docs/rules/extensions.md',
|
|
14
|
-
description: 'Ensure consistent use of file extensions in imports',
|
|
15
|
-
},
|
|
16
|
-
fixable: 'code',
|
|
17
|
-
messages: {
|
|
18
|
-
missingExtension: (0, eslint_devkit_2.formatLLMMessage)({
|
|
19
|
-
icon: eslint_devkit_2.MessageIcons.ARCHITECTURE,
|
|
20
|
-
issueName: 'Missing Extension',
|
|
21
|
-
description: 'Missing file extension in import',
|
|
22
|
-
severity: 'MEDIUM',
|
|
23
|
-
fix: 'Add the file extension (e.g., .js, .ts)',
|
|
24
|
-
documentationLink: 'https://github.com/import-js/eslint-plugin-import/blob/main/docs/rules/extensions.md',
|
|
25
|
-
}),
|
|
26
|
-
unexpectedExtension: (0, eslint_devkit_2.formatLLMMessage)({
|
|
27
|
-
icon: eslint_devkit_2.MessageIcons.ARCHITECTURE,
|
|
28
|
-
issueName: 'Unexpected Extension',
|
|
29
|
-
description: 'Unexpected file extension in import',
|
|
30
|
-
severity: 'MEDIUM',
|
|
31
|
-
fix: 'Remove the file extension',
|
|
32
|
-
documentationLink: 'https://github.com/import-js/eslint-plugin-import/blob/main/docs/rules/extensions.md',
|
|
33
|
-
}),
|
|
34
|
-
},
|
|
35
|
-
schema: [
|
|
36
|
-
{
|
|
37
|
-
type: 'object',
|
|
38
|
-
properties: {
|
|
39
|
-
pattern: {
|
|
40
|
-
type: 'object',
|
|
41
|
-
additionalProperties: { type: 'string', enum: ['always', 'never'] },
|
|
42
|
-
},
|
|
43
|
-
default: { type: 'string', enum: ['always', 'never'] },
|
|
44
|
-
},
|
|
45
|
-
additionalProperties: false,
|
|
46
|
-
},
|
|
47
|
-
],
|
|
48
|
-
},
|
|
49
|
-
defaultOptions: [
|
|
50
|
-
{
|
|
51
|
-
default: 'never',
|
|
52
|
-
pattern: {
|
|
53
|
-
js: 'never',
|
|
54
|
-
ts: 'never',
|
|
55
|
-
tsx: 'never',
|
|
56
|
-
jsx: 'never',
|
|
57
|
-
json: 'always',
|
|
58
|
-
css: 'always',
|
|
59
|
-
scss: 'always',
|
|
60
|
-
svg: 'always',
|
|
61
|
-
png: 'always',
|
|
62
|
-
jpg: 'always',
|
|
63
|
-
},
|
|
64
|
-
},
|
|
65
|
-
],
|
|
66
|
-
create(context) {
|
|
67
|
-
const [options = {}] = context.options;
|
|
68
|
-
const defaultBehavior = options.default ?? 'never';
|
|
69
|
-
const pattern = options.pattern ?? {
|
|
70
|
-
js: 'never',
|
|
71
|
-
ts: 'never',
|
|
72
|
-
tsx: 'never',
|
|
73
|
-
jsx: 'never',
|
|
74
|
-
json: 'always',
|
|
75
|
-
css: 'always',
|
|
76
|
-
scss: 'always',
|
|
77
|
-
};
|
|
78
|
-
return {
|
|
79
|
-
ImportDeclaration(node) {
|
|
80
|
-
const source = node.source.value;
|
|
81
|
-
if (!source.startsWith('.'))
|
|
82
|
-
return;
|
|
83
|
-
const ext = node_path_1.default.extname(source).slice(1);
|
|
84
|
-
const expected = pattern[ext] || defaultBehavior;
|
|
85
|
-
if (ext && expected === 'never') {
|
|
86
|
-
context.report({
|
|
87
|
-
node: node.source,
|
|
88
|
-
messageId: 'unexpectedExtension',
|
|
89
|
-
fix(fixer) {
|
|
90
|
-
return fixer.replaceText(node.source, `'${source.slice(0, -ext.length - 1)}'`);
|
|
91
|
-
},
|
|
92
|
-
});
|
|
93
|
-
}
|
|
94
|
-
else if (!ext) {
|
|
95
|
-
if (defaultBehavior === 'always') {
|
|
96
|
-
context.report({
|
|
97
|
-
node: node.source,
|
|
98
|
-
messageId: 'missingExtension',
|
|
99
|
-
});
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
},
|
|
103
|
-
};
|
|
104
|
-
},
|
|
105
|
-
});
|
|
1
|
+
"use strict";var __importDefault=this&&this.__importDefault||function(mod){return mod&&mod.__esModule?mod:{"default":mod}};Object.defineProperty(exports,"__esModule",{value:true});exports.extensions=void 0;const eslint_devkit_1=require("@interlace/eslint-devkit");const eslint_devkit_2=require("@interlace/eslint-devkit");const node_path_1=__importDefault(require("node:path"));exports.extensions=(0,eslint_devkit_1.createRule)({name:"extensions",meta:{type:"suggestion",docs:{url:"https://github.com/ofri-peretz/eslint/blob/main/packages/eslint-plugin-import-next/docs/rules/extensions.md",description:"Ensure consistent use of file extensions in imports"},fixable:"code",messages:{missingExtension:(0,eslint_devkit_2.formatLLMMessage)({icon:eslint_devkit_2.MessageIcons.ARCHITECTURE,issueName:"Missing Extension",description:"Missing file extension in import",severity:"MEDIUM",fix:"Add the file extension (e.g., .js, .ts)",documentationLink:"https://github.com/import-js/eslint-plugin-import/blob/main/docs/rules/extensions.md"}),unexpectedExtension:(0,eslint_devkit_2.formatLLMMessage)({icon:eslint_devkit_2.MessageIcons.ARCHITECTURE,issueName:"Unexpected Extension",description:"Unexpected file extension in import",severity:"MEDIUM",fix:"Remove the file extension",documentationLink:"https://github.com/import-js/eslint-plugin-import/blob/main/docs/rules/extensions.md"})},schema:[{type:"object",properties:{pattern:{type:"object",additionalProperties:{type:"string",enum:["always","never"]}},default:{type:"string",enum:["always","never"]}},additionalProperties:false}]},defaultOptions:[{default:"never",pattern:{js:"never",ts:"never",tsx:"never",jsx:"never",json:"always",css:"always",scss:"always",svg:"always",png:"always",jpg:"always"}}],create(context){const[options={}]=context.options;const defaultBehavior=options.default??"never";const pattern=options.pattern??{js:"never",ts:"never",tsx:"never",jsx:"never",json:"always",css:"always",scss:"always"};return{ImportDeclaration(node){const source=node.source.value;if(!source.startsWith("."))return;const ext=node_path_1.default.extname(source).slice(1);const expected=pattern[ext]||defaultBehavior;if(ext&&expected==="never"){context.report({node:node.source,messageId:"unexpectedExtension",fix(fixer){return fixer.replaceText(node.source,`'${source.slice(0,-ext.length-1)}'`)}})}else if(!ext){if(defaultBehavior==="always"){context.report({node:node.source,messageId:"missingExtension"})}}}}}});
|
package/src/rules/first.js
CHANGED
|
@@ -1,53 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.first = void 0;
|
|
4
|
-
const eslint_devkit_1 = require("@interlace/eslint-devkit");
|
|
5
|
-
const eslint_devkit_2 = require("@interlace/eslint-devkit");
|
|
6
|
-
exports.first = (0, eslint_devkit_1.createRule)({
|
|
7
|
-
name: 'first',
|
|
8
|
-
meta: {
|
|
9
|
-
type: 'suggestion',
|
|
10
|
-
docs: {
|
|
11
|
-
url: 'https://github.com/ofri-peretz/eslint/blob/main/packages/eslint-plugin-import-next/docs/rules/first.md',
|
|
12
|
-
description: 'Ensure all imports appear before other statements',
|
|
13
|
-
},
|
|
14
|
-
messages: {
|
|
15
|
-
first: (0, eslint_devkit_2.formatLLMMessage)({
|
|
16
|
-
icon: eslint_devkit_2.MessageIcons.ARCHITECTURE,
|
|
17
|
-
issueName: 'Import Placement',
|
|
18
|
-
description: 'Import statements should be at the top of the file',
|
|
19
|
-
severity: 'MEDIUM',
|
|
20
|
-
fix: 'Move import to the top of the file',
|
|
21
|
-
documentationLink: 'https://github.com/import-js/eslint-plugin-import/blob/main/docs/rules/first.md',
|
|
22
|
-
}),
|
|
23
|
-
},
|
|
24
|
-
schema: [],
|
|
25
|
-
},
|
|
26
|
-
defaultOptions: [],
|
|
27
|
-
create(context) {
|
|
28
|
-
return {
|
|
29
|
-
ImportDeclaration(node) {
|
|
30
|
-
const sourceCode = context.sourceCode;
|
|
31
|
-
const body = sourceCode.ast.body;
|
|
32
|
-
const index = body.indexOf(node);
|
|
33
|
-
if (index > 0) {
|
|
34
|
-
const prevNode = body[index - 1];
|
|
35
|
-
if (prevNode.type !== 'ImportDeclaration' &&
|
|
36
|
-
prevNode.type !== 'TSImportEqualsDeclaration' &&
|
|
37
|
-
!isDirective(prevNode)) {
|
|
38
|
-
context.report({
|
|
39
|
-
node,
|
|
40
|
-
messageId: 'first',
|
|
41
|
-
});
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
},
|
|
45
|
-
};
|
|
46
|
-
function isDirective(node) {
|
|
47
|
-
return (node.type === 'ExpressionStatement' &&
|
|
48
|
-
node.expression.type === 'Literal' &&
|
|
49
|
-
typeof node.expression.value === 'string' &&
|
|
50
|
-
node.expression.value.startsWith('use '));
|
|
51
|
-
}
|
|
52
|
-
},
|
|
53
|
-
});
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.first=void 0;const eslint_devkit_1=require("@interlace/eslint-devkit");const eslint_devkit_2=require("@interlace/eslint-devkit");exports.first=(0,eslint_devkit_1.createRule)({name:"first",meta:{type:"suggestion",docs:{url:"https://github.com/ofri-peretz/eslint/blob/main/packages/eslint-plugin-import-next/docs/rules/first.md",description:"Ensure all imports appear before other statements"},messages:{first:(0,eslint_devkit_2.formatLLMMessage)({icon:eslint_devkit_2.MessageIcons.ARCHITECTURE,issueName:"Import Placement",description:"Import statements should be at the top of the file",severity:"MEDIUM",fix:"Move import to the top of the file",documentationLink:"https://github.com/import-js/eslint-plugin-import/blob/main/docs/rules/first.md"})},schema:[]},defaultOptions:[],create(context){return{ImportDeclaration(node){const sourceCode=context.sourceCode;const body=sourceCode.ast.body;const index=body.indexOf(node);if(index>0){const prevNode=body[index-1];if(prevNode.type!=="ImportDeclaration"&&prevNode.type!=="TSImportEqualsDeclaration"&&!isDirective(prevNode)){context.report({node,messageId:"first"})}}}};function isDirective(node){return node.type==="ExpressionStatement"&&node.expression.type==="Literal"&&typeof node.expression.value==="string"&&node.expression.value.startsWith("use ")}}});
|
|
@@ -1,69 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.groupExports = void 0;
|
|
4
|
-
const eslint_devkit_1 = require("@interlace/eslint-devkit");
|
|
5
|
-
exports.groupExports = (0, eslint_devkit_1.createRule)({
|
|
6
|
-
name: 'group-exports',
|
|
7
|
-
meta: {
|
|
8
|
-
type: 'suggestion',
|
|
9
|
-
docs: {
|
|
10
|
-
url: 'https://github.com/ofri-peretz/eslint/blob/main/packages/eslint-plugin-import-next/docs/rules/group-exports.md',
|
|
11
|
-
description: 'Prefer named exports to be grouped together in a single export declaration',
|
|
12
|
-
cwe: 'CWE-1078',
|
|
13
|
-
cvss: 2.5,
|
|
14
|
-
},
|
|
15
|
-
messages: {
|
|
16
|
-
groupExports: (0, eslint_devkit_1.formatLLMMessage)({
|
|
17
|
-
icon: eslint_devkit_1.MessageIcons.ARCHITECTURE,
|
|
18
|
-
issueName: 'Scattered Exports',
|
|
19
|
-
cwe: 'CWE-1078',
|
|
20
|
-
description: 'Multiple export statements can be grouped into a single export',
|
|
21
|
-
severity: 'LOW',
|
|
22
|
-
fix: 'Combine exports into: export { a, b, c }',
|
|
23
|
-
documentationLink: 'https://github.com/import-js/eslint-plugin-import/blob/main/docs/rules/group-exports.md',
|
|
24
|
-
}),
|
|
25
|
-
},
|
|
26
|
-
schema: [],
|
|
27
|
-
},
|
|
28
|
-
defaultOptions: [],
|
|
29
|
-
create(context) {
|
|
30
|
-
const separateExports = [];
|
|
31
|
-
const reExportSources = new Map();
|
|
32
|
-
return {
|
|
33
|
-
ExportNamedDeclaration(node) {
|
|
34
|
-
if (!node.declaration && node.specifiers.length > 0) {
|
|
35
|
-
if (node.source) {
|
|
36
|
-
const source = node.source.value;
|
|
37
|
-
if (!reExportSources.has(source)) {
|
|
38
|
-
reExportSources.set(source, []);
|
|
39
|
-
}
|
|
40
|
-
reExportSources.get(source)?.push(node);
|
|
41
|
-
}
|
|
42
|
-
else {
|
|
43
|
-
separateExports.push(node);
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
},
|
|
47
|
-
'Program:exit'() {
|
|
48
|
-
if (separateExports.length > 1) {
|
|
49
|
-
for (let i = 1; i < separateExports.length; i++) {
|
|
50
|
-
context.report({
|
|
51
|
-
node: separateExports[i],
|
|
52
|
-
messageId: 'groupExports',
|
|
53
|
-
});
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
for (const [, exports] of reExportSources) {
|
|
57
|
-
if (exports.length > 1) {
|
|
58
|
-
for (let i = 1; i < exports.length; i++) {
|
|
59
|
-
context.report({
|
|
60
|
-
node: exports[i],
|
|
61
|
-
messageId: 'groupExports',
|
|
62
|
-
});
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
},
|
|
67
|
-
};
|
|
68
|
-
},
|
|
69
|
-
});
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.groupExports=void 0;const eslint_devkit_1=require("@interlace/eslint-devkit");exports.groupExports=(0,eslint_devkit_1.createRule)({name:"group-exports",meta:{type:"suggestion",docs:{url:"https://github.com/ofri-peretz/eslint/blob/main/packages/eslint-plugin-import-next/docs/rules/group-exports.md",description:"Prefer named exports to be grouped together in a single export declaration",cwe:"CWE-1078",cvss:2.5},messages:{groupExports:(0,eslint_devkit_1.formatLLMMessage)({icon:eslint_devkit_1.MessageIcons.ARCHITECTURE,issueName:"Scattered Exports",cwe:"CWE-1078",description:"Multiple export statements can be grouped into a single export",severity:"LOW",fix:"Combine exports into: export { a, b, c }",documentationLink:"https://github.com/import-js/eslint-plugin-import/blob/main/docs/rules/group-exports.md"})},schema:[]},defaultOptions:[],create(context){const separateExports=[];const reExportSources=new Map;return{ExportNamedDeclaration(node){if(!node.declaration&&node.specifiers.length>0){if(node.source){const source=node.source.value;if(!reExportSources.has(source)){reExportSources.set(source,[])}reExportSources.get(source)?.push(node)}else{separateExports.push(node)}}},"Program:exit"(){if(separateExports.length>1){for(let i=1;i<separateExports.length;i++){context.report({node:separateExports[i],messageId:"groupExports"})}}for(const[,exports2]of reExportSources){if(exports2.length>1){for(let i=1;i<exports2.length;i++){context.report({node:exports2[i],messageId:"groupExports"})}}}}}}});
|