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.
Files changed (62) hide show
  1. package/package.json +9 -4
  2. package/src/files/foo.js +1 -6
  3. package/src/files/no-default.js +1 -4
  4. package/src/index.js +1 -326
  5. package/src/oxlint.js +1 -3
  6. package/src/rules/consistent-type-specifier-style.js +1 -109
  7. package/src/rules/default.js +1 -56
  8. package/src/rules/dynamic-import-chunkname.js +1 -115
  9. package/src/rules/enforce-dependency-direction.js +1 -213
  10. package/src/rules/enforce-import-order.js +1 -299
  11. package/src/rules/enforce-team-boundaries.js +1 -191
  12. package/src/rules/export.js +1 -111
  13. package/src/rules/exports-last.js +1 -67
  14. package/src/rules/extensions.js +1 -105
  15. package/src/rules/first.js +1 -53
  16. package/src/rules/group-exports.js +1 -69
  17. package/src/rules/max-dependencies.js +1 -241
  18. package/src/rules/named.js +1 -67
  19. package/src/rules/namespace.js +1 -64
  20. package/src/rules/newline-after-import.js +1 -57
  21. package/src/rules/no-absolute-path.js +1 -107
  22. package/src/rules/no-amd.js +1 -108
  23. package/src/rules/no-anonymous-default-export.js +1 -135
  24. package/src/rules/no-barrel-file.js +1 -194
  25. package/src/rules/no-barrel-import.js +1 -135
  26. package/src/rules/no-commonjs.js +1 -312
  27. package/src/rules/no-cross-domain-imports.js +1 -233
  28. package/src/rules/no-cycle.js +2 -396
  29. package/src/rules/no-default-export.js +2 -213
  30. package/src/rules/no-deprecated.js +1 -316
  31. package/src/rules/no-duplicates.js +1 -81
  32. package/src/rules/no-dynamic-require.js +1 -78
  33. package/src/rules/no-empty-named-blocks.js +1 -103
  34. package/src/rules/no-extraneous-dependencies.js +7 -385
  35. package/src/rules/no-full-package-import.js +1 -134
  36. package/src/rules/no-import-module-exports.js +1 -76
  37. package/src/rules/no-internal-modules.js +1 -256
  38. package/src/rules/no-legacy-imports.js +1 -125
  39. package/src/rules/no-mutable-exports.js +1 -146
  40. package/src/rules/no-named-as-default-member.js +1 -73
  41. package/src/rules/no-named-as-default.js +1 -90
  42. package/src/rules/no-named-default.js +1 -48
  43. package/src/rules/no-named-export.js +1 -174
  44. package/src/rules/no-namespace.js +1 -71
  45. package/src/rules/no-nodejs-modules.js +1 -229
  46. package/src/rules/no-relative-packages.js +1 -129
  47. package/src/rules/no-relative-parent-imports.js +1 -118
  48. package/src/rules/no-restricted-paths.js +1 -89
  49. package/src/rules/no-self-import.js +1 -113
  50. package/src/rules/no-unassigned-import.js +1 -115
  51. package/src/rules/no-unresolved.js +1 -189
  52. package/src/rules/no-unused-modules.js +1 -82
  53. package/src/rules/no-useless-path-segments.js +1 -107
  54. package/src/rules/prefer-default-export.js +1 -188
  55. package/src/rules/prefer-direct-import.js +1 -170
  56. package/src/rules/prefer-modern-api.js +1 -212
  57. package/src/rules/prefer-node-protocol.js +1 -174
  58. package/src/rules/prefer-tree-shakeable-imports.js +1 -134
  59. package/src/rules/require-import-approval.js +1 -174
  60. package/src/rules/unambiguous.js +1 -70
  61. package/src/types/index.js +1 -2
  62. package/src/utils/typescript-peer.js +1 -23
@@ -1,170 +1 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.preferDirectImport = void 0;
4
- const eslint_devkit_1 = require("@interlace/eslint-devkit");
5
- const DEFAULT_MAPPINGS = [
6
- { barrel: '^@/components$', directPath: '@/components/{name}' },
7
- { barrel: '^@/hooks$', directPath: '@/hooks/{name}' },
8
- { barrel: '^@/utils$', directPath: '@/utils/{name}' },
9
- { barrel: '^@/lib$', directPath: '@/lib/{name}' },
10
- { barrel: '^~/components$', directPath: '~/components/{name}' },
11
- { barrel: '^~/hooks$', directPath: '~/hooks/{name}' },
12
- ];
13
- function findMapping(importPath, mappings) {
14
- for (const mapping of mappings) {
15
- try {
16
- const regex = new RegExp(mapping.barrel);
17
- if (regex.test(importPath)) {
18
- return mapping;
19
- }
20
- }
21
- catch {
22
- if (importPath === mapping.barrel) {
23
- return mapping;
24
- }
25
- }
26
- }
27
- return null;
28
- }
29
- function generateDirectPath(template, importedName) {
30
- return template.replace('{name}', importedName);
31
- }
32
- exports.preferDirectImport = (0, eslint_devkit_1.createRule)({
33
- name: 'prefer-direct-import',
34
- meta: {
35
- type: 'suggestion',
36
- docs: {
37
- url: 'https://github.com/ofri-peretz/eslint/blob/main/packages/eslint-plugin-import-next/docs/rules/prefer-direct-import.md',
38
- description: 'Prefer direct imports over barrel imports for better tree-shaking and build performance',
39
- },
40
- fixable: 'code',
41
- hasSuggestions: true,
42
- messages: {
43
- preferDirectImport: (0, eslint_devkit_1.formatLLMMessage)({
44
- icon: eslint_devkit_1.MessageIcons.INFO,
45
- issueName: 'Prefer Direct Import',
46
- description: "Import '{{importedName}}' directly from '{{suggestedPath}}' instead of from the barrel file '{{barrelPath}}'.",
47
- severity: 'LOW',
48
- fix: 'Use direct imports for better tree-shaking:\n' +
49
- " ❌ import { Button } from '@/components';\n" +
50
- " ✅ import { Button } from '@/components/Button';",
51
- documentationLink: 'https://github.com/ofri-peretz/eslint/blob/main/packages/eslint-plugin-import-next/docs/rules/prefer-direct-import.md',
52
- }),
53
- },
54
- schema: [
55
- {
56
- type: 'object',
57
- properties: {
58
- mappings: {
59
- type: 'array',
60
- items: {
61
- type: 'object',
62
- properties: {
63
- barrel: { type: 'string' },
64
- directPath: { type: 'string' },
65
- },
66
- required: ['barrel', 'directPath'],
67
- },
68
- default: [],
69
- description: 'Mapping of barrel paths to direct import patterns',
70
- },
71
- autoFix: {
72
- type: 'boolean',
73
- default: true,
74
- description: 'Auto-fix the imports when possible',
75
- },
76
- },
77
- additionalProperties: false,
78
- },
79
- ],
80
- },
81
- defaultOptions: [
82
- {
83
- mappings: DEFAULT_MAPPINGS,
84
- autoFix: true,
85
- },
86
- ],
87
- create(context, [options = {}]) {
88
- const opts = options || {};
89
- const mappings = opts.mappings ?? DEFAULT_MAPPINGS;
90
- const autoFix = opts.autoFix ?? true;
91
- return {
92
- ImportDeclaration(node) {
93
- const importPath = node.source.value;
94
- if (typeof importPath !== 'string')
95
- return;
96
- if (node.importKind === 'type')
97
- return;
98
- const mapping = findMapping(importPath, mappings);
99
- if (!mapping)
100
- return;
101
- const namedImports = node.specifiers.filter((spec) => spec.type === 'ImportSpecifier');
102
- if (namedImports.length === 0)
103
- return;
104
- if (namedImports.length === 1) {
105
- const importedName = namedImports[0].imported.type === 'Identifier'
106
- ? namedImports[0].imported.name
107
- : namedImports[0].imported.value;
108
- const suggestedPath = generateDirectPath(mapping.directPath, importedName);
109
- context.report({
110
- node,
111
- messageId: 'preferDirectImport',
112
- data: {
113
- importedName,
114
- suggestedPath,
115
- barrelPath: importPath,
116
- },
117
- fix: autoFix
118
- ? (fixer) => {
119
- return fixer.replaceText(node.source, `'${suggestedPath}'`);
120
- }
121
- : undefined,
122
- suggest: !autoFix
123
- ? [
124
- {
125
- messageId: 'preferDirectImport',
126
- data: {
127
- importedName,
128
- suggestedPath,
129
- barrelPath: importPath,
130
- },
131
- fix: (fixer) => {
132
- return fixer.replaceText(node.source, `'${suggestedPath}'`);
133
- },
134
- },
135
- ]
136
- : undefined,
137
- });
138
- }
139
- else {
140
- for (const spec of namedImports) {
141
- const importedName = spec.imported.type === 'Identifier'
142
- ? spec.imported.name
143
- : spec.imported.value;
144
- const suggestedPath = generateDirectPath(mapping.directPath, importedName);
145
- context.report({
146
- node: spec,
147
- messageId: 'preferDirectImport',
148
- data: {
149
- importedName,
150
- suggestedPath,
151
- barrelPath: importPath,
152
- },
153
- suggest: [
154
- {
155
- messageId: 'preferDirectImport',
156
- data: {
157
- importedName,
158
- suggestedPath,
159
- barrelPath: importPath,
160
- },
161
- fix: () => null,
162
- },
163
- ],
164
- });
165
- }
166
- }
167
- },
168
- };
169
- },
170
- });
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.preferDirectImport=void 0;const eslint_devkit_1=require("@interlace/eslint-devkit");const DEFAULT_MAPPINGS=[{barrel:"^@/components$",directPath:"@/components/{name}"},{barrel:"^@/hooks$",directPath:"@/hooks/{name}"},{barrel:"^@/utils$",directPath:"@/utils/{name}"},{barrel:"^@/lib$",directPath:"@/lib/{name}"},{barrel:"^~/components$",directPath:"~/components/{name}"},{barrel:"^~/hooks$",directPath:"~/hooks/{name}"}];function findMapping(importPath,mappings){for(const mapping of mappings){try{const regex=new RegExp(mapping.barrel);if(regex.test(importPath)){return mapping}}catch{if(importPath===mapping.barrel){return mapping}}}return null}function generateDirectPath(template,importedName){return template.replace("{name}",importedName)}exports.preferDirectImport=(0,eslint_devkit_1.createRule)({name:"prefer-direct-import",meta:{type:"suggestion",docs:{url:"https://github.com/ofri-peretz/eslint/blob/main/packages/eslint-plugin-import-next/docs/rules/prefer-direct-import.md",description:"Prefer direct imports over barrel imports for better tree-shaking and build performance"},fixable:"code",hasSuggestions:true,messages:{preferDirectImport:(0,eslint_devkit_1.formatLLMMessage)({icon:eslint_devkit_1.MessageIcons.INFO,issueName:"Prefer Direct Import",description:"Import '{{importedName}}' directly from '{{suggestedPath}}' instead of from the barrel file '{{barrelPath}}'.",severity:"LOW",fix:"Use direct imports for better tree-shaking:\n \u274C import { Button } from '@/components';\n \u2705 import { Button } from '@/components/Button';",documentationLink:"https://github.com/ofri-peretz/eslint/blob/main/packages/eslint-plugin-import-next/docs/rules/prefer-direct-import.md"})},schema:[{type:"object",properties:{mappings:{type:"array",items:{type:"object",properties:{barrel:{type:"string"},directPath:{type:"string"}},required:["barrel","directPath"]},default:[],description:"Mapping of barrel paths to direct import patterns"},autoFix:{type:"boolean",default:true,description:"Auto-fix the imports when possible"}},additionalProperties:false}]},defaultOptions:[{mappings:DEFAULT_MAPPINGS,autoFix:true}],create(context,[options={}]){const opts=options||{};const mappings=opts.mappings??DEFAULT_MAPPINGS;const autoFix=opts.autoFix??true;return{ImportDeclaration(node){const importPath=node.source.value;if(typeof importPath!=="string")return;if(node.importKind==="type")return;const mapping=findMapping(importPath,mappings);if(!mapping)return;const namedImports=node.specifiers.filter(spec=>spec.type==="ImportSpecifier");if(namedImports.length===0)return;if(namedImports.length===1){const importedName=namedImports[0].imported.type==="Identifier"?namedImports[0].imported.name:namedImports[0].imported.value;const suggestedPath=generateDirectPath(mapping.directPath,importedName);context.report({node,messageId:"preferDirectImport",data:{importedName,suggestedPath,barrelPath:importPath},fix:autoFix?fixer=>{return fixer.replaceText(node.source,`'${suggestedPath}'`)}:void 0,suggest:!autoFix?[{messageId:"preferDirectImport",data:{importedName,suggestedPath,barrelPath:importPath},fix:fixer=>{return fixer.replaceText(node.source,`'${suggestedPath}'`)}}]:void 0})}else{for(const spec of namedImports){const importedName=spec.imported.type==="Identifier"?spec.imported.name:spec.imported.value;const suggestedPath=generateDirectPath(mapping.directPath,importedName);context.report({node:spec,messageId:"preferDirectImport",data:{importedName,suggestedPath,barrelPath:importPath},suggest:[{messageId:"preferDirectImport",data:{importedName,suggestedPath,barrelPath:importPath},fix:()=>null}]})}}}}}});
@@ -1,212 +1 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.preferModernApi = void 0;
4
- const eslint_devkit_1 = require("@interlace/eslint-devkit");
5
- const BUILT_IN_MAPPINGS = [
6
- {
7
- deprecated: 'moment',
8
- modern: 'date-fns or dayjs',
9
- reason: 'Moment.js is in maintenance mode. date-fns is tree-shakeable.',
10
- difficulty: 'medium',
11
- migrationGuide: 'https://github.com/date-fns/date-fns/blob/HEAD/docs/moment.md',
12
- },
13
- {
14
- deprecated: 'moment-timezone',
15
- modern: 'date-fns-tz',
16
- reason: 'Maintenance mode. date-fns-tz is smaller and tree-shakeable.',
17
- difficulty: 'medium',
18
- },
19
- {
20
- deprecated: 'request',
21
- modern: 'node-fetch, axios, or undici',
22
- reason: 'request is deprecated since 2020. Use modern alternatives.',
23
- difficulty: 'easy',
24
- },
25
- {
26
- deprecated: 'request-promise',
27
- modern: 'axios or node-fetch',
28
- reason: 'Deprecated with the request package.',
29
- difficulty: 'easy',
30
- },
31
- {
32
- deprecated: 'underscore',
33
- modern: 'lodash-es or native methods',
34
- reason: 'Underscore is outdated. Modern JS has most utilities built-in.',
35
- difficulty: 'medium',
36
- },
37
- {
38
- deprecated: 'mocha',
39
- modern: 'vitest or jest',
40
- reason: 'Vitest offers faster execution and better ESM support.',
41
- difficulty: 'hard',
42
- },
43
- {
44
- deprecated: 'chai',
45
- modern: 'vitest expect or jest',
46
- reason: 'Modern test runners have built-in assertions.',
47
- difficulty: 'medium',
48
- },
49
- {
50
- deprecated: 'gulp',
51
- modern: 'npm scripts or vite',
52
- reason: 'Modern bundlers handle most gulp tasks natively.',
53
- difficulty: 'hard',
54
- },
55
- {
56
- deprecated: 'grunt',
57
- modern: 'npm scripts or vite',
58
- reason: 'Grunt is largely obsolete. Use modern build tools.',
59
- difficulty: 'hard',
60
- },
61
- {
62
- deprecated: 'node-sass',
63
- modern: 'sass (dart-sass)',
64
- reason: 'node-sass is deprecated. dart-sass is the official implementation.',
65
- difficulty: 'easy',
66
- },
67
- {
68
- deprecated: 'bcrypt-nodejs',
69
- modern: 'bcrypt or bcryptjs',
70
- reason: 'bcrypt-nodejs is unmaintained and has security issues.',
71
- difficulty: 'easy',
72
- },
73
- {
74
- deprecated: 'uuid/v4',
75
- modern: 'crypto.randomUUID() or uuid',
76
- reason: 'Node.js 16+ has built-in crypto.randomUUID().',
77
- difficulty: 'easy',
78
- },
79
- {
80
- deprecated: 'redux',
81
- modern: 'zustand, jotai, or redux-toolkit',
82
- reason: 'Modern state libraries have less boilerplate.',
83
- difficulty: 'hard',
84
- },
85
- {
86
- deprecated: 'joi',
87
- modern: 'zod or yup',
88
- reason: 'Zod has better TypeScript integration and smaller bundle.',
89
- difficulty: 'medium',
90
- },
91
- {
92
- deprecated: 'webpack',
93
- modern: 'vite, esbuild, or rspack',
94
- reason: 'Vite and esbuild offer 10-100x faster builds.',
95
- difficulty: 'hard',
96
- },
97
- ];
98
- function matchPackage(importPath, deprecated) {
99
- const packageName = importPath.startsWith('@')
100
- ? importPath.split('/').slice(0, 2).join('/')
101
- : importPath.split('/')[0];
102
- return packageName === deprecated || importPath.startsWith(deprecated + '/');
103
- }
104
- exports.preferModernApi = (0, eslint_devkit_1.createRule)({
105
- name: 'prefer-modern-api',
106
- meta: {
107
- type: 'suggestion',
108
- docs: {
109
- url: 'https://github.com/ofri-peretz/eslint/blob/main/packages/eslint-plugin-import-next/docs/rules/prefer-modern-api.md',
110
- description: 'Suggest modern replacements for deprecated or outdated libraries',
111
- },
112
- messages: {
113
- preferModernApi: (0, eslint_devkit_1.formatLLMMessage)({
114
- icon: eslint_devkit_1.MessageIcons.DEPRECATION,
115
- issueName: 'Outdated Package',
116
- description: "'{{deprecated}}' is outdated. Consider migrating to {{modern}}. " +
117
- "Reason: {{reason}}",
118
- severity: 'LOW',
119
- fix: 'Migration difficulty: {{difficulty}}\n' +
120
- '{{migrationGuide}}',
121
- documentationLink: '',
122
- }),
123
- },
124
- schema: [
125
- {
126
- type: 'object',
127
- properties: {
128
- customMappings: {
129
- type: 'array',
130
- items: {
131
- type: 'object',
132
- properties: {
133
- deprecated: { type: 'string' },
134
- modern: { type: 'string' },
135
- reason: { type: 'string' },
136
- difficulty: { type: 'string', enum: ['easy', 'medium', 'hard'] },
137
- migrationGuide: { type: 'string' },
138
- },
139
- required: ['deprecated', 'modern', 'reason'],
140
- },
141
- },
142
- disableBuiltIn: {
143
- type: 'boolean',
144
- default: false,
145
- },
146
- },
147
- additionalProperties: false,
148
- },
149
- ],
150
- },
151
- defaultOptions: [
152
- {
153
- customMappings: [],
154
- disableBuiltIn: false,
155
- },
156
- ],
157
- create(context, [options = {}]) {
158
- const { customMappings = [], disableBuiltIn = false } = options;
159
- const allMappings = disableBuiltIn
160
- ? customMappings
161
- : [...BUILT_IN_MAPPINGS, ...customMappings];
162
- function checkImport(importPath, node) {
163
- if (importPath.startsWith('.') || importPath.startsWith('/'))
164
- return;
165
- for (const mapping of allMappings) {
166
- if (matchPackage(importPath, mapping.deprecated)) {
167
- context.report({
168
- node,
169
- messageId: 'preferModernApi',
170
- data: {
171
- deprecated: mapping.deprecated,
172
- modern: mapping.modern,
173
- reason: mapping.reason,
174
- difficulty: mapping.difficulty || 'unknown',
175
- migrationGuide: mapping.migrationGuide
176
- ? `See: ${mapping.migrationGuide}`
177
- : 'Check package documentation for migration guide.',
178
- },
179
- });
180
- break;
181
- }
182
- }
183
- }
184
- return {
185
- ImportDeclaration(node) {
186
- const importPath = node.source.value;
187
- if (typeof importPath === 'string') {
188
- checkImport(importPath, node);
189
- }
190
- },
191
- ImportExpression(node) {
192
- if (node.source.type === eslint_devkit_1.AST_NODE_TYPES.Literal) {
193
- const importPath = node.source.value;
194
- if (typeof importPath === 'string') {
195
- checkImport(importPath, node);
196
- }
197
- }
198
- },
199
- CallExpression(node) {
200
- if (node.callee.type === eslint_devkit_1.AST_NODE_TYPES.Identifier &&
201
- node.callee.name === 'require' &&
202
- node.arguments.length > 0 &&
203
- node.arguments[0].type === eslint_devkit_1.AST_NODE_TYPES.Literal) {
204
- const importPath = node.arguments[0].value;
205
- if (typeof importPath === 'string') {
206
- checkImport(importPath, node);
207
- }
208
- }
209
- },
210
- };
211
- },
212
- });
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.preferModernApi=void 0;const eslint_devkit_1=require("@interlace/eslint-devkit");const BUILT_IN_MAPPINGS=[{deprecated:"moment",modern:"date-fns or dayjs",reason:"Moment.js is in maintenance mode. date-fns is tree-shakeable.",difficulty:"medium",migrationGuide:"https://github.com/date-fns/date-fns/blob/HEAD/docs/moment.md"},{deprecated:"moment-timezone",modern:"date-fns-tz",reason:"Maintenance mode. date-fns-tz is smaller and tree-shakeable.",difficulty:"medium"},{deprecated:"request",modern:"node-fetch, axios, or undici",reason:"request is deprecated since 2020. Use modern alternatives.",difficulty:"easy"},{deprecated:"request-promise",modern:"axios or node-fetch",reason:"Deprecated with the request package.",difficulty:"easy"},{deprecated:"underscore",modern:"lodash-es or native methods",reason:"Underscore is outdated. Modern JS has most utilities built-in.",difficulty:"medium"},{deprecated:"mocha",modern:"vitest or jest",reason:"Vitest offers faster execution and better ESM support.",difficulty:"hard"},{deprecated:"chai",modern:"vitest expect or jest",reason:"Modern test runners have built-in assertions.",difficulty:"medium"},{deprecated:"gulp",modern:"npm scripts or vite",reason:"Modern bundlers handle most gulp tasks natively.",difficulty:"hard"},{deprecated:"grunt",modern:"npm scripts or vite",reason:"Grunt is largely obsolete. Use modern build tools.",difficulty:"hard"},{deprecated:"node-sass",modern:"sass (dart-sass)",reason:"node-sass is deprecated. dart-sass is the official implementation.",difficulty:"easy"},{deprecated:"bcrypt-nodejs",modern:"bcrypt or bcryptjs",reason:"bcrypt-nodejs is unmaintained and has security issues.",difficulty:"easy"},{deprecated:"uuid/v4",modern:"crypto.randomUUID() or uuid",reason:"Node.js 16+ has built-in crypto.randomUUID().",difficulty:"easy"},{deprecated:"redux",modern:"zustand, jotai, or redux-toolkit",reason:"Modern state libraries have less boilerplate.",difficulty:"hard"},{deprecated:"joi",modern:"zod or yup",reason:"Zod has better TypeScript integration and smaller bundle.",difficulty:"medium"},{deprecated:"webpack",modern:"vite, esbuild, or rspack",reason:"Vite and esbuild offer 10-100x faster builds.",difficulty:"hard"}];function matchPackage(importPath,deprecated){const packageName=importPath.startsWith("@")?importPath.split("/").slice(0,2).join("/"):importPath.split("/")[0];return packageName===deprecated||importPath.startsWith(deprecated+"/")}exports.preferModernApi=(0,eslint_devkit_1.createRule)({name:"prefer-modern-api",meta:{type:"suggestion",docs:{url:"https://github.com/ofri-peretz/eslint/blob/main/packages/eslint-plugin-import-next/docs/rules/prefer-modern-api.md",description:"Suggest modern replacements for deprecated or outdated libraries"},messages:{preferModernApi:(0,eslint_devkit_1.formatLLMMessage)({icon:eslint_devkit_1.MessageIcons.DEPRECATION,issueName:"Outdated Package",description:"'{{deprecated}}' is outdated. Consider migrating to {{modern}}. Reason: {{reason}}",severity:"LOW",fix:"Migration difficulty: {{difficulty}}\n{{migrationGuide}}",documentationLink:""})},schema:[{type:"object",properties:{customMappings:{type:"array",items:{type:"object",properties:{deprecated:{type:"string"},modern:{type:"string"},reason:{type:"string"},difficulty:{type:"string",enum:["easy","medium","hard"]},migrationGuide:{type:"string"}},required:["deprecated","modern","reason"]}},disableBuiltIn:{type:"boolean",default:false}},additionalProperties:false}]},defaultOptions:[{customMappings:[],disableBuiltIn:false}],create(context,[options={}]){const{customMappings=[],disableBuiltIn=false}=options;const allMappings=disableBuiltIn?customMappings:[...BUILT_IN_MAPPINGS,...customMappings];function checkImport(importPath,node){if(importPath.startsWith(".")||importPath.startsWith("/"))return;for(const mapping of allMappings){if(matchPackage(importPath,mapping.deprecated)){context.report({node,messageId:"preferModernApi",data:{deprecated:mapping.deprecated,modern:mapping.modern,reason:mapping.reason,difficulty:mapping.difficulty||"unknown",migrationGuide:mapping.migrationGuide?`See: ${mapping.migrationGuide}`:"Check package documentation for migration guide."}});break}}}return{ImportDeclaration(node){const importPath=node.source.value;if(typeof importPath==="string"){checkImport(importPath,node)}},ImportExpression(node){if(node.source.type===eslint_devkit_1.AST_NODE_TYPES.Literal){const importPath=node.source.value;if(typeof importPath==="string"){checkImport(importPath,node)}}},CallExpression(node){if(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){const importPath=node.arguments[0].value;if(typeof importPath==="string"){checkImport(importPath,node)}}}}}});
@@ -1,174 +1 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.preferNodeProtocol = void 0;
4
- const eslint_devkit_1 = require("@interlace/eslint-devkit");
5
- const eslint_devkit_2 = require("@interlace/eslint-devkit");
6
- const NODE_BUILT_INS = new Set([
7
- 'assert',
8
- 'async_hooks',
9
- 'buffer',
10
- 'child_process',
11
- 'cluster',
12
- 'console',
13
- 'constants',
14
- 'crypto',
15
- 'dgram',
16
- 'diagnostics_channel',
17
- 'dns',
18
- 'domain',
19
- 'events',
20
- 'fs',
21
- 'http',
22
- 'http2',
23
- 'https',
24
- 'inspector',
25
- 'module',
26
- 'net',
27
- 'os',
28
- 'path',
29
- 'perf_hooks',
30
- 'process',
31
- 'punycode',
32
- 'querystring',
33
- 'readline',
34
- 'repl',
35
- 'stream',
36
- 'string_decoder',
37
- 'sys',
38
- 'timers',
39
- 'tls',
40
- 'trace_events',
41
- 'tty',
42
- 'url',
43
- 'util',
44
- 'v8',
45
- 'vm',
46
- 'wasi',
47
- 'worker_threads',
48
- 'zlib',
49
- ]);
50
- exports.preferNodeProtocol = (0, eslint_devkit_1.createRule)({
51
- name: 'prefer-node-protocol',
52
- meta: {
53
- type: 'suggestion',
54
- docs: {
55
- url: 'https://github.com/ofri-peretz/eslint/blob/main/packages/eslint-plugin-import-next/docs/rules/prefer-node-protocol.md',
56
- description: 'Prefer using the node: protocol when importing Node.js builtin modules',
57
- },
58
- fixable: 'code',
59
- hasSuggestions: true,
60
- messages: {
61
- preferNodeProtocol: (0, eslint_devkit_2.formatLLMMessage)({
62
- icon: eslint_devkit_2.MessageIcons.WARNING,
63
- issueName: 'Node.js Protocol Import',
64
- description: 'Use node: protocol for built-in modules',
65
- severity: 'MEDIUM',
66
- fix: 'Change "{{moduleName}}" to "node:{{moduleName}}" in import',
67
- documentationLink: 'https://nodejs.org/api/modules.html#modules_node_imports',
68
- }),
69
- },
70
- schema: [
71
- {
72
- type: 'object',
73
- properties: {
74
- additionalModules: {
75
- type: 'array',
76
- items: { type: 'string' },
77
- default: [],
78
- },
79
- },
80
- additionalProperties: false,
81
- },
82
- ],
83
- },
84
- defaultOptions: [{}],
85
- create(context, [options = {}]) {
86
- const { additionalModules = [] } = options || {};
87
- const allModulesToCheck = new Set([
88
- ...NODE_BUILT_INS,
89
- ...additionalModules,
90
- ]);
91
- return {
92
- ImportDeclaration(node) {
93
- const moduleName = node.source.value;
94
- if (typeof moduleName === 'string' &&
95
- isBuiltInModule(moduleName, allModulesToCheck)) {
96
- const fixedModuleName = `node:${moduleName}`;
97
- context.report({
98
- node: node.source,
99
- messageId: 'preferNodeProtocol',
100
- data: {
101
- moduleName,
102
- fix: `Change "${moduleName}" to "${fixedModuleName}"`,
103
- },
104
- fix(fixer) {
105
- return fixer.replaceText(node.source, `"${fixedModuleName}"`);
106
- },
107
- });
108
- }
109
- },
110
- CallExpression(node) {
111
- if (node.callee.type === 'Identifier' &&
112
- node.callee.name === 'require' &&
113
- node.arguments.length === 1) {
114
- const arg = node.arguments[0];
115
- if (arg.type === 'Literal' && typeof arg.value === 'string') {
116
- const moduleName = arg.value;
117
- if (isBuiltInModule(moduleName, allModulesToCheck)) {
118
- const fixedModuleName = `node:${moduleName}`;
119
- context.report({
120
- node: arg,
121
- messageId: 'preferNodeProtocol',
122
- data: {
123
- moduleName,
124
- fix: `Change "${moduleName}" to "${fixedModuleName}"`,
125
- },
126
- fix(fixer) {
127
- return fixer.replaceText(arg, `"${fixedModuleName}"`);
128
- },
129
- });
130
- }
131
- }
132
- }
133
- },
134
- ImportExpression(node) {
135
- if (node.source.type === 'Literal' &&
136
- typeof node.source.value === 'string') {
137
- const moduleName = node.source.value;
138
- if (isBuiltInModule(moduleName, allModulesToCheck)) {
139
- const fixedModuleName = `node:${moduleName}`;
140
- context.report({
141
- node: node.source,
142
- messageId: 'preferNodeProtocol',
143
- data: {
144
- moduleName,
145
- fix: `Change "${moduleName}" to "${fixedModuleName}"`,
146
- },
147
- fix(fixer) {
148
- return fixer.replaceText(node.source, `"${fixedModuleName}"`);
149
- },
150
- });
151
- }
152
- }
153
- },
154
- };
155
- function isBuiltInModule(moduleName, modulesToCheck) {
156
- if (moduleName.startsWith('node:')) {
157
- return false;
158
- }
159
- if (modulesToCheck.has(moduleName)) {
160
- return true;
161
- }
162
- const lowerCaseModule = moduleName.toLowerCase();
163
- if (modulesToCheck.has(lowerCaseModule)) {
164
- return true;
165
- }
166
- const baseModule = moduleName.split('/')[0];
167
- if (modulesToCheck.has(baseModule)) {
168
- return true;
169
- }
170
- const lowerCaseBaseModule = baseModule.toLowerCase();
171
- return modulesToCheck.has(lowerCaseBaseModule);
172
- }
173
- },
174
- });
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.preferNodeProtocol=void 0;const eslint_devkit_1=require("@interlace/eslint-devkit");const eslint_devkit_2=require("@interlace/eslint-devkit");const NODE_BUILT_INS=new Set(["assert","async_hooks","buffer","child_process","cluster","console","constants","crypto","dgram","diagnostics_channel","dns","domain","events","fs","http","http2","https","inspector","module","net","os","path","perf_hooks","process","punycode","querystring","readline","repl","stream","string_decoder","sys","timers","tls","trace_events","tty","url","util","v8","vm","wasi","worker_threads","zlib"]);exports.preferNodeProtocol=(0,eslint_devkit_1.createRule)({name:"prefer-node-protocol",meta:{type:"suggestion",docs:{url:"https://github.com/ofri-peretz/eslint/blob/main/packages/eslint-plugin-import-next/docs/rules/prefer-node-protocol.md",description:"Prefer using the node: protocol when importing Node.js builtin modules"},fixable:"code",hasSuggestions:true,messages:{preferNodeProtocol:(0,eslint_devkit_2.formatLLMMessage)({icon:eslint_devkit_2.MessageIcons.WARNING,issueName:"Node.js Protocol Import",description:"Use node: protocol for built-in modules",severity:"MEDIUM",fix:'Change "{{moduleName}}" to "node:{{moduleName}}" in import',documentationLink:"https://nodejs.org/api/modules.html#modules_node_imports"})},schema:[{type:"object",properties:{additionalModules:{type:"array",items:{type:"string"},default:[]}},additionalProperties:false}]},defaultOptions:[{}],create(context,[options={}]){const{additionalModules=[]}=options||{};const allModulesToCheck=new Set([...NODE_BUILT_INS,...additionalModules]);return{ImportDeclaration(node){const moduleName=node.source.value;if(typeof moduleName==="string"&&isBuiltInModule(moduleName,allModulesToCheck)){const fixedModuleName=`node:${moduleName}`;context.report({node:node.source,messageId:"preferNodeProtocol",data:{moduleName,fix:`Change "${moduleName}" to "${fixedModuleName}"`},fix(fixer){return fixer.replaceText(node.source,`"${fixedModuleName}"`)}})}},CallExpression(node){if(node.callee.type==="Identifier"&&node.callee.name==="require"&&node.arguments.length===1){const arg=node.arguments[0];if(arg.type==="Literal"&&typeof arg.value==="string"){const moduleName=arg.value;if(isBuiltInModule(moduleName,allModulesToCheck)){const fixedModuleName=`node:${moduleName}`;context.report({node:arg,messageId:"preferNodeProtocol",data:{moduleName,fix:`Change "${moduleName}" to "${fixedModuleName}"`},fix(fixer){return fixer.replaceText(arg,`"${fixedModuleName}"`)}})}}}},ImportExpression(node){if(node.source.type==="Literal"&&typeof node.source.value==="string"){const moduleName=node.source.value;if(isBuiltInModule(moduleName,allModulesToCheck)){const fixedModuleName=`node:${moduleName}`;context.report({node:node.source,messageId:"preferNodeProtocol",data:{moduleName,fix:`Change "${moduleName}" to "${fixedModuleName}"`},fix(fixer){return fixer.replaceText(node.source,`"${fixedModuleName}"`)}})}}}};function isBuiltInModule(moduleName,modulesToCheck){if(moduleName.startsWith("node:")){return false}if(modulesToCheck.has(moduleName)){return true}const lowerCaseModule=moduleName.toLowerCase();if(modulesToCheck.has(lowerCaseModule)){return true}const baseModule=moduleName.split("/")[0];if(modulesToCheck.has(baseModule)){return true}const lowerCaseBaseModule=baseModule.toLowerCase();return modulesToCheck.has(lowerCaseBaseModule)}}});