first commit

This commit is contained in:
2025-10-26 23:10:15 +08:00
commit 8f0345b7be
14961 changed files with 2356381 additions and 0 deletions

View File

@@ -0,0 +1,5 @@
import type { TSESLint } from '@typescript-eslint/utils';
export type Options = 'prefer-inline' | 'prefer-top-level';
type MessageId = 'inline' | 'topLevel';
declare const _default: TSESLint.RuleModule<MessageId, [(Options | undefined)?], import("../utils/create-rule.ts").ImportXPluginDocs, TSESLint.RuleListener>;
export default _default;

View File

@@ -0,0 +1,172 @@
import { createRule, getValue } from '../utils/index.js';
function isComma(token) {
return token.type === 'Punctuator' && token.value === ',';
}
function removeSpecifiers(fixes, fixer, sourceCode, specifiers) {
for (const specifier of specifiers) {
const token = sourceCode.getTokenAfter(specifier);
if (token && isComma(token)) {
fixes.push(fixer.remove(token));
}
fixes.push(fixer.remove(specifier));
}
}
function getImportText(node, sourceCode, specifiers, kind) {
const sourceString = sourceCode.getText(node.source);
if (specifiers.length === 0) {
return '';
}
const names = specifiers.map(s => {
const importedName = getValue(s.imported);
if (importedName === s.local.name) {
return importedName;
}
return `${importedName} as ${s.local.name}`;
});
return `import ${kind} {${names.join(', ')}} from ${sourceString};`;
}
export default createRule({
name: 'consistent-type-specifier-style',
meta: {
type: 'suggestion',
docs: {
category: 'Style guide',
description: 'Enforce or ban the use of inline type-only markers for named imports.',
},
fixable: 'code',
schema: [
{
type: 'string',
enum: ['prefer-top-level', 'prefer-inline'],
default: 'prefer-top-level',
},
],
messages: {
inline: 'Prefer using inline {{kind}} specifiers instead of a top-level {{kind}}-only import.',
topLevel: 'Prefer using a top-level {{kind}}-only import instead of inline {{kind}} specifiers.',
},
},
defaultOptions: [],
create(context) {
const { sourceCode } = context;
if (context.options[0] === 'prefer-inline') {
return {
ImportDeclaration(node) {
if (node.importKind === 'value' || node.importKind == null) {
return;
}
if (node.specifiers.length === 0 ||
(node.specifiers.length === 1 &&
(node.specifiers[0].type === 'ImportDefaultSpecifier' ||
node.specifiers[0].type === 'ImportNamespaceSpecifier'))) {
return;
}
context.report({
node,
messageId: 'inline',
data: {
kind: node.importKind,
},
fix(fixer) {
const kindToken = sourceCode.getFirstToken(node, { skip: 1 });
return [
kindToken ? fixer.remove(kindToken) : [],
node.specifiers.map(specifier => fixer.insertTextBefore(specifier, `${node.importKind} `)),
].flat();
},
});
},
};
}
return {
ImportDeclaration(node) {
if (node.importKind === 'type' ||
node.importKind === 'typeof' ||
node.specifiers.length === 0 ||
(node.specifiers.length === 1 &&
(node.specifiers[0].type === 'ImportDefaultSpecifier' ||
node.specifiers[0].type === 'ImportNamespaceSpecifier'))) {
return;
}
const typeSpecifiers = [];
const typeofSpecifiers = [];
const valueSpecifiers = [];
let defaultSpecifier = null;
for (const specifier of node.specifiers) {
if (specifier.type === 'ImportDefaultSpecifier') {
defaultSpecifier = specifier;
continue;
}
if (!('importKind' in specifier)) {
continue;
}
if (specifier.importKind === 'type') {
typeSpecifiers.push(specifier);
}
else if (specifier.importKind === 'typeof') {
typeofSpecifiers.push(specifier);
}
else if (specifier.importKind === 'value' ||
specifier.importKind == null) {
valueSpecifiers.push(specifier);
}
}
const typeImport = getImportText(node, sourceCode, typeSpecifiers, 'type');
const typeofImport = getImportText(node, sourceCode, typeofSpecifiers, 'typeof');
const newImports = `${typeImport}\n${typeofImport}`.trim();
if (typeSpecifiers.length + typeofSpecifiers.length ===
node.specifiers.length) {
const kind = [
typeSpecifiers.length > 0 ? 'type' : [],
typeofSpecifiers.length > 0 ? 'typeof' : [],
].flat();
context.report({
node,
messageId: 'topLevel',
data: {
kind: kind.join('/'),
},
fix(fixer) {
return fixer.replaceText(node, newImports);
},
});
}
else {
for (const specifier of [...typeSpecifiers, ...typeofSpecifiers]) {
context.report({
node: specifier,
messageId: 'topLevel',
data: {
kind: specifier.importKind,
},
fix(fixer) {
const fixes = [];
if (valueSpecifiers.length > 0) {
removeSpecifiers(fixes, fixer, sourceCode, typeSpecifiers);
removeSpecifiers(fixes, fixer, sourceCode, typeofSpecifiers);
const maybeComma = sourceCode.getTokenAfter(valueSpecifiers[valueSpecifiers.length - 1]);
if (isComma(maybeComma)) {
fixes.push(fixer.remove(maybeComma));
}
}
else if (defaultSpecifier) {
const comma = sourceCode.getTokenAfter(defaultSpecifier, isComma);
const closingBrace = sourceCode.getTokenAfter(node.specifiers[node.specifiers.length - 1], token => token.type === 'Punctuator' && token.value === '}');
fixes.push(fixer.removeRange([
comma.range[0],
closingBrace.range[1],
]));
}
return [
...fixes,
fixer.insertTextAfter(node, `\n${newImports}`),
];
},
});
}
}
},
};
},
});
//# sourceMappingURL=consistent-type-specifier-style.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,3 @@
export type MessageId = 'noDefaultExport';
declare const _default: import("@typescript-eslint/utils/ts-eslint").RuleModule<"noDefaultExport", [], import("../utils/create-rule.ts").ImportXPluginDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
export default _default;

View File

@@ -0,0 +1,45 @@
import { ExportMap, createRule } from '../utils/index.js';
export default createRule({
name: 'default',
meta: {
type: 'problem',
docs: {
category: 'Static analysis',
description: 'Ensure a default export is present, given a default import.',
},
schema: [],
messages: {
noDefaultExport: 'No default export found in imported module "{{module}}".',
},
},
defaultOptions: [],
create(context) {
function checkDefault(specifierType, node) {
const defaultSpecifier = node.specifiers.find(specifier => specifier.type === specifierType);
if (!defaultSpecifier) {
return;
}
const imports = ExportMap.get(node.source.value, context);
if (imports == null) {
return;
}
if (imports.errors.length > 0) {
imports.reportErrors(context, node);
}
else if (imports.get('default') === undefined) {
context.report({
node: defaultSpecifier,
messageId: 'noDefaultExport',
data: {
module: node.source.value,
},
});
}
}
return {
ImportDeclaration: checkDefault.bind(null, 'ImportDefaultSpecifier'),
ExportNamedDeclaration: checkDefault.bind(null, 'ExportDefaultSpecifier'),
};
},
});
//# sourceMappingURL=default.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"default.js","sourceRoot":"","sources":["../../src/rules/default.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAIzD,eAAe,UAAU,CAAgB;IACvC,IAAI,EAAE,SAAS;IACf,IAAI,EAAE;QACJ,IAAI,EAAE,SAAS;QACf,IAAI,EAAE;YACJ,QAAQ,EAAE,iBAAiB;YAC3B,WAAW,EACT,6DAA6D;SAChE;QACD,MAAM,EAAE,EAAE;QACV,QAAQ,EAAE;YACR,eAAe,EACb,0DAA0D;SAC7D;KACF;IACD,cAAc,EAAE,EAAE;IAClB,MAAM,CAAC,OAAO;QACZ,SAAS,YAAY,CACnB,aAAkE,EAClE,IAAkE;YAElE,MAAM,gBAAgB,GACpB,IAAI,CAAC,UAGN,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,SAAS,CAAC,IAAI,KAAK,aAAa,CAAC,CAAA;YAErD,IAAI,CAAC,gBAAgB,EAAE,CAAC;gBACtB,OAAM;YACR,CAAC;YACD,MAAM,OAAO,GAAG,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,MAAO,CAAC,KAAK,EAAE,OAAO,CAAC,CAAA;YAC1D,IAAI,OAAO,IAAI,IAAI,EAAE,CAAC;gBACpB,OAAM;YACR,CAAC;YAED,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC9B,OAAO,CAAC,YAAY,CAAC,OAAO,EAAE,IAAI,CAAC,CAAA;YACrC,CAAC;iBAAM,IAAI,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,KAAK,SAAS,EAAE,CAAC;gBAChD,OAAO,CAAC,MAAM,CAAC;oBACb,IAAI,EAAE,gBAAgB;oBACtB,SAAS,EAAE,iBAAiB;oBAC5B,IAAI,EAAE;wBACJ,MAAM,EAAE,IAAI,CAAC,MAAO,CAAC,KAAK;qBAC3B;iBACF,CAAC,CAAA;YACJ,CAAC;QACH,CAAC;QAED,OAAO;YACL,iBAAiB,EAAE,YAAY,CAAC,IAAI,CAAC,IAAI,EAAE,wBAAwB,CAAC;YACpE,sBAAsB,EAAE,YAAY,CAAC,IAAI,CAAC,IAAI,EAAE,wBAAwB,CAAC;SAC1E,CAAA;IACH,CAAC;CACF,CAAC,CAAA"}

View File

@@ -0,0 +1,9 @@
import type { TSESLint } from '@typescript-eslint/utils';
export interface Options {
allowEmpty?: boolean;
importFunctions?: readonly string[];
webpackChunknameFormat?: string;
}
export type MessageId = 'leadingComment' | 'blockComment' | 'paddedSpaces' | 'webpackComment' | 'chunknameFormat' | 'webpackEagerModeNoChunkName' | 'webpackRemoveEagerMode' | 'webpackRemoveChunkName';
declare const _default: TSESLint.RuleModule<MessageId, [(Options | undefined)?], import("../utils/create-rule.ts").ImportXPluginDocs, TSESLint.RuleListener>;
export default _default;

View File

@@ -0,0 +1,184 @@
import vm from 'node:vm';
import { createRule } from '../utils/index.js';
export default createRule({
name: 'dynamic-import-chunkname',
meta: {
type: 'suggestion',
docs: {
category: 'Style guide',
description: 'Enforce a leading comment with the webpackChunkName for dynamic imports.',
},
hasSuggestions: true,
schema: [
{
type: 'object',
properties: {
importFunctions: {
type: 'array',
uniqueItems: true,
items: {
type: 'string',
},
},
allowEmpty: {
type: 'boolean',
},
webpackChunknameFormat: {
type: 'string',
},
},
},
],
messages: {
leadingComment: 'dynamic imports require a leading comment with the webpack chunkname',
blockComment: 'dynamic imports require a /* foo */ style comment, not a // foo comment',
paddedSpaces: 'dynamic imports require a block comment padded with spaces - /* foo */',
webpackComment: 'dynamic imports require a "webpack" comment with valid syntax',
chunknameFormat: 'dynamic imports require a leading comment in the form /* {{format}} */',
webpackEagerModeNoChunkName: 'dynamic imports using eager mode do not need a webpackChunkName',
webpackRemoveEagerMode: 'Remove webpackMode',
webpackRemoveChunkName: 'Remove webpackChunkName',
},
},
defaultOptions: [],
create(context) {
const { importFunctions = [], allowEmpty = false, webpackChunknameFormat = String.raw `([0-9a-zA-Z-_/.]|\[(request|index)\])+`, } = context.options[0] || {};
const paddedCommentRegex = /^ (\S[\S\s]+\S) $/;
const commentStyleRegex = /^( (((webpackChunkName|webpackFetchPriority): .+)|((webpackPrefetch|webpackPreload): (true|false|-?\d+))|(webpackIgnore: (true|false))|((webpackInclude|webpackExclude): \/.+\/)|(webpackMode: ["'](lazy|lazy-once|eager|weak)["'])|(webpackExports: (["']\w+["']|\[(["']\w+["'], *)+(["']\w+["']*)]))),?)+ $/;
const chunkSubstrFormat = `webpackChunkName: ["']${webpackChunknameFormat}["'],?`;
const chunkSubstrRegex = new RegExp(chunkSubstrFormat);
const eagerModeFormat = `webpackMode: ["']eager["'],?`;
const eagerModeRegex = new RegExp(eagerModeFormat);
function run(node, arg) {
const { sourceCode } = context;
const leadingComments = sourceCode.getCommentsBefore(arg);
if ((!leadingComments || leadingComments.length === 0) && !allowEmpty) {
context.report({
node,
messageId: 'leadingComment',
});
return;
}
let isChunknamePresent = false;
let isEagerModePresent = false;
for (const comment of leadingComments) {
if (comment.type !== 'Block') {
context.report({
node,
messageId: 'blockComment',
});
return;
}
if (!paddedCommentRegex.test(comment.value)) {
context.report({
node,
messageId: 'paddedSpaces',
});
return;
}
try {
vm.runInNewContext(`(function() {return {${comment.value}}})()`);
}
catch {
context.report({
node,
messageId: 'webpackComment',
});
return;
}
if (!commentStyleRegex.test(comment.value)) {
context.report({
node,
messageId: 'webpackComment',
});
return;
}
if (eagerModeRegex.test(comment.value)) {
isEagerModePresent = true;
}
if (chunkSubstrRegex.test(comment.value)) {
isChunknamePresent = true;
}
}
const removeCommentsAndLeadingSpaces = (fixer, comment) => {
const leftToken = sourceCode.getTokenBefore(comment);
const leftComments = sourceCode.getCommentsBefore(comment);
if (leftToken) {
if (leftComments.length > 0) {
return fixer.removeRange([
Math.max(leftToken.range[1], leftComments[leftComments.length - 1].range[1]),
comment.range[1],
]);
}
return fixer.removeRange([leftToken.range[1], comment.range[1]]);
}
return fixer.remove(comment);
};
if (isChunknamePresent && isEagerModePresent) {
context.report({
node,
messageId: 'webpackEagerModeNoChunkName',
suggest: [
{
messageId: 'webpackRemoveChunkName',
fix(fixer) {
for (const comment of leadingComments) {
if (chunkSubstrRegex.test(comment.value)) {
const replacement = comment.value
.replace(chunkSubstrRegex, '')
.trim()
.replace(/,$/, '');
return replacement === ''
? removeCommentsAndLeadingSpaces(fixer, comment)
: fixer.replaceText(comment, `/* ${replacement} */`);
}
}
return null;
},
},
{
messageId: 'webpackRemoveEagerMode',
fix(fixer) {
for (const comment of leadingComments) {
if (eagerModeRegex.test(comment.value)) {
const replacement = comment.value
.replace(eagerModeRegex, '')
.trim()
.replace(/,$/, '');
return replacement === ''
? removeCommentsAndLeadingSpaces(fixer, comment)
: fixer.replaceText(comment, `/* ${replacement} */`);
}
}
return null;
},
},
],
});
}
if (!isChunknamePresent && !allowEmpty && !isEagerModePresent) {
context.report({
node,
messageId: 'chunknameFormat',
data: {
format: chunkSubstrFormat,
},
});
}
}
return {
ImportExpression(node) {
run(node, node.source);
},
CallExpression(node) {
if (node.callee.type !== 'Import' &&
(!('name' in node.callee) ||
!importFunctions.includes(node.callee.name))) {
return;
}
run(node, node.arguments[0]);
},
};
},
});
//# sourceMappingURL=dynamic-import-chunkname.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,3 @@
export type MessageId = 'noNamed' | 'multiDefault' | 'multiNamed';
declare const _default: import("@typescript-eslint/utils/ts-eslint").RuleModule<MessageId, [], import("../utils/create-rule.ts").ImportXPluginDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
export default _default;

172
node_modules/eslint-plugin-import-x/lib/rules/export.js generated vendored Normal file
View File

@@ -0,0 +1,172 @@
import { AST_NODE_TYPES } from '@typescript-eslint/types';
import { ExportMap, recursivePatternCapture, createRule, getValue, } from '../utils/index.js';
const rootProgram = 'root';
const tsTypePrefix = 'type:';
function removeTypescriptFunctionOverloads(nodes) {
for (const node of nodes) {
const declType = node.type === AST_NODE_TYPES.ExportDefaultDeclaration
? node.declaration.type
: node.parent?.type;
if (declType === AST_NODE_TYPES.TSDeclareFunction) {
nodes.delete(node);
}
}
}
function isTypescriptNamespaceMerging(nodes) {
const types = new Set(Array.from(nodes, node => `${node.parent.type}`));
const noNamespaceNodes = [...nodes].filter(node => node.parent.type !== 'TSModuleDeclaration');
return (types.has('TSModuleDeclaration') &&
(types.size === 1 ||
(types.size === 2 &&
(types.has('FunctionDeclaration') || types.has('TSDeclareFunction'))) ||
(types.size === 3 &&
types.has('FunctionDeclaration') &&
types.has('TSDeclareFunction')) ||
(types.size === 2 &&
(types.has('ClassDeclaration') || types.has('TSEnumDeclaration')) &&
noNamespaceNodes.length === 1)));
}
function shouldSkipTypescriptNamespace(node, nodes) {
const types = new Set(Array.from(nodes, node => `${node.parent.type}`));
return (!isTypescriptNamespaceMerging(nodes) &&
node.parent.type === 'TSModuleDeclaration' &&
(types.has('TSEnumDeclaration') ||
types.has('ClassDeclaration') ||
types.has('FunctionDeclaration') ||
types.has('TSDeclareFunction')));
}
export default createRule({
name: 'export',
meta: {
type: 'problem',
docs: {
category: 'Helpful warnings',
description: 'Forbid any invalid exports, i.e. re-export of the same name.',
},
schema: [],
messages: {
noNamed: "No named exports found in module '{{module}}'.",
multiDefault: 'Multiple default exports.',
multiNamed: "Multiple exports of name '{{name}}'.",
},
},
defaultOptions: [],
create(context) {
const namespace = new Map([[rootProgram, new Map()]]);
function addNamed(name, node, parent, isType) {
if (!namespace.has(parent)) {
namespace.set(parent, new Map());
}
const named = namespace.get(parent);
const key = isType ? `${tsTypePrefix}${name}` : name;
let nodes = named.get(key);
if (nodes == null) {
nodes = new Set();
named.set(key, nodes);
}
nodes.add(node);
}
function getParent(node) {
if (node.parent?.type === 'TSModuleBlock') {
return node.parent.parent;
}
return rootProgram;
}
return {
ExportDefaultDeclaration(node) {
addNamed('default', node, getParent(node));
},
ExportSpecifier(node) {
addNamed(getValue(node.exported), node.exported, getParent(node.parent));
},
ExportNamedDeclaration(node) {
if (node.declaration == null) {
return;
}
const parent = getParent(node);
const isTypeVariableDecl = 'kind' in node.declaration &&
node.declaration.kind === 'type';
if ('id' in node.declaration && node.declaration.id != null) {
const id = node.declaration.id;
addNamed(id.name, id, parent, ['TSTypeAliasDeclaration', 'TSInterfaceDeclaration'].includes(node.declaration.type) || isTypeVariableDecl);
}
if ('declarations' in node.declaration &&
node.declaration.declarations != null) {
for (const declaration of node.declaration.declarations) {
recursivePatternCapture(declaration.id, v => {
addNamed(v.name, v, parent, isTypeVariableDecl);
});
}
}
},
ExportAllDeclaration(node) {
if (node.source == null) {
return;
}
if (node.exported && node.exported.name) {
return;
}
const remoteExports = ExportMap.get(node.source.value, context);
if (remoteExports == null) {
return;
}
if (remoteExports.errors.length > 0) {
remoteExports.reportErrors(context, node);
return;
}
const parent = getParent(node);
let any = false;
remoteExports.$forEach((_, name) => {
if (name !== 'default') {
any = true;
addNamed(name, node, parent);
}
});
if (!any) {
context.report({
node: node.source,
messageId: 'noNamed',
data: { module: node.source.value },
});
}
},
'Program:exit'() {
for (const [, named] of namespace) {
for (const [name, nodes] of named) {
if (nodes.size === 0) {
continue;
}
removeTypescriptFunctionOverloads(nodes);
if (nodes.size <= 1) {
continue;
}
if (isTypescriptNamespaceMerging(nodes)) {
continue;
}
for (const node of nodes) {
if (shouldSkipTypescriptNamespace(node, nodes)) {
continue;
}
if (name === 'default') {
context.report({
node,
messageId: 'multiDefault',
});
}
else {
context.report({
node,
messageId: 'multiNamed',
data: {
name: name.replace(tsTypePrefix, ''),
},
});
}
}
}
}
},
};
},
});
//# sourceMappingURL=export.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,2 @@
declare const _default: import("@typescript-eslint/utils/ts-eslint").RuleModule<"end", [], import("../utils/create-rule.ts").ImportXPluginDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
export default _default;

View File

@@ -0,0 +1,49 @@
import { createRule } from '../utils/index.js';
const findLastIndex = (array, predicate) => {
let i = array.length - 1;
while (i >= 0) {
if (predicate(array[i])) {
return i;
}
i--;
}
return -1;
};
function isNonExportStatement({ type }) {
return (type !== 'ExportDefaultDeclaration' &&
type !== 'ExportNamedDeclaration' &&
type !== 'ExportAllDeclaration');
}
export default createRule({
name: 'exports-last',
meta: {
type: 'suggestion',
docs: {
category: 'Style guide',
description: 'Ensure all exports appear after other statements.',
},
schema: [],
messages: {
end: 'Export statements should appear at the end of the file',
},
},
defaultOptions: [],
create(context) {
return {
Program({ body }) {
const lastNonExportStatementIndex = findLastIndex(body, isNonExportStatement);
if (lastNonExportStatementIndex !== -1) {
for (const node of body.slice(0, lastNonExportStatementIndex)) {
if (!isNonExportStatement(node)) {
context.report({
node,
messageId: 'end',
});
}
}
}
},
};
},
});
//# sourceMappingURL=exports-last.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"exports-last.js","sourceRoot":"","sources":["../../src/rules/exports-last.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAE9C,MAAM,aAAa,GAAG,CAAI,KAAU,EAAE,SAA+B,EAAE,EAAE;IACvE,IAAI,CAAC,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,CAAA;IACxB,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QACd,IAAI,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YACxB,OAAO,CAAC,CAAA;QACV,CAAC;QACD,CAAC,EAAE,CAAA;IACL,CAAC;IACD,OAAO,CAAC,CAAC,CAAA;AACX,CAAC,CAAA;AAED,SAAS,oBAAoB,CAAC,EAAE,IAAI,EAAiB;IACnD,OAAO,CACL,IAAI,KAAK,0BAA0B;QACnC,IAAI,KAAK,wBAAwB;QACjC,IAAI,KAAK,sBAAsB,CAChC,CAAA;AACH,CAAC;AAED,eAAe,UAAU,CAAC;IACxB,IAAI,EAAE,cAAc;IACpB,IAAI,EAAE;QACJ,IAAI,EAAE,YAAY;QAClB,IAAI,EAAE;YACJ,QAAQ,EAAE,aAAa;YACvB,WAAW,EAAE,mDAAmD;SACjE;QACD,MAAM,EAAE,EAAE;QACV,QAAQ,EAAE;YACR,GAAG,EAAE,wDAAwD;SAC9D;KACF;IACD,cAAc,EAAE,EAAE;IAClB,MAAM,CAAC,OAAO;QACZ,OAAO;YACL,OAAO,CAAC,EAAE,IAAI,EAAE;gBACd,MAAM,2BAA2B,GAAG,aAAa,CAC/C,IAAI,EACJ,oBAAoB,CACrB,CAAA;gBAED,IAAI,2BAA2B,KAAK,CAAC,CAAC,EAAE,CAAC;oBACvC,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,2BAA2B,CAAC,EAAE,CAAC;wBAC9D,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC,EAAE,CAAC;4BAChC,OAAO,CAAC,MAAM,CAAC;gCACb,IAAI;gCACJ,SAAS,EAAE,KAAK;6BACjB,CAAC,CAAA;wBACJ,CAAC;oBACH,CAAC;gBACH,CAAC;YACH,CAAC;SACF,CAAA;IACH,CAAC;CACF,CAAC,CAAA"}

View File

@@ -0,0 +1,35 @@
import type { TSESLint } from '@typescript-eslint/utils';
import type { MinimatchOptions } from 'minimatch';
declare const modifierValues: readonly ["always", "ignorePackages", "never"];
export type Modifier = (typeof modifierValues)[number];
export type ModifierByFileExtension = Partial<Record<string, Modifier>>;
export interface OptionsItemWithPatternProperty {
ignorePackages?: boolean;
checkTypeImports?: boolean;
pattern: ModifierByFileExtension;
pathGroupOverrides?: PathGroupOverride[];
fix?: boolean;
}
export interface PathGroupOverride {
pattern: string;
patternOptions?: Record<string, MinimatchOptions>;
action: 'enforce' | 'ignore';
}
export interface OptionsItemWithoutPatternProperty {
ignorePackages?: boolean;
checkTypeImports?: boolean;
pathGroupOverrides?: PathGroupOverride[];
fix?: boolean;
}
export type Options = [] | [OptionsItemWithoutPatternProperty] | [OptionsItemWithPatternProperty] | [Modifier] | [Modifier, OptionsItemWithoutPatternProperty] | [Modifier, OptionsItemWithPatternProperty] | [Modifier, ModifierByFileExtension] | [ModifierByFileExtension];
export interface NormalizedOptions {
defaultConfig?: Modifier;
pattern?: Record<string, Modifier>;
ignorePackages?: boolean;
checkTypeImports?: boolean;
pathGroupOverrides?: PathGroupOverride[];
fix?: boolean;
}
export type MessageId = 'missing' | 'missingKnown' | 'unexpected' | 'addMissing' | 'removeUnexpected';
declare const _default: TSESLint.RuleModule<MessageId, Options, import("../utils/create-rule.ts").ImportXPluginDocs, TSESLint.RuleListener>;
export default _default;

View File

@@ -0,0 +1,302 @@
import path from 'node:path';
import { minimatch } from 'minimatch';
import { isBuiltIn, isExternalModule, isScoped, createRule, moduleVisitor, resolve, parsePath, stringifyPath, } from '../utils/index.js';
const modifierValues = ['always', 'ignorePackages', 'never'];
const modifierSchema = {
type: 'string',
enum: [...modifierValues],
};
const modifierByFileExtensionSchema = {
type: 'object',
patternProperties: { '.*': modifierSchema },
};
const properties = {
type: 'object',
properties: {
pattern: modifierByFileExtensionSchema,
ignorePackages: {
type: 'boolean',
},
checkTypeImports: {
type: 'boolean',
},
pathGroupOverrides: {
type: 'array',
items: {
type: 'object',
properties: {
pattern: { type: 'string' },
patternOptions: { type: 'object' },
action: {
type: 'string',
enum: ['enforce', 'ignore'],
},
},
additionalProperties: false,
required: ['pattern', 'action'],
},
},
fix: {
type: 'boolean',
},
},
};
function buildProperties(context) {
const result = {
defaultConfig: 'never',
pattern: {},
ignorePackages: false,
checkTypeImports: false,
pathGroupOverrides: [],
fix: false,
};
for (const obj of context.options) {
if (typeof obj === 'string') {
result.defaultConfig = obj;
continue;
}
if (typeof obj !== 'object' || !obj) {
continue;
}
if (obj.fix != null) {
result.fix = Boolean(obj.fix);
}
if ((!('pattern' in obj) || obj.pattern == null) &&
obj.ignorePackages == null &&
obj.checkTypeImports == null) {
Object.assign(result.pattern, obj);
continue;
}
if ('pattern' in obj && obj.pattern != null) {
Object.assign(result.pattern, obj.pattern);
}
if (typeof obj.ignorePackages === 'boolean') {
result.ignorePackages = obj.ignorePackages;
}
if (typeof obj.checkTypeImports === 'boolean') {
result.checkTypeImports = obj.checkTypeImports;
}
if (Array.isArray(obj.pathGroupOverrides)) {
result.pathGroupOverrides = obj.pathGroupOverrides;
}
}
if (result.defaultConfig === 'ignorePackages') {
result.defaultConfig = 'always';
result.ignorePackages = true;
}
return result;
}
function isExternalRootModule(file) {
if (file === '.' || file === '..') {
return false;
}
const slashCount = file.split('/').length - 1;
return slashCount === 0 || (isScoped(file) && slashCount <= 1);
}
function computeOverrideAction(pathGroupOverrides, path) {
for (const { pattern, patternOptions, action } of pathGroupOverrides) {
if (minimatch(path, pattern, patternOptions || { nocomment: true })) {
return action;
}
}
}
function replaceImportPath(source, importPath) {
return source.replace(/^(['"])(.+)\1$/, (_, quote) => `${quote}${importPath}${quote}`);
}
export default createRule({
name: 'extensions',
meta: {
type: 'suggestion',
docs: {
category: 'Style guide',
description: 'Ensure consistent use of file extension within the import path.',
},
fixable: 'code',
hasSuggestions: true,
schema: {
anyOf: [
{
type: 'array',
items: [modifierSchema],
additionalItems: false,
},
{
type: 'array',
items: [modifierSchema, properties],
additionalItems: false,
},
{
type: 'array',
items: [properties],
additionalItems: false,
},
{
type: 'array',
items: [modifierSchema, modifierByFileExtensionSchema],
additionalItems: false,
},
{
type: 'array',
items: [modifierByFileExtensionSchema],
additionalItems: false,
},
],
},
messages: {
missing: 'Missing file extension for "{{importPath}}"',
missingKnown: 'Missing file extension "{{extension}}" for "{{importPath}}"',
unexpected: 'Unexpected use of file extension "{{extension}}" for "{{importPath}}"',
addMissing: 'Add "{{extension}}" file extension from "{{importPath}}" into "{{fixedImportPath}}"',
removeUnexpected: 'Remove unexpected "{{extension}}" file extension from "{{importPath}}" into "{{fixedImportPath}}"',
},
},
defaultOptions: [],
create(context) {
const props = buildProperties(context);
function getModifier(extension) {
return props.pattern[extension] || props.defaultConfig;
}
function isUseOfExtensionRequired(extension, isPackage) {
return (getModifier(extension) === 'always' &&
(!props.ignorePackages || !isPackage));
}
function isUseOfExtensionForbidden(extension) {
return getModifier(extension) === 'never';
}
function isResolvableWithoutExtension(file) {
const extension = path.extname(file);
const fileWithoutExtension = file.slice(0, -extension.length);
const resolvedFileWithoutExtension = resolve(fileWithoutExtension, context);
return resolvedFileWithoutExtension === resolve(file, context);
}
return moduleVisitor((source, node) => {
if (!source || !source.value) {
return;
}
const importPathWithQueryString = source.value;
const overrideAction = computeOverrideAction(props.pathGroupOverrides || [], importPathWithQueryString);
if (overrideAction === 'ignore') {
return;
}
if (!overrideAction &&
isBuiltIn(importPathWithQueryString, context.settings)) {
return;
}
const { pathname: importPath, query, hash, } = parsePath(importPathWithQueryString);
if (!overrideAction && isExternalRootModule(importPath)) {
return;
}
const resolvedPath = resolve(importPath, context);
const extension = path.extname(resolvedPath || importPath).slice(1);
const isPackage = isExternalModule(importPath, resolve(importPath, context), context) || isScoped(importPath);
if (!extension || !importPath.endsWith(`.${extension}`)) {
if (!props.checkTypeImports &&
(('importKind' in node && node.importKind === 'type') ||
('exportKind' in node && node.exportKind === 'type'))) {
return;
}
const extensionRequired = isUseOfExtensionRequired(extension, !overrideAction && isPackage);
const extensionForbidden = isUseOfExtensionForbidden(extension);
if (extensionRequired && !extensionForbidden) {
const fixedImportPath = stringifyPath({
pathname: `${/([\\/]|[\\/]?\.?\.)$/.test(importPath)
? `${importPath.endsWith('/')
? importPath.slice(0, -1)
: importPath}/index.${extension}`
: `${importPath}.${extension}`}`,
query,
hash,
});
const fixOrSuggest = {
fix(fixer) {
return fixer.replaceText(source, replaceImportPath(source.raw, fixedImportPath));
},
};
context.report({
node: source,
messageId: extension ? 'missingKnown' : 'missing',
data: {
extension,
importPath: importPathWithQueryString,
},
...(extension &&
(props.fix
? fixOrSuggest
: {
suggest: [
{
...fixOrSuggest,
messageId: 'addMissing',
data: {
extension,
importPath: importPathWithQueryString,
fixedImportPath,
},
},
],
})),
});
}
}
else if (extension &&
isUseOfExtensionForbidden(extension) &&
isResolvableWithoutExtension(importPath)) {
const fixedPathname = importPath.slice(0, -(extension.length + 1));
const isIndex = fixedPathname.endsWith('/index');
const fixedImportPath = stringifyPath({
pathname: isIndex ? fixedPathname.slice(0, -6) : fixedPathname,
query,
hash,
});
const fixOrSuggest = {
fix(fixer) {
return fixer.replaceText(source, replaceImportPath(source.raw, fixedImportPath));
},
};
const commonSuggestion = {
...fixOrSuggest,
messageId: 'removeUnexpected',
data: {
extension,
importPath: importPathWithQueryString,
fixedImportPath,
},
};
context.report({
node: source,
messageId: 'unexpected',
data: {
extension,
importPath: importPathWithQueryString,
},
...(props.fix
? fixOrSuggest
: {
suggest: [
commonSuggestion,
isIndex && {
...commonSuggestion,
fix(fixer) {
return fixer.replaceText(source, replaceImportPath(source.raw, stringifyPath({
pathname: fixedPathname,
query,
hash,
})));
},
data: {
...commonSuggestion.data,
fixedImportPath: stringifyPath({
pathname: fixedPathname,
query,
hash,
}),
},
},
].filter(Boolean),
}),
});
}
}, { commonjs: true });
},
});
//# sourceMappingURL=extensions.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,5 @@
import type { TSESLint } from '@typescript-eslint/utils';
export type Options = 'absolute-first' | 'disable-absolute-first';
export type MessageId = 'absolute' | 'order';
declare const _default: TSESLint.RuleModule<MessageId, [(Options | undefined)?], import("../utils/create-rule.ts").ImportXPluginDocs, TSESLint.RuleListener>;
export default _default;

153
node_modules/eslint-plugin-import-x/lib/rules/first.js generated vendored Normal file
View File

@@ -0,0 +1,153 @@
import { createRule } from '../utils/index.js';
function getImportValue(node) {
return node.type === 'ImportDeclaration'
? node.source.value
: 'moduleReference' in node &&
'expression' in node.moduleReference &&
'value' in node.moduleReference.expression &&
node.moduleReference.expression.value;
}
function isPossibleDirective(node) {
return (node.type === 'ExpressionStatement' &&
node.expression.type === 'Literal' &&
typeof node.expression.value === 'string');
}
export default createRule({
name: 'first',
meta: {
type: 'suggestion',
docs: {
category: 'Style guide',
description: 'Ensure all imports appear before other statements.',
},
fixable: 'code',
schema: [
{
type: 'string',
enum: ['absolute-first', 'disable-absolute-first'],
},
],
messages: {
absolute: 'Absolute imports should come before relative imports.',
order: 'Import in body of module; reorder to top.',
},
},
defaultOptions: [],
create(context) {
return {
Program(n) {
const body = n.body;
if (!body?.length) {
return;
}
const absoluteFirst = context.options[0] === 'absolute-first';
const { sourceCode } = context;
const originSourceCode = sourceCode.getText();
let nonImportCount = 0;
let anyExpressions = false;
let anyRelative = false;
let lastLegalImp = null;
const errorInfos = [];
let shouldSort = true;
let lastSortNodesIndex = 0;
for (const [index, node] of body.entries()) {
if (!anyExpressions && isPossibleDirective(node)) {
continue;
}
anyExpressions = true;
if (node.type === 'ImportDeclaration' ||
node.type === 'TSImportEqualsDeclaration') {
if (absoluteFirst) {
const importValue = getImportValue(node);
if (typeof importValue === 'string' && /^\./.test(importValue)) {
anyRelative = true;
}
else if (anyRelative) {
context.report({
node: node.type === 'ImportDeclaration'
? node.source
: node.moduleReference,
messageId: 'absolute',
});
}
}
if (nonImportCount > 0) {
for (const variable of sourceCode.getDeclaredVariables(node)) {
if (!shouldSort) {
break;
}
for (const reference of variable.references) {
if (reference.identifier.range[0] < node.range[1]) {
shouldSort = false;
break;
}
}
}
if (shouldSort) {
lastSortNodesIndex = errorInfos.length;
}
errorInfos.push({
node,
range: [body[index - 1].range[1], node.range[1]],
});
}
else {
lastLegalImp = node;
}
}
else {
nonImportCount++;
}
}
if (errorInfos.length === 0) {
return;
}
for (const [index, { node }] of errorInfos.entries()) {
let fix;
if (index < lastSortNodesIndex) {
fix = (fixer) => fixer.insertTextAfter(node, '');
}
else if (index === lastSortNodesIndex) {
const sortNodes = errorInfos.slice(0, lastSortNodesIndex + 1);
fix = (fixer) => {
const removeFixers = sortNodes.map(({ range }) => fixer.removeRange(range));
const range = [
0,
removeFixers[removeFixers.length - 1].range[1],
];
let insertSourceCode = sortNodes
.map(({ range }) => {
const nodeSourceCode = originSourceCode.slice(...range);
if (/\S/.test(nodeSourceCode[0])) {
return `\n${nodeSourceCode}`;
}
return nodeSourceCode;
})
.join('');
let replaceSourceCode = '';
if (!lastLegalImp) {
insertSourceCode =
insertSourceCode.trim() + insertSourceCode.match(/^(\s+)/)[0];
}
const insertFixer = lastLegalImp
? fixer.insertTextAfter(lastLegalImp, insertSourceCode)
: fixer.insertTextBefore(body[0], insertSourceCode);
const fixers = [insertFixer, ...removeFixers];
for (const [i, computedFixer] of fixers.entries()) {
replaceSourceCode +=
originSourceCode.slice(fixers[i - 1] ? fixers[i - 1].range[1] : 0, computedFixer.range[0]) + computedFixer.text;
}
return fixer.replaceTextRange(range, replaceSourceCode);
};
}
context.report({
node,
messageId: 'order',
fix,
});
}
},
};
},
});
//# sourceMappingURL=first.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"first.js","sourceRoot":"","sources":["../../src/rules/first.ts"],"names":[],"mappings":"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"}

View File

@@ -0,0 +1,4 @@
export type Literal = string | number | bigint | boolean | RegExp | null;
export type MessageId = 'ExportNamedDeclaration' | 'AssignmentExpression';
declare const _default: import("@typescript-eslint/utils/ts-eslint").RuleModule<MessageId, [], import("../utils/create-rule.ts").ImportXPluginDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
export default _default;

View File

@@ -0,0 +1,123 @@
import { createRule } from '../utils/index.js';
function accessorChain(node) {
const chain = [];
let exp = node;
do {
if ('name' in exp.property) {
chain.unshift(exp.property.name);
}
else if ('value' in exp.property) {
chain.unshift(exp.property.value);
}
if (exp.object.type === 'Identifier') {
chain.unshift(exp.object.name);
break;
}
exp = exp.object;
} while (exp.type === 'MemberExpression');
return chain;
}
export default createRule({
name: 'group-exports',
meta: {
type: 'suggestion',
docs: {
category: 'Style guide',
description: 'Prefer named exports to be grouped together in a single export declaration.',
},
schema: [],
messages: {
ExportNamedDeclaration: 'Multiple named export declarations; consolidate all named exports into a single export declaration',
AssignmentExpression: 'Multiple CommonJS exports; consolidate all exports into a single assignment to `module.exports`',
},
},
defaultOptions: [],
create(context) {
const nodes = {
modules: {
set: new Set(),
sources: {},
},
types: {
set: new Set(),
sources: {},
},
commonjs: {
set: new Set(),
},
};
return {
ExportNamedDeclaration(node) {
const target = node.exportKind === 'type' ? nodes.types : nodes.modules;
if (!node.source) {
target.set.add(node);
}
else if (Array.isArray(target.sources[node.source.value])) {
target.sources[node.source.value].push(node);
}
else {
target.sources[node.source.value] = [node];
}
},
AssignmentExpression(node) {
if (node.left.type !== 'MemberExpression') {
return;
}
const chain = accessorChain(node.left);
if (chain[0] === 'module' &&
chain[1] === 'exports' &&
chain.length <= 3) {
nodes.commonjs.set.add(node);
return;
}
if (chain[0] === 'exports' && chain.length === 2) {
nodes.commonjs.set.add(node);
return;
}
},
'Program:exit'() {
if (nodes.modules.set.size > 1) {
for (const node of nodes.modules.set) {
context.report({
node,
messageId: node.type,
});
}
}
for (const node of Object.values(nodes.modules.sources)
.filter(nodesWithSource => Array.isArray(nodesWithSource) && nodesWithSource.length > 1)
.flat()) {
context.report({
node,
messageId: node.type,
});
}
if (nodes.types.set.size > 1) {
for (const node of nodes.types.set) {
context.report({
node,
messageId: node.type,
});
}
}
for (const node of Object.values(nodes.types.sources)
.filter(nodesWithSource => Array.isArray(nodesWithSource) && nodesWithSource.length > 1)
.flat()) {
context.report({
node,
messageId: node.type,
});
}
if (nodes.commonjs.set.size > 1) {
for (const node of nodes.commonjs.set) {
context.report({
node,
messageId: node.type,
});
}
}
},
};
},
});
//# sourceMappingURL=group-exports.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"group-exports.js","sourceRoot":"","sources":["../../src/rules/group-exports.ts"],"names":[],"mappings":"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"}

View File

@@ -0,0 +1,2 @@
declare const _default: import("@typescript-eslint/utils/ts-eslint").RuleModule<import("./first.js").MessageId, [(import("./first.js").Options | undefined)?], import("../utils/create-rule.ts").ImportXPluginDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
export default _default;

View File

@@ -0,0 +1,25 @@
import { createRule, docsUrl } from '../utils/index.js';
import first from './first.js';
export default createRule({
...first,
name: 'imports-first',
meta: {
...first.meta,
deprecated: {
message: 'Replaced by `import-x/first`.',
url: 'https://github.com/import-js/eslint-plugin-import/blob/main/CHANGELOG.md#changed-24',
deprecatedSince: '2.0.0',
replacedBy: [
{
message: 'Replaced by `import-x/first`.',
rule: { name: 'first', url: docsUrl('first') },
},
],
},
docs: {
category: 'Style guide',
description: 'Replaced by `import-x/first`.',
},
},
});
//# sourceMappingURL=imports-first.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"imports-first.js","sourceRoot":"","sources":["../../src/rules/imports-first.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAA;AAEvD,OAAO,KAAK,MAAM,YAAY,CAAA;AAE9B,eAAe,UAAU,CAAC;IACxB,GAAG,KAAK;IACR,IAAI,EAAE,eAAe;IACrB,IAAI,EAAE;QACJ,GAAG,KAAK,CAAC,IAAI;QACb,UAAU,EAAE;YACV,OAAO,EAAE,+BAA+B;YACxC,GAAG,EAAE,qFAAqF;YAC1F,eAAe,EAAE,OAAO;YACxB,UAAU,EAAE;gBACV;oBACE,OAAO,EAAE,+BAA+B;oBACxC,IAAI,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,CAAC,OAAO,CAAC,EAAE;iBAC/C;aACF;SACF;QACD,IAAI,EAAE;YACJ,QAAQ,EAAE,aAAa;YACvB,WAAW,EAAE,+BAA+B;SAC7C;KACF;CACF,CAAC,CAAA"}

View File

@@ -0,0 +1,7 @@
export interface Options {
ignoreTypeImports?: boolean;
max?: number;
}
export type MessageId = 'max';
declare const _default: import("@typescript-eslint/utils/ts-eslint").RuleModule<"max", [(Options | undefined)?], import("../utils/create-rule.ts").ImportXPluginDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
export default _default;

View File

@@ -0,0 +1,53 @@
import { createRule, moduleVisitor } from '../utils/index.js';
export default createRule({
name: 'max-dependencies',
meta: {
type: 'suggestion',
docs: {
category: 'Style guide',
description: 'Enforce the maximum number of dependencies a module can have.',
},
schema: [
{
type: 'object',
properties: {
max: { type: 'number' },
ignoreTypeImports: { type: 'boolean' },
},
additionalProperties: false,
},
],
messages: {
max: 'Maximum number of dependencies ({{max}}) exceeded.',
},
},
defaultOptions: [],
create(context) {
const { ignoreTypeImports } = context.options[0] || {};
const dependencies = new Set();
let lastNode;
return {
'Program:exit'() {
const { max = 10 } = context.options[0] || {};
if (dependencies.size <= max) {
return;
}
context.report({
node: lastNode,
messageId: 'max',
data: {
max,
},
});
},
...moduleVisitor((source, node) => {
if (('importKind' in node && node.importKind !== 'type') ||
!ignoreTypeImports) {
dependencies.add(source.value);
}
lastNode = source;
}, { commonjs: true }),
};
},
});
//# sourceMappingURL=max-dependencies.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"max-dependencies.js","sourceRoot":"","sources":["../../src/rules/max-dependencies.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AAS7D,eAAe,UAAU,CAAwB;IAC/C,IAAI,EAAE,kBAAkB;IACxB,IAAI,EAAE;QACJ,IAAI,EAAE,YAAY;QAClB,IAAI,EAAE;YACJ,QAAQ,EAAE,aAAa;YACvB,WAAW,EACT,+DAA+D;SAClE;QACD,MAAM,EAAE;YACN;gBACE,IAAI,EAAE,QAAQ;gBACd,UAAU,EAAE;oBACV,GAAG,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;oBACvB,iBAAiB,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE;iBACvC;gBACD,oBAAoB,EAAE,KAAK;aAC5B;SACF;QACD,QAAQ,EAAE;YACR,GAAG,EAAE,oDAAoD;SAC1D;KACF;IACD,cAAc,EAAE,EAAE;IAClB,MAAM,CAAC,OAAO;QACZ,MAAM,EAAE,iBAAiB,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,EAAE,CAAA;QAEtD,MAAM,YAAY,GAAG,IAAI,GAAG,EAAU,CAAA;QAEtC,IAAI,QAAgC,CAAA;QAEpC,OAAO;YACL,cAAc;gBACZ,MAAM,EAAE,GAAG,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,EAAE,CAAA;gBAE7C,IAAI,YAAY,CAAC,IAAI,IAAI,GAAG,EAAE,CAAC;oBAC7B,OAAM;gBACR,CAAC;gBAED,OAAO,CAAC,MAAM,CAAC;oBACb,IAAI,EAAE,QAAQ;oBACd,SAAS,EAAE,KAAK;oBAChB,IAAI,EAAE;wBACJ,GAAG;qBACJ;iBACF,CAAC,CAAA;YACJ,CAAC;YACD,GAAG,aAAa,CACd,CAAC,MAAM,EAAE,IAAI,EAAE,EAAE;gBACf,IACE,CAAC,YAAY,IAAI,IAAI,IAAI,IAAI,CAAC,UAAU,KAAK,MAAM,CAAC;oBACpD,CAAC,iBAAiB,EAClB,CAAC;oBACD,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;gBAChC,CAAC;gBACD,QAAQ,GAAG,MAAM,CAAA;YACnB,CAAC,EACD,EAAE,QAAQ,EAAE,IAAI,EAAE,CACnB;SACF,CAAA;IACH,CAAC;CACF,CAAC,CAAA"}

View File

@@ -0,0 +1,4 @@
import type { ModuleOptions } from '../utils/index.js';
export type MessageId = 'notFound' | 'notFoundDeep';
declare const _default: import("@typescript-eslint/utils/ts-eslint").RuleModule<MessageId, [(ModuleOptions | undefined)?], import("../utils/create-rule.ts").ImportXPluginDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
export default _default;

153
node_modules/eslint-plugin-import-x/lib/rules/named.js generated vendored Normal file
View File

@@ -0,0 +1,153 @@
import path from 'node:path';
import { ExportMap, createRule } from '../utils/index.js';
export default createRule({
name: 'named',
meta: {
type: 'problem',
docs: {
category: 'Static analysis',
description: 'Ensure named imports correspond to a named export in the remote file.',
},
schema: [
{
type: 'object',
properties: {
commonjs: {
type: 'boolean',
},
},
additionalProperties: false,
},
],
messages: {
notFound: "{{name}} not found in '{{path}}'",
notFoundDeep: '{{name}} not found via {{deepPath}}',
},
},
defaultOptions: [],
create(context) {
const options = context.options[0] || {};
function checkSpecifiers(key, type, node) {
if (node.source == null ||
('importKind' in node &&
(node.importKind === 'type' ||
node.importKind === 'typeof')) ||
('exportKind' in node && node.exportKind === 'type')) {
return;
}
if (!node.specifiers.some(im => im.type === type)) {
return;
}
const imports = ExportMap.get(node.source.value, context);
if (imports == null || imports.parseGoal === 'ambiguous') {
return;
}
if (imports.errors.length > 0) {
imports.reportErrors(context, node);
return;
}
for (const im of node.specifiers) {
if (im.type !== type ||
('importKind' in im &&
(im.importKind === 'type' ||
im.importKind === 'typeof'))) {
continue;
}
const imNode = im[key];
const name = imNode.name ||
imNode.value;
const deepLookup = imports.hasDeep(name);
if (!deepLookup.found) {
if (deepLookup.path.length > 1) {
const deepPath = deepLookup.path
.map(i => path.relative(path.dirname(context.physicalFilename), i.path))
.join(' -> ');
context.report({
node: imNode,
messageId: 'notFoundDeep',
data: {
name,
deepPath,
},
});
}
else {
context.report({
node: imNode,
messageId: 'notFound',
data: {
name,
path: node.source.value,
},
});
}
}
}
}
return {
ImportDeclaration: checkSpecifiers.bind(null, 'imported', 'ImportSpecifier'),
ExportNamedDeclaration: checkSpecifiers.bind(null, 'local', 'ExportSpecifier'),
VariableDeclarator(node) {
if (!options.commonjs ||
node.type !== 'VariableDeclarator' ||
!node.id ||
node.id.type !== 'ObjectPattern' ||
node.id.properties.length === 0 ||
!node.init ||
node.init.type !== 'CallExpression') {
return;
}
const call = node.init;
const source = call.arguments[0];
const variableImports = node.id.properties;
const variableExports = ExportMap.get(source.value, context);
if (call.callee.type !== 'Identifier' ||
call.callee.name !== 'require' ||
call.arguments.length !== 1 ||
source.type !== 'Literal' ||
variableExports == null ||
variableExports.parseGoal === 'ambiguous') {
return;
}
if (variableExports.errors.length > 0) {
variableExports.reportErrors(context, node);
return;
}
for (const im of variableImports) {
if (im.type !== 'Property' ||
!im.key ||
im.key.type !== 'Identifier') {
continue;
}
const deepLookup = variableExports.hasDeep(im.key.name);
if (!deepLookup.found) {
if (deepLookup.path.length > 1) {
const deepPath = deepLookup.path
.map(i => path.relative(path.dirname(context.filename), i.path))
.join(' -> ');
context.report({
node: im.key,
messageId: 'notFoundDeep',
data: {
name: im.key.name,
deepPath,
},
});
}
else {
context.report({
node: im.key,
messageId: 'notFound',
data: {
name: im.key.name,
path: source.value,
},
});
}
}
}
},
};
},
});
//# sourceMappingURL=named.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"named.js","sourceRoot":"","sources":["../../src/rules/named.ts"],"names":[],"mappings":"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"}

View File

@@ -0,0 +1,7 @@
import type { TSESLint } from '@typescript-eslint/utils';
export type MessageId = 'noNamesFound' | 'computedReference' | 'namespaceMember' | 'topLevelNames' | 'notFoundInNamespace' | 'notFoundInNamespaceDeep';
export interface Options {
allowComputed?: boolean;
}
declare const _default: TSESLint.RuleModule<MessageId, [Options], import("../utils/create-rule.ts").ImportXPluginDocs, TSESLint.RuleListener>;
export default _default;

View File

@@ -0,0 +1,238 @@
import { importDeclaration, ExportMap, createRule, declaredScope, getValue, } from '../utils/index.js';
function processBodyStatement(context, namespaces, declaration) {
if (declaration.type !== 'ImportDeclaration') {
return;
}
if (declaration.specifiers.length === 0) {
return;
}
const imports = ExportMap.get(declaration.source.value, context);
if (imports == null) {
return;
}
if (imports.errors.length > 0) {
imports.reportErrors(context, declaration);
return;
}
for (const specifier of declaration.specifiers) {
switch (specifier.type) {
case 'ImportNamespaceSpecifier': {
if (imports.size === 0) {
context.report({
node: specifier,
messageId: 'noNamesFound',
data: {
module: declaration.source.value,
},
});
}
namespaces.set(specifier.local.name, imports);
break;
}
case 'ImportDefaultSpecifier':
case 'ImportSpecifier': {
const meta = imports.get('imported' in specifier
? getValue(specifier.imported)
:
'default');
if (!meta || !meta.namespace) {
break;
}
namespaces.set(specifier.local.name, meta.namespace);
break;
}
default:
}
}
}
function makeMessage(last, namepath, node = last) {
const messageId = namepath.length > 1 ? 'notFoundInNamespaceDeep' : 'notFoundInNamespace';
return {
node,
messageId,
data: {
name: last.name,
namepath: namepath.join('.'),
},
};
}
export default createRule({
name: 'namespace',
meta: {
type: 'problem',
docs: {
category: 'Static analysis',
description: 'Ensure imported namespaces contain dereferenced properties as they are dereferenced.',
},
schema: [
{
type: 'object',
properties: {
allowComputed: {
description: 'If `false`, will report computed (and thus, un-lintable) references to namespace members.',
type: 'boolean',
default: false,
},
},
additionalProperties: false,
},
],
messages: {
noNamesFound: "No exported names found in module '{{module}}'.",
computedReference: "Unable to validate computed reference to imported namespace '{{namespace}}'.",
namespaceMember: "Assignment to member of namespace '{{namespace}}'.",
topLevelNames: 'Only destructure top-level names.',
notFoundInNamespace: "'{{name}}' not found in imported namespace '{{namepath}}'.",
notFoundInNamespaceDeep: "'{{name}}' not found in deeply imported namespace '{{namepath}}'.",
},
},
defaultOptions: [
{
allowComputed: false,
},
],
create(context) {
const { allowComputed } = context.options[0] || {};
const namespaces = new Map();
return {
Program({ body }) {
for (const x of body) {
processBodyStatement(context, namespaces, x);
}
},
ExportNamespaceSpecifier(namespace) {
const declaration = importDeclaration(context, namespace);
const imports = ExportMap.get(declaration.source.value, context);
if (imports == null) {
return null;
}
if (imports.errors.length > 0) {
imports.reportErrors(context, declaration);
return;
}
if (imports.size === 0) {
context.report({
node: namespace,
messageId: 'noNamesFound',
data: {
module: declaration.source.value,
},
});
}
},
MemberExpression(dereference) {
if (dereference.object.type !== 'Identifier') {
return;
}
if (!namespaces.has(dereference.object.name)) {
return;
}
if (declaredScope(context, dereference, dereference.object.name) !==
'module') {
return;
}
const parent = dereference.parent;
if (parent?.type === 'AssignmentExpression' &&
parent.left === dereference) {
context.report({
node: parent,
messageId: 'namespaceMember',
data: {
namespace: dereference.object.name,
},
});
}
let namespace = namespaces.get(dereference.object.name);
const namepath = [dereference.object.name];
let deref = dereference;
while (namespace instanceof ExportMap &&
deref?.type === 'MemberExpression') {
if (deref.computed) {
if (!allowComputed) {
context.report({
node: deref.property,
messageId: 'computedReference',
data: {
namespace: 'name' in deref.object && deref.object.name,
},
});
}
return;
}
if (!namespace.has(deref.property.name)) {
context.report(makeMessage(deref.property, namepath));
break;
}
const exported = namespace.get(deref.property.name);
if (exported == null) {
return;
}
namepath.push(deref.property.name);
namespace = exported.namespace;
deref = deref.parent;
}
},
VariableDeclarator(node) {
const { id, init } = node;
if (init == null) {
return;
}
if (init.type !== 'Identifier') {
return;
}
if (!namespaces.has(init.name)) {
return;
}
if (declaredScope(context, node, init.name) !== 'module') {
return;
}
const initName = init.name;
function testKey(pattern, namespace, path = [initName]) {
if (!(namespace instanceof ExportMap)) {
return;
}
if (pattern.type !== 'ObjectPattern') {
return;
}
for (const property of pattern.properties) {
if (property.type === 'ExperimentalRestProperty' ||
property.type === 'RestElement' ||
!property.key) {
continue;
}
if (property.key.type !== 'Identifier') {
context.report({
node: property,
messageId: 'topLevelNames',
});
continue;
}
if (!namespace.has(property.key.name)) {
context.report(makeMessage(property.key, path, property));
continue;
}
path.push(property.key.name);
const dependencyExportMap = namespace.get(property.key.name);
if (dependencyExportMap != null) {
testKey(property.value, dependencyExportMap.namespace, path);
}
path.pop();
}
}
testKey(id, namespaces.get(init.name));
},
JSXMemberExpression({ object, property }) {
if (!('name' in object) ||
typeof object.name !== 'string' ||
!namespaces.has(object.name)) {
return;
}
const namespace = namespaces.get(object.name);
if (!namespace.has(property.name)) {
context.report(makeMessage(property, [object.name]));
}
},
};
},
});
//# sourceMappingURL=namespace.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,9 @@
import type { TSESLint } from '@typescript-eslint/utils';
export interface Options {
count?: number;
exactCount?: boolean;
considerComments?: boolean;
}
export type MessageId = 'newline';
declare const _default: TSESLint.RuleModule<"newline", [(Options | undefined)?], import("../utils/create-rule.ts").ImportXPluginDocs, TSESLint.RuleListener>;
export default _default;

View File

@@ -0,0 +1,224 @@
import debug from 'debug';
import { isStaticRequire, createRule } from '../utils/index.js';
const log = debug('eslint-plugin-import-x:rules:newline-after-import');
function containsNodeOrEqual(outerNode, innerNode) {
return (outerNode.range[0] <= innerNode.range[0] &&
outerNode.range[1] >= innerNode.range[1]);
}
function getScopeBody(scope) {
if (scope.block.type === 'SwitchStatement') {
log('SwitchStatement scopes not supported');
return [];
}
const body = 'body' in scope.block ? scope.block.body : null;
if (body && 'type' in body && body.type === 'BlockStatement') {
return body.body;
}
return Array.isArray(body) ? body : [];
}
function findNodeIndexInScopeBody(body, nodeToFind) {
return body.findIndex(node => containsNodeOrEqual(node, nodeToFind));
}
function getLineDifference(node, nextNode) {
return nextNode.loc.start.line - node.loc.end.line;
}
function isClassWithDecorator(node) {
return node.type === 'ClassDeclaration' && !!node.decorators?.length;
}
function isExportDefaultClass(node) {
return (node.type === 'ExportDefaultDeclaration' &&
node.declaration.type === 'ClassDeclaration');
}
function isExportNameClass(node) {
return (node.type === 'ExportNamedDeclaration' &&
node.declaration?.type === 'ClassDeclaration');
}
export default createRule({
name: 'newline-after-import',
meta: {
type: 'layout',
docs: {
category: 'Style guide',
description: 'Enforce a newline after import statements.',
},
fixable: 'whitespace',
schema: [
{
type: 'object',
properties: {
count: {
type: 'integer',
minimum: 1,
},
exactCount: { type: 'boolean' },
considerComments: { type: 'boolean' },
},
additionalProperties: false,
},
],
messages: {
newline: 'Expected {{count}} empty line{{lineSuffix}} after {{type}} statement not followed by another {{type}}.',
},
},
defaultOptions: [],
create(context) {
let level = 0;
const requireCalls = [];
const options = {
count: 1,
exactCount: false,
considerComments: false,
...context.options[0],
};
function checkForNewLine(node, nextNode, type) {
if (isExportDefaultClass(nextNode) || isExportNameClass(nextNode)) {
const classNode = nextNode.declaration;
if (isClassWithDecorator(classNode)) {
nextNode = classNode.decorators[0];
}
}
else if (isClassWithDecorator(nextNode)) {
nextNode = nextNode.decorators[0];
}
const lineDifference = getLineDifference(node, nextNode);
const EXPECTED_LINE_DIFFERENCE = options.count + 1;
if (lineDifference < EXPECTED_LINE_DIFFERENCE ||
(options.exactCount && lineDifference !== EXPECTED_LINE_DIFFERENCE)) {
let column = node.loc.start.column;
if (node.loc.start.line !== node.loc.end.line) {
column = 0;
}
context.report({
loc: {
line: node.loc.end.line,
column,
},
messageId: 'newline',
data: {
count: options.count,
lineSuffix: options.count > 1 ? 's' : '',
type,
},
fix: options.exactCount && EXPECTED_LINE_DIFFERENCE < lineDifference
? undefined
: fixer => fixer.insertTextAfter(node, '\n'.repeat(EXPECTED_LINE_DIFFERENCE - lineDifference)),
});
}
}
function commentAfterImport(node, nextComment, type) {
const lineDifference = getLineDifference(node, nextComment);
const EXPECTED_LINE_DIFFERENCE = options.count + 1;
if (lineDifference < EXPECTED_LINE_DIFFERENCE) {
let column = node.loc.start.column;
if (node.loc.start.line !== node.loc.end.line) {
column = 0;
}
context.report({
loc: {
line: node.loc.end.line,
column,
},
messageId: 'newline',
data: {
count: options.count,
lineSuffix: options.count > 1 ? 's' : '',
type,
},
fix: options.exactCount && EXPECTED_LINE_DIFFERENCE < lineDifference
? undefined
: fixer => fixer.insertTextAfter(node, '\n'.repeat(EXPECTED_LINE_DIFFERENCE - lineDifference)),
});
}
}
function incrementLevel() {
level++;
}
function decrementLevel() {
level--;
}
function checkImport(node) {
const { parent } = node;
if (!parent || !('body' in parent) || !parent.body) {
return;
}
const root = parent;
const nodePosition = root.body.indexOf(node);
const nextNode = root.body[nodePosition + 1];
const endLine = node.loc.end.line;
let nextComment;
if (root.comments !== undefined && options.considerComments) {
nextComment = root.comments.find(o => o.loc.start.line >= endLine &&
o.loc.start.line <= endLine + options.count + 1);
}
if (node.type === 'TSImportEqualsDeclaration' &&
node.isExport) {
return;
}
if (nextComment) {
commentAfterImport(node, nextComment, 'import');
}
else if (nextNode &&
nextNode.type !== 'ImportDeclaration' &&
(nextNode.type !== 'TSImportEqualsDeclaration' ||
nextNode.isExport)) {
checkForNewLine(node, nextNode, 'import');
}
}
return {
ImportDeclaration: checkImport,
TSImportEqualsDeclaration: checkImport,
CallExpression(node) {
if (isStaticRequire(node) && level === 0) {
requireCalls.push(node);
}
},
'Program:exit'(node) {
log('exit processing for', context.physicalFilename);
const scopeBody = getScopeBody(context.sourceCode.getScope(node));
log('got scope:', scopeBody);
for (const [index, node] of requireCalls.entries()) {
const nodePosition = findNodeIndexInScopeBody(scopeBody, node);
log('node position in scope:', nodePosition);
const statementWithRequireCall = scopeBody[nodePosition];
const nextStatement = scopeBody[nodePosition + 1];
const nextRequireCall = requireCalls[index + 1];
if (nextRequireCall &&
containsNodeOrEqual(statementWithRequireCall, nextRequireCall)) {
continue;
}
if (nextStatement &&
(!nextRequireCall ||
!containsNodeOrEqual(nextStatement, nextRequireCall))) {
let nextComment;
if ('comments' in statementWithRequireCall.parent &&
statementWithRequireCall.parent.comments !== undefined &&
options.considerComments) {
const endLine = node.loc.end.line;
nextComment = statementWithRequireCall.parent.comments.find(o => o.loc.start.line >= endLine &&
o.loc.start.line <= endLine + options.count + 1);
}
if (nextComment && nextComment !== undefined) {
commentAfterImport(statementWithRequireCall, nextComment, 'require');
}
else {
checkForNewLine(statementWithRequireCall, nextStatement, 'require');
}
}
}
},
FunctionDeclaration: incrementLevel,
FunctionExpression: incrementLevel,
ArrowFunctionExpression: incrementLevel,
BlockStatement: incrementLevel,
ObjectExpression: incrementLevel,
Decorator: incrementLevel,
'FunctionDeclaration:exit': decrementLevel,
'FunctionExpression:exit': decrementLevel,
'ArrowFunctionExpression:exit': decrementLevel,
'BlockStatement:exit': decrementLevel,
'ObjectExpression:exit': decrementLevel,
'Decorator:exit': decrementLevel,
};
},
});
//# sourceMappingURL=newline-after-import.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,4 @@
import type { ModuleOptions } from '../utils/index.js';
export type MessageId = 'absolute';
declare const _default: import("@typescript-eslint/utils/ts-eslint").RuleModule<"absolute", [(ModuleOptions | undefined)?], import("../utils/create-rule.ts").ImportXPluginDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
export default _default;

View File

@@ -0,0 +1,38 @@
import path from 'node:path';
import { isAbsolute, createRule, moduleVisitor, makeOptionsSchema, } from '../utils/index.js';
export default createRule({
name: 'no-absolute-path',
meta: {
type: 'suggestion',
docs: {
category: 'Static analysis',
description: 'Forbid import of modules using absolute paths.',
},
fixable: 'code',
schema: [makeOptionsSchema()],
messages: {
absolute: 'Do not import modules using an absolute path',
},
},
defaultOptions: [],
create(context) {
const options = { esmodule: true, commonjs: true, ...context.options[0] };
return moduleVisitor(source => {
if (!isAbsolute(source.value)) {
return;
}
context.report({
node: source,
messageId: 'absolute',
fix(fixer) {
let relativePath = path.posix.relative(path.dirname(context.physicalFilename), source.value);
if (!relativePath.startsWith('.')) {
relativePath = `./${relativePath}`;
}
return fixer.replaceText(source, JSON.stringify(relativePath));
},
});
}, options);
},
});
//# sourceMappingURL=no-absolute-path.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"no-absolute-path.js","sourceRoot":"","sources":["../../src/rules/no-absolute-path.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAA;AAE5B,OAAO,EACL,UAAU,EACV,UAAU,EACV,aAAa,EACb,iBAAiB,GAClB,MAAM,mBAAmB,CAAA;AAK1B,eAAe,UAAU,CAA8B;IACrD,IAAI,EAAE,kBAAkB;IACxB,IAAI,EAAE;QACJ,IAAI,EAAE,YAAY;QAClB,IAAI,EAAE;YACJ,QAAQ,EAAE,iBAAiB;YAC3B,WAAW,EAAE,gDAAgD;SAC9D;QACD,OAAO,EAAE,MAAM;QACf,MAAM,EAAE,CAAC,iBAAiB,EAAE,CAAC;QAC7B,QAAQ,EAAE;YACR,QAAQ,EAAE,8CAA8C;SACzD;KACF;IACD,cAAc,EAAE,EAAE;IAClB,MAAM,CAAC,OAAO;QACZ,MAAM,OAAO,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAA;QACzE,OAAO,aAAa,CAAC,MAAM,CAAC,EAAE;YAC5B,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC9B,OAAM;YACR,CAAC;YACD,OAAO,CAAC,MAAM,CAAC;gBACb,IAAI,EAAE,MAAM;gBACZ,SAAS,EAAE,UAAU;gBACrB,GAAG,CAAC,KAAK;oBAEP,IAAI,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CACpC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,gBAAgB,CAAC,EACtC,MAAM,CAAC,KAAK,CACb,CAAA;oBACD,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;wBAClC,YAAY,GAAG,KAAK,YAAY,EAAE,CAAA;oBACpC,CAAC;oBACD,OAAO,KAAK,CAAC,WAAW,CAAC,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,CAAA;gBAChE,CAAC;aACF,CAAC,CAAA;QACJ,CAAC,EAAE,OAAO,CAAC,CAAA;IACb,CAAC;CACF,CAAC,CAAA"}

View File

@@ -0,0 +1,3 @@
export type MessageId = 'amd';
declare const _default: import("@typescript-eslint/utils/ts-eslint").RuleModule<"amd", [], import("../utils/create-rule.ts").ImportXPluginDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
export default _default;

View File

@@ -0,0 +1,46 @@
import { createRule } from '../utils/index.js';
export default createRule({
name: 'no-amd',
meta: {
type: 'suggestion',
docs: {
category: 'Module systems',
description: 'Forbid AMD `require` and `define` calls.',
},
schema: [],
messages: {
amd: 'Expected imports instead of AMD {{type}}().',
},
},
defaultOptions: [],
create(context) {
return {
CallExpression(node) {
if (context.sourceCode.getScope(node).type !== 'module') {
return;
}
if (node.callee.type !== 'Identifier') {
return;
}
if (node.callee.name !== 'require' && node.callee.name !== 'define') {
return;
}
if (node.arguments.length !== 2) {
return;
}
const modules = node.arguments[0];
if (modules.type !== 'ArrayExpression') {
return;
}
context.report({
node,
messageId: 'amd',
data: {
type: node.callee.name,
},
});
},
};
},
});
//# sourceMappingURL=no-amd.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"no-amd.js","sourceRoot":"","sources":["../../src/rules/no-amd.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAI9C,eAAe,UAAU,CAAgB;IACvC,IAAI,EAAE,QAAQ;IACd,IAAI,EAAE;QACJ,IAAI,EAAE,YAAY;QAClB,IAAI,EAAE;YACJ,QAAQ,EAAE,gBAAgB;YAC1B,WAAW,EAAE,0CAA0C;SACxD;QACD,MAAM,EAAE,EAAE;QACV,QAAQ,EAAE;YACR,GAAG,EAAE,6CAA6C;SACnD;KACF;IACD,cAAc,EAAE,EAAE;IAClB,MAAM,CAAC,OAAO;QACZ,OAAO;YACL,cAAc,CAAC,IAAI;gBACjB,IAAI,OAAO,CAAC,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;oBACxD,OAAM;gBACR,CAAC;gBAED,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;oBACtC,OAAM;gBACR,CAAC;gBAED,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,SAAS,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;oBACpE,OAAM;gBACR,CAAC;gBAGD,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBAChC,OAAM;gBACR,CAAC;gBAED,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAA;gBAEjC,IAAI,OAAO,CAAC,IAAI,KAAK,iBAAiB,EAAE,CAAC;oBACvC,OAAM;gBACR,CAAC;gBAID,OAAO,CAAC,MAAM,CAAC;oBACb,IAAI;oBACJ,SAAS,EAAE,KAAK;oBAChB,IAAI,EAAE;wBACJ,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,IAAI;qBACvB;iBACF,CAAC,CAAA;YACJ,CAAC;SACF,CAAA;IACH,CAAC;CACF,CAAC,CAAA"}

View File

@@ -0,0 +1,13 @@
type MessageId = 'assign' | 'anonymous';
export interface Options {
allowArray?: boolean;
allowArrowFunction?: boolean;
allowCallExpression?: boolean;
allowAnonymousClass?: boolean;
allowAnonymousFunction?: boolean;
allowLiteral?: boolean;
allowObject?: boolean;
allowNew?: boolean;
}
declare const _default: import("@typescript-eslint/utils/ts-eslint").RuleModule<MessageId, [(Options | undefined)?], import("../utils/create-rule.ts").ImportXPluginDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
export default _default;

View File

@@ -0,0 +1,134 @@
import { createRule } from '../utils/index.js';
const { hasOwnProperty } = Object.prototype;
const hasOwn = (object, key) => hasOwnProperty.call(object, key);
const defs = {
ArrayExpression: {
option: 'allowArray',
description: 'If `false`, will report default export of an array',
messageId: 'assign',
data: {
type: 'array',
},
},
ArrowFunctionExpression: {
option: 'allowArrowFunction',
description: 'If `false`, will report default export of an arrow function',
messageId: 'assign',
data: {
type: 'arrow function',
},
},
CallExpression: {
option: 'allowCallExpression',
description: 'If `false`, will report default export of a function call',
messageId: 'assign',
data: {
type: 'call result',
},
default: true,
},
ClassDeclaration: {
option: 'allowAnonymousClass',
description: 'If `false`, will report default export of an anonymous class',
messageId: 'anonymous',
data: {
type: 'class',
},
forbid: (node) => !('id' in node.declaration) || !node.declaration.id,
},
FunctionDeclaration: {
option: 'allowAnonymousFunction',
description: 'If `false`, will report default export of an anonymous function',
messageId: 'anonymous',
data: {
type: 'function',
},
forbid: (node) => !('id' in node.declaration) || !node.declaration.id,
},
Literal: {
option: 'allowLiteral',
description: 'If `false`, will report default export of a literal',
messageId: 'assign',
data: {
type: 'literal',
},
},
ObjectExpression: {
option: 'allowObject',
description: 'If `false`, will report default export of an object expression',
messageId: 'assign',
data: {
type: 'object',
},
},
TemplateLiteral: {
option: 'allowLiteral',
description: 'If `false`, will report default export of a literal',
messageId: 'assign',
data: {
type: 'literal',
},
},
NewExpression: {
option: 'allowNew',
description: 'If `false`, will report default export of a class instantiation',
messageId: 'assign',
data: {
type: 'instance',
},
},
};
const schemaProperties = Object.fromEntries(Object.values(defs).map(def => [
def.option,
{
description: def.description,
type: 'boolean',
},
]));
const defaults = Object.fromEntries(Object.values(defs).map(def => [
def.option,
hasOwn(def, 'default') ? def.default : false,
]));
export default createRule({
name: 'no-anonymous-default-export',
meta: {
type: 'suggestion',
docs: {
category: 'Style guide',
description: 'Forbid anonymous values as default exports.',
},
schema: [
{
type: 'object',
properties: schemaProperties,
additionalProperties: false,
},
],
messages: {
assign: 'Assign {{type}} to a variable before exporting as module default',
anonymous: 'Unexpected default export of anonymous {{type}}',
},
},
defaultOptions: [],
create(context) {
const options = { ...defaults, ...context.options[0] };
return {
ExportDefaultDeclaration(node) {
const type = node.declaration
.type;
if (!(type in defs)) {
return;
}
const def = defs[type];
if (!options[def.option] && (!('forbid' in def) || def.forbid(node))) {
context.report({
node,
messageId: def.messageId,
data: def.data,
});
}
},
};
},
});
//# sourceMappingURL=no-anonymous-default-export.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"no-anonymous-default-export.js","sourceRoot":"","sources":["../../src/rules/no-anonymous-default-export.ts"],"names":[],"mappings":"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"}

View File

@@ -0,0 +1,10 @@
import type { TSESLint } from '@typescript-eslint/utils';
export interface NormalizedOptions {
allowPrimitiveModules?: boolean;
allowRequire?: boolean;
allowConditionalRequire?: boolean;
}
export type Options = 'allow-primitive-modules' | NormalizedOptions;
type MessageId = 'export' | 'import';
declare const _default: TSESLint.RuleModule<MessageId, [(Options | undefined)?], import("../utils/create-rule.ts").ImportXPluginDocs, TSESLint.RuleListener>;
export default _default;

View File

@@ -0,0 +1,132 @@
import { createRule } from '../utils/index.js';
function normalizeLegacyOptions(options) {
if (options.includes('allow-primitive-modules')) {
return { allowPrimitiveModules: true };
}
return options[0] || {};
}
function allowPrimitive(node, options) {
if (!options.allowPrimitiveModules) {
return false;
}
if (node.parent.type !== 'AssignmentExpression') {
return false;
}
return node.parent.right.type !== 'ObjectExpression';
}
function validateScope(scope) {
return scope.variableScope.type === 'module';
}
function isConditional(node) {
if (node.type === 'IfStatement' ||
node.type === 'TryStatement' ||
node.type === 'LogicalExpression' ||
node.type === 'ConditionalExpression') {
return true;
}
if (node.parent) {
return isConditional(node.parent);
}
return false;
}
function isLiteralString(node) {
return ((node.type === 'Literal' && typeof node.value === 'string') ||
(node.type === 'TemplateLiteral' && node.expressions.length === 0));
}
export default createRule({
name: 'no-commonjs',
meta: {
type: 'suggestion',
docs: {
category: 'Module systems',
description: 'Forbid CommonJS `require` calls and `module.exports` or `exports.*`.',
},
schema: {
anyOf: [
{
type: 'array',
items: [
{
type: 'string',
enum: ['allow-primitive-modules'],
},
],
additionalItems: false,
},
{
type: 'array',
items: [
{
type: 'object',
properties: {
allowPrimitiveModules: { type: 'boolean' },
allowRequire: { type: 'boolean' },
allowConditionalRequire: { type: 'boolean' },
},
additionalProperties: false,
},
],
additionalItems: false,
},
],
},
messages: {
export: 'Expected "export" or "export default"',
import: 'Expected "import" instead of "require()"',
},
},
defaultOptions: [],
create(context) {
const options = normalizeLegacyOptions(context.options);
return {
MemberExpression(node) {
if ('name' in node.object &&
node.object.name === 'module' &&
'name' in node.property &&
node.property.name === 'exports') {
if (allowPrimitive(node, options)) {
return;
}
context.report({ node, messageId: 'export' });
}
if ('name' in node.object && node.object.name === 'exports') {
const isInScope = context.sourceCode
.getScope(node)
.variables.some(variable => variable.name === 'exports');
if (!isInScope) {
context.report({ node, messageId: 'export' });
}
}
},
CallExpression(call) {
if (!validateScope(context.sourceCode.getScope(call))) {
return;
}
if (call.callee.type !== 'Identifier') {
return;
}
if (call.callee.name !== 'require') {
return;
}
if (call.arguments.length !== 1) {
return;
}
if (!isLiteralString(call.arguments[0])) {
return;
}
if (options.allowRequire) {
return;
}
if (options.allowConditionalRequire !== false &&
isConditional(call.parent)) {
return;
}
context.report({
node: call.callee,
messageId: 'import',
});
},
};
},
});
//# sourceMappingURL=no-commonjs.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"no-commonjs.js","sourceRoot":"","sources":["../../src/rules/no-commonjs.ts"],"names":[],"mappings":"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"}

View File

@@ -0,0 +1,14 @@
import type { DeclarationMetadata, ModuleOptions } from '../utils/index.js';
import { ExportMap } from '../utils/index.js';
export interface Options extends ModuleOptions {
allowUnsafeDynamicCyclicDependency?: boolean;
ignoreExternal?: boolean;
maxDepth?: number | '∞';
}
export type MessageId = 'cycle' | 'cycleSource';
export interface Traverser {
mget(): ExportMap | null;
route: Array<DeclarationMetadata['source']>;
}
declare const _default: import("@typescript-eslint/utils/ts-eslint").RuleModule<MessageId, [(Options | undefined)?], import("../utils/create-rule.ts").ImportXPluginDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
export default _default;

View File

@@ -0,0 +1,141 @@
import { ExportMap, isExternalModule, createRule, moduleVisitor, makeOptionsSchema, resolve, } from '../utils/index.js';
const traversed = new Set();
export default createRule({
name: 'no-cycle',
meta: {
type: 'suggestion',
docs: {
category: 'Static analysis',
description: 'Forbid a module from importing a module with a dependency path back to itself.',
},
schema: [
makeOptionsSchema({
maxDepth: {
anyOf: [
{
description: 'maximum dependency depth to traverse',
type: 'integer',
minimum: 1,
},
{
enum: ['∞'],
type: 'string',
},
],
},
ignoreExternal: {
description: 'ignore external modules',
type: 'boolean',
default: false,
},
allowUnsafeDynamicCyclicDependency: {
description: 'Allow cyclic dependency if there is at least one dynamic import in the chain',
type: 'boolean',
default: false,
},
}),
],
messages: {
cycle: 'Dependency cycle detected',
cycleSource: 'Dependency cycle via "{{source}}"',
},
},
defaultOptions: [],
create(context) {
const filename = context.physicalFilename;
if (filename === '<text>') {
return {};
}
const options = context.options[0] || {};
const maxDepth = typeof options.maxDepth === 'number'
? options.maxDepth
: Number.POSITIVE_INFINITY;
const ignoreModule = options.ignoreExternal
? (name) => isExternalModule(name, resolve(name, context), context)
: () => false;
return {
...moduleVisitor(function checkSourceValue(sourceNode, importer) {
if (ignoreModule(sourceNode.value)) {
return;
}
if (options.allowUnsafeDynamicCyclicDependency &&
(importer.type === 'ImportExpression' ||
(importer.type === 'CallExpression' &&
'name' in importer.callee &&
importer.callee.name !== 'require'))) {
return;
}
if (importer.type === 'ImportDeclaration' &&
(importer.importKind === 'type' ||
importer.specifiers.every(s => 'importKind' in s && s.importKind === 'type'))) {
return;
}
const imported = ExportMap.get(sourceNode.value, context);
if (imported == null) {
return;
}
if (imported.path === filename) {
return;
}
const untraversed = [{ mget: () => imported, route: [] }];
function detectCycle({ mget, route }) {
const m = mget();
if (m == null) {
return;
}
if (traversed.has(m.path)) {
return;
}
traversed.add(m.path);
for (const [path, { getter, declarations }] of m.imports) {
if (traversed.has(path)) {
continue;
}
const toTraverse = [...declarations].filter(({ source, isOnlyImportingTypes }) => !ignoreModule(source.value) &&
!isOnlyImportingTypes);
if (options.allowUnsafeDynamicCyclicDependency &&
toTraverse.some(d => d.dynamic)) {
return;
}
if (path === filename && toTraverse.length > 0) {
return true;
}
if (route.length + 1 < maxDepth) {
for (const { source } of toTraverse) {
untraversed.push({ mget: getter, route: [...route, source] });
}
}
}
}
while (untraversed.length > 0) {
const next = untraversed.shift();
if (detectCycle(next)) {
if (next.route.length > 0) {
context.report({
node: importer,
messageId: 'cycleSource',
data: {
source: routeString(next.route),
},
});
}
else {
context.report({
node: importer,
messageId: 'cycle',
});
}
return;
}
}
}, context.options[0]),
'Program:exit'() {
traversed.clear();
},
};
},
});
function routeString(route) {
return route.map(s => `${s.value}:${s.loc.start.line}`).join('=>');
}
//# sourceMappingURL=no-cycle.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"no-cycle.js","sourceRoot":"","sources":["../../src/rules/no-cycle.ts"],"names":[],"mappings":"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"}

View File

@@ -0,0 +1,2 @@
declare const _default: import("@typescript-eslint/utils/ts-eslint").RuleModule<"preferNamed" | "noAliasDefault", [], import("../utils/create-rule.ts").ImportXPluginDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
export default _default;

View File

@@ -0,0 +1,56 @@
import { createRule, getValue, sourceType } from '../utils/index.js';
export default createRule({
name: 'no-default-export',
meta: {
type: 'suggestion',
docs: {
category: 'Style guide',
description: 'Forbid default exports.',
},
schema: [],
messages: {
preferNamed: 'Prefer named exports.',
noAliasDefault: 'Do not alias `{{local}}` as `default`. Just export `{{local}}` itself instead.',
},
},
defaultOptions: [],
create(context) {
if (sourceType(context) !== 'module') {
return {};
}
const { sourceCode } = context;
return {
ExportDefaultDeclaration(node) {
const { loc } = sourceCode.getFirstTokens(node)[1] || {};
context.report({
node,
messageId: 'preferNamed',
loc,
});
},
ExportNamedDeclaration(node) {
for (const specifier of node.specifiers.filter(specifier => getValue(specifier.exported) === 'default')) {
const { loc } = sourceCode.getFirstTokens(node)[1] || {};
if (specifier.type === 'ExportDefaultSpecifier') {
context.report({
node,
messageId: 'preferNamed',
loc,
});
}
else if (specifier.type === 'ExportSpecifier') {
context.report({
node,
messageId: 'noAliasDefault',
data: {
local: getValue(specifier.local),
},
loc,
});
}
}
},
};
},
});
//# sourceMappingURL=no-default-export.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"no-default-export.js","sourceRoot":"","sources":["../../src/rules/no-default-export.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAEpE,eAAe,UAAU,CAAC;IACxB,IAAI,EAAE,mBAAmB;IACzB,IAAI,EAAE;QACJ,IAAI,EAAE,YAAY;QAClB,IAAI,EAAE;YACJ,QAAQ,EAAE,aAAa;YACvB,WAAW,EAAE,yBAAyB;SACvC;QACD,MAAM,EAAE,EAAE;QACV,QAAQ,EAAE;YACR,WAAW,EAAE,uBAAuB;YACpC,cAAc,EACZ,gFAAgF;SACnF;KACF;IACD,cAAc,EAAE,EAAE;IAClB,MAAM,CAAC,OAAO;QAEZ,IAAI,UAAU,CAAC,OAAO,CAAC,KAAK,QAAQ,EAAE,CAAC;YACrC,OAAO,EAAE,CAAA;QACX,CAAC;QAED,MAAM,EAAE,UAAU,EAAE,GAAG,OAAO,CAAA;QAE9B,OAAO;YACL,wBAAwB,CAAC,IAAI;gBAC3B,MAAM,EAAE,GAAG,EAAE,GAAG,UAAU,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAA;gBACxD,OAAO,CAAC,MAAM,CAAC;oBACb,IAAI;oBACJ,SAAS,EAAE,aAAa;oBACxB,GAAG;iBACJ,CAAC,CAAA;YACJ,CAAC;YAED,sBAAsB,CAAC,IAAI;gBACzB,KAAK,MAAM,SAAS,IAAI,IAAI,CAAC,UAAU,CAAC,MAAM,CAC5C,SAAS,CAAC,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,QAAQ,CAAC,KAAK,SAAS,CACxD,EAAE,CAAC;oBACF,MAAM,EAAE,GAAG,EAAE,GAAG,UAAU,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAA;oBAExD,IAAI,SAAS,CAAC,IAAI,KAAK,wBAAwB,EAAE,CAAC;wBAChD,OAAO,CAAC,MAAM,CAAC;4BACb,IAAI;4BACJ,SAAS,EAAE,aAAa;4BACxB,GAAG;yBACJ,CAAC,CAAA;oBACJ,CAAC;yBAAM,IAAI,SAAS,CAAC,IAAI,KAAK,iBAAiB,EAAE,CAAC;wBAChD,OAAO,CAAC,MAAM,CAAC;4BACb,IAAI;4BACJ,SAAS,EAAE,gBAAgB;4BAC3B,IAAI,EAAE;gCACJ,KAAK,EAAE,QAAQ,CAAC,SAAS,CAAC,KAAK,CAAC;6BACjC;4BACD,GAAG;yBACJ,CAAC,CAAA;oBACJ,CAAC;gBACH,CAAC;YACH,CAAC;SACF,CAAA;IACH,CAAC;CACF,CAAC,CAAA"}

View File

@@ -0,0 +1,2 @@
declare const _default: import("@typescript-eslint/utils/ts-eslint").RuleModule<"deprecated" | "deprecatedDesc", [], import("../utils/create-rule.ts").ImportXPluginDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
export default _default;

View File

@@ -0,0 +1,161 @@
import { ExportMap, createRule, declaredScope, getValue, } from '../utils/index.js';
function message(deprecation) {
if (deprecation.description) {
return {
messageId: 'deprecatedDesc',
data: { description: deprecation.description },
};
}
return { messageId: 'deprecated' };
}
function getDeprecation(metadata) {
if (!metadata || !metadata.doc) {
return;
}
return metadata.doc.tags.find(t => t.tag === 'deprecated');
}
export default createRule({
name: 'no-deprecated',
meta: {
type: 'suggestion',
docs: {
category: 'Helpful warnings',
description: 'Forbid imported names marked with `@deprecated` documentation tag.',
},
schema: [],
messages: {
deprecatedDesc: 'Deprecated: {{description}}',
deprecated: 'Deprecated: consider to find an alternative.',
},
},
defaultOptions: [],
create(context) {
const deprecated = new Map();
const namespaces = new Map();
return {
Program({ body }) {
for (const node of body) {
if (node.type !== 'ImportDeclaration') {
continue;
}
if (node.source == null) {
continue;
}
const imports = ExportMap.get(node.source.value, context);
if (imports == null) {
continue;
}
const moduleDeprecation = imports.doc?.tags.find(t => t.tag === 'deprecated');
if (moduleDeprecation) {
context.report({
node,
...message(moduleDeprecation),
});
}
if (imports.errors.length > 0) {
imports.reportErrors(context, node);
continue;
}
for (const im of node.specifiers) {
let imported;
let local;
switch (im.type) {
case 'ImportNamespaceSpecifier': {
if (imports.size === 0) {
continue;
}
namespaces.set(im.local.name, imports);
continue;
}
case 'ImportDefaultSpecifier': {
imported = 'default';
local = im.local.name;
break;
}
case 'ImportSpecifier': {
imported = getValue(im.imported);
local = im.local.name;
break;
}
default: {
continue;
}
}
const exported = imports.get(imported);
if (exported == null) {
continue;
}
if (exported.namespace) {
namespaces.set(local, exported.namespace);
}
const deprecation = getDeprecation(imports.get(imported));
if (!deprecation) {
continue;
}
context.report({
node: im,
...message(deprecation),
});
deprecated.set(local, deprecation);
}
}
},
Identifier(node) {
if (!node.parent ||
(node.parent.type === 'MemberExpression' &&
node.parent.property === node)) {
return;
}
if (node.parent.type.slice(0, 6) === 'Import') {
return;
}
if (!deprecated.has(node.name)) {
return;
}
if (declaredScope(context, node, node.name) !== 'module') {
return;
}
context.report({
node,
...message(deprecated.get(node.name)),
});
},
MemberExpression(dereference) {
if (dereference.object.type !== 'Identifier') {
return;
}
if (!namespaces.has(dereference.object.name)) {
return;
}
if (declaredScope(context, dereference, dereference.object.name) !==
'module') {
return;
}
let namespace = namespaces.get(dereference.object.name);
const namepath = [dereference.object.name];
let node = dereference;
while (namespace instanceof ExportMap &&
node?.type === 'MemberExpression') {
if (node.computed) {
return;
}
const metadata = namespace.get(node.property.name);
if (!metadata) {
break;
}
const deprecation = getDeprecation(metadata);
if (deprecation) {
context.report({
node: node.property,
...message(deprecation),
});
}
namepath.push(node.property.name);
namespace = metadata.namespace;
node = node.parent;
}
},
};
},
});
//# sourceMappingURL=no-deprecated.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"no-deprecated.js","sourceRoot":"","sources":["../../src/rules/no-deprecated.ts"],"names":[],"mappings":"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"}

View File

@@ -0,0 +1,15 @@
import type { TSESLint, TSESTree } from '@typescript-eslint/utils';
export interface Options {
considerQueryString?: boolean;
'prefer-inline'?: boolean;
}
export type MessageId = 'duplicate';
export interface ModuleMap {
imported: Map<string, TSESTree.ImportDeclaration[]>;
nsImported: Map<string, TSESTree.ImportDeclaration[]>;
defaultTypesImported: Map<string, TSESTree.ImportDeclaration[]>;
namespaceTypesImported: Map<string, TSESTree.ImportDeclaration[]>;
namedTypesImported: Map<string, TSESTree.ImportDeclaration[]>;
}
declare const _default: TSESLint.RuleModule<"duplicate", [(Options | undefined)?], import("../utils/create-rule.ts").ImportXPluginDocs, TSESLint.RuleListener>;
export default _default;

View File

@@ -0,0 +1,313 @@
import * as semver from 'semver';
import { cjsRequire } from '../require.js';
import { createRule, lazy, resolve } from '../utils/index.js';
const isTypeScriptVersionSupportPreferInline = lazy(() => {
let typescriptPkg;
try {
typescriptPkg = cjsRequire('typescript/package.json');
}
catch {
}
return !typescriptPkg || !semver.satisfies(typescriptPkg.version, '>= 4.5');
});
function checkImports(imported, context) {
imported.forEach((nodes, module) => {
if (nodes.length <= 1) {
return;
}
for (let i = 0, len = nodes.length; i < len; i++) {
const node = nodes[i];
context.report({
node: node.source,
messageId: 'duplicate',
data: {
module,
},
fix: i === 0 ? getFix(nodes, context.sourceCode, context) : null,
});
}
});
}
function getFix(nodes, sourceCode, context) {
const first = nodes[0];
if (hasProblematicComments(first, sourceCode) || hasNamespace(first)) {
return null;
}
const defaultImportNames = new Set(nodes.flatMap(x => getDefaultImportName(x) || []));
if (defaultImportNames.size > 1) {
return null;
}
const rest = nodes.slice(1);
const restWithoutCommentsAndNamespaces = rest.filter(node => !hasProblematicComments(node, sourceCode) && !hasNamespace(node));
const restWithoutCommentsAndNamespacesHasSpecifiers = restWithoutCommentsAndNamespaces.map(hasSpecifiers);
const specifiers = restWithoutCommentsAndNamespaces.reduce((acc, node, nodeIndex) => {
const tokens = sourceCode.getTokens(node);
const openBrace = tokens.find(token => isPunctuator(token, '{'));
const closeBrace = tokens.find(token => isPunctuator(token, '}'));
if (openBrace == null || closeBrace == null) {
return acc;
}
acc.push({
importNode: node,
identifiers: sourceCode.text
.slice(openBrace.range[1], closeBrace.range[0])
.split(','),
isEmpty: !restWithoutCommentsAndNamespacesHasSpecifiers[nodeIndex],
});
return acc;
}, []);
const unnecessaryImports = restWithoutCommentsAndNamespaces.filter((node, nodeIndex) => !restWithoutCommentsAndNamespacesHasSpecifiers[nodeIndex] &&
!specifiers.some(specifier => specifier.importNode === node));
const shouldAddSpecifiers = specifiers.length > 0;
const shouldRemoveUnnecessary = unnecessaryImports.length > 0;
const shouldAddDefault = lazy(() => getDefaultImportName(first) == null && defaultImportNames.size === 1);
if (!shouldAddSpecifiers && !shouldRemoveUnnecessary && !shouldAddDefault()) {
return null;
}
const preferInline = context.options[0] && context.options[0]['prefer-inline'];
return (fixer) => {
const tokens = sourceCode.getTokens(first);
const openBrace = tokens.find(token => isPunctuator(token, '{'));
const closeBrace = tokens.find(token => isPunctuator(token, '}'));
const firstToken = sourceCode.getFirstToken(first);
const [defaultImportName] = defaultImportNames;
const firstHasTrailingComma = closeBrace != null &&
isPunctuator(sourceCode.getTokenBefore(closeBrace), ',');
const firstIsEmpty = !hasSpecifiers(first);
const firstExistingIdentifiers = firstIsEmpty
? new Set()
: new Set(sourceCode.text
.slice(openBrace.range[1], closeBrace.range[0])
.split(',')
.map(x => x.split(' as ')[0].trim()));
const [specifiersText] = specifiers.reduce(([result, needsComma, existingIdentifiers], specifier) => {
const isTypeSpecifier = 'importNode' in specifier &&
specifier.importNode.importKind === 'type';
if (preferInline && isTypeScriptVersionSupportPreferInline()) {
throw new Error('Your version of TypeScript does not support inline type imports.');
}
const [specifierText, updatedExistingIdentifiers] = specifier.identifiers.reduce(([text, set], cur) => {
const trimmed = cur.trim();
if (trimmed.length === 0 || existingIdentifiers.has(trimmed)) {
return [text, set];
}
const curWithType = preferInline && isTypeSpecifier
? cur.replace(/^(\s*)/, '$1type ')
: cur;
return [
text.length > 0 ? `${text},${curWithType}` : curWithType,
set.add(trimmed),
];
}, ['', existingIdentifiers]);
return [
needsComma && !specifier.isEmpty && specifierText.length > 0
? `${result},${specifierText}`
: `${result}${specifierText}`,
specifier.isEmpty ? needsComma : true,
updatedExistingIdentifiers,
];
}, ['', !firstHasTrailingComma && !firstIsEmpty, firstExistingIdentifiers]);
const fixes = [];
if (shouldAddSpecifiers && preferInline && first.importKind === 'type') {
const typeIdentifierToken = tokens.find(token => token.type === 'Identifier' && token.value === 'type');
if (typeIdentifierToken) {
fixes.push(fixer.removeRange([
typeIdentifierToken.range[0],
typeIdentifierToken.range[1] + 1,
]));
}
for (const identifier of tokens.filter(token => firstExistingIdentifiers.has(token.value))) {
fixes.push(fixer.replaceTextRange([identifier.range[0], identifier.range[1]], `type ${identifier.value}`));
}
}
if (openBrace == null && shouldAddSpecifiers && shouldAddDefault()) {
fixes.push(fixer.insertTextAfter(firstToken, ` ${defaultImportName}, {${specifiersText}} from`));
}
else if (openBrace == null &&
!shouldAddSpecifiers &&
shouldAddDefault()) {
fixes.push(fixer.insertTextAfter(firstToken, ` ${defaultImportName} from`));
}
else if (openBrace != null && closeBrace != null && shouldAddDefault()) {
fixes.push(fixer.insertTextAfter(firstToken, ` ${defaultImportName},`));
if (shouldAddSpecifiers) {
fixes.push(fixer.insertTextBefore(closeBrace, specifiersText));
}
}
else if (openBrace == null &&
shouldAddSpecifiers &&
!shouldAddDefault()) {
if (first.specifiers.length === 0) {
fixes.push(fixer.insertTextAfter(firstToken, ` {${specifiersText}} from`));
}
else {
fixes.push(fixer.insertTextAfter(first.specifiers[0], `, {${specifiersText}}`));
}
}
else if (openBrace != null && closeBrace != null && !shouldAddDefault()) {
const tokenBefore = sourceCode.getTokenBefore(closeBrace);
fixes.push(fixer.insertTextAfter(tokenBefore, specifiersText));
}
for (const specifier of specifiers) {
const importNode = specifier.importNode;
fixes.push(fixer.remove(importNode));
const charAfterImportRange = [
importNode.range[1],
importNode.range[1] + 1,
];
const charAfterImport = sourceCode.text.slice(charAfterImportRange[0], charAfterImportRange[1]);
if (charAfterImport === '\n') {
fixes.push(fixer.removeRange(charAfterImportRange));
}
}
for (const node of unnecessaryImports) {
fixes.push(fixer.remove(node));
const charAfterImportRange = [node.range[1], node.range[1] + 1];
const charAfterImport = sourceCode.text.slice(charAfterImportRange[0], charAfterImportRange[1]);
if (charAfterImport === '\n') {
fixes.push(fixer.removeRange(charAfterImportRange));
}
}
return fixes;
};
}
function isPunctuator(node, value) {
return node.type === 'Punctuator' && node.value === value;
}
function getDefaultImportName(node) {
const defaultSpecifier = node.specifiers.find(specifier => specifier.type === 'ImportDefaultSpecifier');
return defaultSpecifier?.local.name;
}
function hasNamespace(node) {
return node.specifiers.some(specifier => specifier.type === 'ImportNamespaceSpecifier');
}
function hasSpecifiers(node) {
return node.specifiers.some(specifier => specifier.type === 'ImportSpecifier');
}
function hasProblematicComments(node, sourceCode) {
return (hasCommentBefore(node, sourceCode) ||
hasCommentAfter(node, sourceCode) ||
hasCommentInsideNonSpecifiers(node, sourceCode));
}
function hasCommentBefore(node, sourceCode) {
return sourceCode
.getCommentsBefore(node)
.some(comment => comment.loc.end.line >= node.loc.start.line - 1);
}
function hasCommentAfter(node, sourceCode) {
return sourceCode
.getCommentsAfter(node)
.some(comment => comment.loc.start.line === node.loc.end.line);
}
function hasCommentInsideNonSpecifiers(node, sourceCode) {
const tokens = sourceCode.getTokens(node);
const openBraceIndex = tokens.findIndex(token => isPunctuator(token, '{'));
const closeBraceIndex = tokens.findIndex(token => isPunctuator(token, '}'));
const someTokens = openBraceIndex !== -1 && closeBraceIndex !== -1
? [
...tokens.slice(1, openBraceIndex + 1),
...tokens.slice(closeBraceIndex + 1),
]
: tokens.slice(1);
return someTokens.some(token => sourceCode.getCommentsBefore(token).length > 0);
}
export default createRule({
name: 'no-duplicates',
meta: {
type: 'problem',
docs: {
category: 'Style guide',
description: 'Forbid repeated import of the same module in multiple places.',
},
fixable: 'code',
schema: [
{
type: 'object',
properties: {
considerQueryString: {
type: 'boolean',
},
'prefer-inline': {
type: 'boolean',
},
},
additionalProperties: false,
},
],
messages: {
duplicate: "'{{module}}' imported multiple times.",
},
},
defaultOptions: [],
create(context) {
const preferInline = context.options[0]?.['prefer-inline'];
const considerQueryStringOption = context.options[0]?.considerQueryString;
const defaultResolver = (sourcePath) => resolve(sourcePath, context) || sourcePath;
const resolver = considerQueryStringOption
? (sourcePath) => {
const parts = sourcePath.match(/^([^?]*)\?(.*)$/);
if (!parts) {
return defaultResolver(sourcePath);
}
return `${defaultResolver(parts[1])}?${parts[2]}`;
}
: defaultResolver;
const moduleMaps = new Map();
function getImportMap(n) {
const parent = n.parent;
let map;
if (moduleMaps.has(parent)) {
map = moduleMaps.get(parent);
}
else {
map = {
imported: new Map(),
nsImported: new Map(),
defaultTypesImported: new Map(),
namespaceTypesImported: new Map(),
namedTypesImported: new Map(),
};
moduleMaps.set(parent, map);
}
if (n.importKind === 'type') {
if (n.specifiers.length > 0 &&
n.specifiers[0].type === 'ImportDefaultSpecifier') {
return map.defaultTypesImported;
}
if (n.specifiers.length > 0 &&
n.specifiers[0].type === 'ImportNamespaceSpecifier') {
return map.namespaceTypesImported;
}
if (!preferInline) {
return map.namedTypesImported;
}
}
if (!preferInline &&
n.specifiers.some(spec => 'importKind' in spec && spec.importKind === 'type')) {
return map.namedTypesImported;
}
return hasNamespace(n) ? map.nsImported : map.imported;
}
return {
ImportDeclaration(n) {
const resolvedPath = resolver(n.source.value);
const importMap = getImportMap(n);
if (importMap.has(resolvedPath)) {
importMap.get(resolvedPath).push(n);
}
else {
importMap.set(resolvedPath, [n]);
}
},
'Program:exit'() {
for (const map of moduleMaps.values()) {
checkImports(map.imported, context);
checkImports(map.nsImported, context);
checkImports(map.defaultTypesImported, context);
checkImports(map.namedTypesImported, context);
}
},
};
},
});
//# sourceMappingURL=no-duplicates.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,6 @@
export interface Options {
esmodule?: boolean;
}
export type MessageId = 'import' | 'require';
declare const _default: import("@typescript-eslint/utils/ts-eslint").RuleModule<MessageId, [(Options | undefined)?], import("../utils/create-rule.ts").ImportXPluginDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
export default _default;

View File

@@ -0,0 +1,72 @@
import { createRule } from '../utils/index.js';
function isRequire(node) {
return (node.callee?.type === 'Identifier' &&
node.callee.name === 'require' &&
node.arguments.length > 0);
}
function isDynamicImport(node) {
return (node?.callee &&
node.callee.type === 'Import');
}
function isStaticValue(node) {
return (node.type === 'Literal' ||
(node.type === 'TemplateLiteral' && node.expressions.length === 0));
}
export default createRule({
name: 'no-dynamic-require',
meta: {
type: 'suggestion',
docs: {
category: 'Static analysis',
description: 'Forbid `require()` calls with expressions.',
},
schema: [
{
type: 'object',
properties: {
esmodule: {
type: 'boolean',
},
},
additionalProperties: false,
},
],
messages: {
import: 'Calls to import() should use string literals',
require: 'Calls to require() should use string literals',
},
},
defaultOptions: [],
create(context) {
const options = context.options[0] || {};
return {
CallExpression(node) {
if (!node.arguments[0] || isStaticValue(node.arguments[0])) {
return;
}
if (isRequire(node)) {
return context.report({
node,
messageId: 'require',
});
}
if (options.esmodule && isDynamicImport(node)) {
return context.report({
node,
messageId: 'import',
});
}
},
ImportExpression(node) {
if (!options.esmodule || isStaticValue(node.source)) {
return;
}
return context.report({
node,
messageId: 'import',
});
},
};
},
});
//# sourceMappingURL=no-dynamic-require.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"no-dynamic-require.js","sourceRoot":"","sources":["../../src/rules/no-dynamic-require.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAE9C,SAAS,SAAS,CAAC,IAA6B;IAC9C,OAAO,CACL,IAAI,CAAC,MAAM,EAAE,IAAI,KAAK,YAAY;QAClC,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,SAAS;QAC9B,IAAI,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,CAC1B,CAAA;AACH,CAAC;AAED,SAAS,eAAe,CAAC,IAA6B;IACpD,OAAO,CACL,IAAI,EAAE,MAAM;QAEZ,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,QAAQ,CAC9B,CAAA;AACH,CAAC;AAED,SAAS,aAAa,CACpB,IAAmB;IAEnB,OAAO,CACL,IAAI,CAAC,IAAI,KAAK,SAAS;QACvB,CAAC,IAAI,CAAC,IAAI,KAAK,iBAAiB,IAAI,IAAI,CAAC,WAAW,CAAC,MAAM,KAAK,CAAC,CAAC,CACnE,CAAA;AACH,CAAC;AAQD,eAAe,UAAU,CAAwB;IAC/C,IAAI,EAAE,oBAAoB;IAC1B,IAAI,EAAE;QACJ,IAAI,EAAE,YAAY;QAClB,IAAI,EAAE;YACJ,QAAQ,EAAE,iBAAiB;YAC3B,WAAW,EAAE,4CAA4C;SAC1D;QACD,MAAM,EAAE;YACN;gBACE,IAAI,EAAE,QAAQ;gBACd,UAAU,EAAE;oBACV,QAAQ,EAAE;wBACR,IAAI,EAAE,SAAS;qBAChB;iBACF;gBACD,oBAAoB,EAAE,KAAK;aAC5B;SACF;QACD,QAAQ,EAAE;YACR,MAAM,EAAE,8CAA8C;YACtD,OAAO,EAAE,+CAA+C;SACzD;KACF;IACD,cAAc,EAAE,EAAE;IAClB,MAAM,CAAC,OAAO;QACZ,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,EAAE,CAAA;QAExC,OAAO;YACL,cAAc,CAAC,IAAI;gBACjB,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,aAAa,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;oBAC3D,OAAM;gBACR,CAAC;gBACD,IAAI,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC;oBACpB,OAAO,OAAO,CAAC,MAAM,CAAC;wBACpB,IAAI;wBACJ,SAAS,EAAE,SAAS;qBACrB,CAAC,CAAA;gBACJ,CAAC;gBACD,IAAI,OAAO,CAAC,QAAQ,IAAI,eAAe,CAAC,IAAI,CAAC,EAAE,CAAC;oBAC9C,OAAO,OAAO,CAAC,MAAM,CAAC;wBACpB,IAAI;wBACJ,SAAS,EAAE,QAAQ;qBACpB,CAAC,CAAA;gBACJ,CAAC;YACH,CAAC;YACD,gBAAgB,CAAC,IAAI;gBACnB,IAAI,CAAC,OAAO,CAAC,QAAQ,IAAI,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;oBACpD,OAAM;gBACR,CAAC;gBACD,OAAO,OAAO,CAAC,MAAM,CAAC;oBACpB,IAAI;oBACJ,SAAS,EAAE,QAAQ;iBACpB,CAAC,CAAA;YACJ,CAAC;SACF,CAAA;IACH,CAAC;CACF,CAAC,CAAA"}

View File

@@ -0,0 +1,2 @@
declare const _default: import("@typescript-eslint/utils/ts-eslint").RuleModule<"emptyNamed" | "unused" | "emptyImport", [], import("../utils/create-rule.ts").ImportXPluginDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
export default _default;

View File

@@ -0,0 +1,103 @@
import { createRule } from '../utils/index.js';
function getEmptyBlockRange(tokens, index) {
const token = tokens[index];
const nextToken = tokens[index + 1];
const prevToken = tokens[index - 1];
let start = token.range[0];
const end = nextToken.range[1];
if (prevToken.value === ',' ||
prevToken.value === 'type' ||
prevToken.value === 'typeof') {
start = prevToken.range[0];
}
return [start, end];
}
export default createRule({
name: 'no-empty-named-blocks',
meta: {
type: 'suggestion',
docs: {
category: 'Helpful warnings',
description: 'Forbid empty named import blocks.',
},
fixable: 'code',
hasSuggestions: true,
schema: [],
messages: {
emptyNamed: 'Unexpected empty named import block',
unused: 'Remove unused import',
emptyImport: 'Remove empty import block',
},
},
defaultOptions: [],
create(context) {
const importsWithoutNameds = [];
return {
ImportDeclaration(node) {
if (!node.specifiers.some(x => x.type === 'ImportSpecifier')) {
importsWithoutNameds.push(node);
}
},
'Program:exit'(program) {
const importsTokens = importsWithoutNameds.map(node => [
node,
program.tokens.filter(x => x.range[0] >= node.range[0] && x.range[1] <= node.range[1]),
]);
const pTokens = program.tokens || [];
for (const [node, tokens] of importsTokens) {
for (const token of tokens) {
const idx = pTokens.indexOf(token);
const nextToken = pTokens[idx + 1];
if (nextToken && token.value === '{' && nextToken.value === '}') {
const hasOtherIdentifiers = tokens.some(token => token.type === 'Identifier' &&
token.value !== 'from' &&
token.value !== 'type' &&
token.value !== 'typeof');
if (hasOtherIdentifiers) {
context.report({
node,
messageId: 'emptyNamed',
fix(fixer) {
return fixer.removeRange(getEmptyBlockRange(pTokens, idx));
},
});
}
else {
context.report({
node,
messageId: 'emptyNamed',
suggest: [
{
messageId: 'unused',
fix(fixer) {
return fixer.remove(node);
},
},
{
messageId: 'emptyImport',
fix(fixer) {
const { sourceCode } = context;
const fromToken = pTokens.find(t => t.value === 'from');
const importToken = pTokens.find(t => t.value === 'import');
const hasSpaceAfterFrom = sourceCode.isSpaceBetween(fromToken, sourceCode.getTokenAfter(fromToken));
const hasSpaceAfterImport = sourceCode.isSpaceBetween(importToken, sourceCode.getTokenAfter(fromToken));
const [start] = getEmptyBlockRange(pTokens, idx);
const [, end] = fromToken.range;
const range = [
start,
hasSpaceAfterFrom ? end + 1 : end,
];
return fixer.replaceTextRange(range, hasSpaceAfterImport ? '' : ' ');
},
},
],
});
}
}
}
}
},
};
},
});
//# sourceMappingURL=no-empty-named-blocks.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"no-empty-named-blocks.js","sourceRoot":"","sources":["../../src/rules/no-empty-named-blocks.ts"],"names":[],"mappings":"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"}

View File

@@ -0,0 +1,37 @@
import type { PackageJson } from 'type-fest';
export type PackageDeps = ReturnType<typeof extractDepFields>;
declare function extractDepFields(pkg: PackageJson): {
dependencies: Partial<Record<string, string>>;
devDependencies: Partial<Record<string, string>>;
optionalDependencies: Partial<Record<string, string>>;
peerDependencies: Partial<Record<string, string>>;
bundledDependencies: string[];
};
export interface DepDeclaration {
isInDeps: boolean;
isInDevDeps: boolean;
isInOptDeps: boolean;
isInPeerDeps: boolean;
isInBundledDeps: boolean;
}
export interface DepsOptions {
allowDevDeps: boolean;
allowOptDeps: boolean;
allowPeerDeps: boolean;
allowBundledDeps: boolean;
verifyInternalDeps: boolean;
verifyTypeImports: boolean;
}
export interface Options {
packageDir?: string | string[];
devDependencies?: boolean | string[];
optionalDependencies?: boolean | string[];
peerDependencies?: boolean | string[];
bundledDependencies?: boolean | string[];
includeInternal?: boolean;
includeTypes?: boolean;
whitelist?: string[];
}
export type MessageId = 'pkgNotFound' | 'pkgUnparsable' | 'devDep' | 'optDep' | 'missing';
declare const _default: import("@typescript-eslint/utils/ts-eslint").RuleModule<MessageId, [(Options | undefined)?], import("../utils/create-rule.ts").ImportXPluginDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
export default _default;

View File

@@ -0,0 +1,278 @@
import fs from 'node:fs';
import path from 'node:path';
import { minimatch } from 'minimatch';
import { createRule, moduleVisitor, resolve, pkgUp, importType, getFilePackageName, getNpmInstallCommand, } from '../utils/index.js';
const depFieldCache = new Map();
function hasKeys(obj = {}) {
return Object.keys(obj).length > 0;
}
function arrayOrKeys(arrayOrObject) {
return Array.isArray(arrayOrObject)
? arrayOrObject
: Object.keys(arrayOrObject);
}
function readJSON(jsonPath, throwException) {
try {
return JSON.parse(fs.readFileSync(jsonPath, 'utf8'));
}
catch (error) {
if (throwException) {
throw error;
}
}
}
function extractDepFields(pkg) {
return {
dependencies: pkg.dependencies || {},
devDependencies: pkg.devDependencies || {},
optionalDependencies: pkg.optionalDependencies || {},
peerDependencies: pkg.peerDependencies || {},
bundledDependencies: arrayOrKeys(pkg.bundleDependencies || pkg.bundledDependencies || []),
};
}
function getPackageDepFields(packageJsonPath, throwAtRead) {
if (!depFieldCache.has(packageJsonPath)) {
const packageJson = readJSON(packageJsonPath, throwAtRead);
if (packageJson) {
const depFields = extractDepFields(packageJson);
depFieldCache.set(packageJsonPath, depFields);
}
}
return depFieldCache.get(packageJsonPath);
}
function getDependencies(context, packageDir) {
let paths = [];
try {
let packageContent = {
dependencies: {},
devDependencies: {},
optionalDependencies: {},
peerDependencies: {},
bundledDependencies: [],
};
if (packageDir && packageDir.length > 0) {
paths = Array.isArray(packageDir)
? packageDir.map(dir => path.resolve(dir))
: [path.resolve(packageDir)];
}
if (paths.length > 0) {
for (const dir of paths) {
const packageJsonPath = path.resolve(dir, 'package.json');
const packageContent_ = getPackageDepFields(packageJsonPath, paths.length === 1);
if (packageContent_) {
for (const depsKey of Object.keys(packageContent)) {
const key = depsKey;
Object.assign(packageContent[key], packageContent_[key]);
}
}
}
}
else {
const packageJsonPath = pkgUp({
cwd: context.physicalFilename,
});
const packageContent_ = getPackageDepFields(packageJsonPath, false);
if (packageContent_) {
packageContent = packageContent_;
}
}
if (![
packageContent.dependencies,
packageContent.devDependencies,
packageContent.optionalDependencies,
packageContent.peerDependencies,
packageContent.bundledDependencies,
].some(hasKeys)) {
return;
}
return packageContent;
}
catch (error_) {
const error = error_;
if (paths.length > 0 && error.code === 'ENOENT') {
context.report({
messageId: 'pkgNotFound',
loc: { line: 0, column: 0 },
});
}
if (error.name === 'JSONError' || error instanceof SyntaxError) {
context.report({
messageId: 'pkgUnparsable',
data: { error: error.message },
loc: { line: 0, column: 0 },
});
}
}
}
function getModuleOriginalName(name) {
const [first, second] = name.split('/');
return first.startsWith('@') ? `${first}/${second}` : first;
}
function checkDependencyDeclaration(deps, packageName, declarationStatus) {
const newDeclarationStatus = declarationStatus || {
isInDeps: false,
isInDevDeps: false,
isInOptDeps: false,
isInPeerDeps: false,
isInBundledDeps: false,
};
const packageHierarchy = [];
const packageNameParts = packageName ? packageName.split('/') : [];
for (const [index, namePart] of packageNameParts.entries()) {
if (!namePart.startsWith('@')) {
const ancestor = packageNameParts.slice(0, index + 1).join('/');
packageHierarchy.push(ancestor);
}
}
return packageHierarchy.reduce((result, ancestorName) => ({
isInDeps: result.isInDeps || deps.dependencies[ancestorName] !== undefined,
isInDevDeps: result.isInDevDeps || deps.devDependencies[ancestorName] !== undefined,
isInOptDeps: result.isInOptDeps ||
deps.optionalDependencies[ancestorName] !== undefined,
isInPeerDeps: result.isInPeerDeps ||
deps.peerDependencies[ancestorName] !== undefined,
isInBundledDeps: result.isInBundledDeps ||
deps.bundledDependencies.includes(ancestorName),
}), newDeclarationStatus);
}
function reportIfMissing(context, deps, depsOptions, node, name, whitelist) {
if (!depsOptions.verifyTypeImports &&
(('importKind' in node &&
(node.importKind === 'type' ||
node.importKind === 'typeof')) ||
('exportKind' in node && node.exportKind === 'type') ||
('specifiers' in node &&
Array.isArray(node.specifiers) &&
node.specifiers.length > 0 &&
node.specifiers.every(specifier => 'importKind' in specifier &&
(specifier.importKind === 'type' ||
specifier.importKind === 'typeof'))))) {
return;
}
const typeOfImport = importType(name, context);
if (typeOfImport !== 'external' &&
(typeOfImport !== 'internal' || !depsOptions.verifyInternalDeps)) {
return;
}
const resolved = resolve(name, context);
if (!resolved) {
return;
}
const importPackageName = getModuleOriginalName(name);
let declarationStatus = checkDependencyDeclaration(deps, importPackageName);
if (declarationStatus.isInDeps ||
(depsOptions.allowDevDeps && declarationStatus.isInDevDeps) ||
(depsOptions.allowPeerDeps && declarationStatus.isInPeerDeps) ||
(depsOptions.allowOptDeps && declarationStatus.isInOptDeps) ||
(depsOptions.allowBundledDeps && declarationStatus.isInBundledDeps)) {
return;
}
const realPackageName = getFilePackageName(resolved);
if (realPackageName && realPackageName !== importPackageName) {
declarationStatus = checkDependencyDeclaration(deps, realPackageName, declarationStatus);
if (declarationStatus.isInDeps ||
(depsOptions.allowDevDeps && declarationStatus.isInDevDeps) ||
(depsOptions.allowPeerDeps && declarationStatus.isInPeerDeps) ||
(depsOptions.allowOptDeps && declarationStatus.isInOptDeps) ||
(depsOptions.allowBundledDeps && declarationStatus.isInBundledDeps)) {
return;
}
}
const packageName = realPackageName || importPackageName;
if (whitelist?.has(packageName)) {
return;
}
if (declarationStatus.isInDevDeps && !depsOptions.allowDevDeps) {
context.report({
node,
messageId: 'devDep',
data: {
packageName,
},
});
return;
}
if (declarationStatus.isInOptDeps && !depsOptions.allowOptDeps) {
context.report({
node,
messageId: 'optDep',
data: {
packageName,
},
});
return;
}
context.report({
node,
messageId: 'missing',
data: {
packageName,
},
});
}
function testConfig(config, context) {
if (typeof config === 'boolean' || config === undefined) {
return config;
}
const filename = context.physicalFilename;
return config.some(c => minimatch(filename, c) ||
minimatch(filename, path.resolve(context.cwd, c), {
windowsPathsNoEscape: true,
}) ||
minimatch(filename, path.resolve(c), { windowsPathsNoEscape: true }));
}
export default createRule({
name: 'no-extraneous-dependencies',
meta: {
type: 'problem',
docs: {
category: 'Helpful warnings',
description: 'Forbid the use of extraneous packages.',
},
schema: [
{
type: 'object',
properties: {
devDependencies: { type: ['boolean', 'array'] },
optionalDependencies: { type: ['boolean', 'array'] },
peerDependencies: { type: ['boolean', 'array'] },
bundledDependencies: { type: ['boolean', 'array'] },
packageDir: { type: ['string', 'array'] },
includeInternal: { type: ['boolean'] },
includeTypes: { type: ['boolean'] },
whitelist: { type: ['array'] },
},
additionalProperties: false,
},
],
messages: {
pkgNotFound: 'The package.json file could not be found.',
pkgUnparsable: 'The package.json file could not be parsed: {{error}}',
devDep: "'{{packageName}}' should be listed in the project's dependencies, not devDependencies.",
optDep: "'{{packageName}}' should be listed in the project's dependencies, not optionalDependencies.",
missing: `'{{packageName}}' should be listed in the project's dependencies. Run '${getNpmInstallCommand('{{packageName}}')}' to add it`,
},
},
defaultOptions: [],
create(context) {
const options = context.options[0] || {};
const deps = getDependencies(context, options.packageDir) || extractDepFields({});
const depsOptions = {
allowDevDeps: testConfig(options.devDependencies, context) !== false,
allowOptDeps: testConfig(options.optionalDependencies, context) !== false,
allowPeerDeps: testConfig(options.peerDependencies, context) !== false,
allowBundledDeps: testConfig(options.bundledDependencies, context) !== false,
verifyInternalDeps: !!options.includeInternal,
verifyTypeImports: !!options.includeTypes,
};
return {
...moduleVisitor((source, node) => {
reportIfMissing(context, deps, depsOptions, node, source.value, options.whitelist ? new Set(options.whitelist) : undefined);
}, { commonjs: true }),
'Program:exit'() {
depFieldCache.clear();
},
};
},
});
//# sourceMappingURL=no-extraneous-dependencies.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,7 @@
import type { TSESLint } from '@typescript-eslint/utils';
export interface Options {
exceptions?: string[];
}
export type MessageId = 'notAllowed';
declare const _default: TSESLint.RuleModule<"notAllowed", [(Options | undefined)?], import("../utils/create-rule.ts").ImportXPluginDocs, TSESLint.RuleListener>;
export default _default;

View File

@@ -0,0 +1,94 @@
import path from 'node:path';
import { minimatch } from 'minimatch';
import { cjsRequire } from '../require.js';
import { createRule, pkgUp } from '../utils/index.js';
function getEntryPoint(context) {
const pkgPath = pkgUp({
cwd: context.physicalFilename,
});
try {
return cjsRequire.resolve(path.dirname(pkgPath));
}
catch {
return null;
}
}
function findScope(context, identifier) {
const { scopeManager } = context.sourceCode;
return scopeManager?.scopes
.slice()
.reverse()
.find(scope => scope.variables.some(variable => variable.identifiers.some(node => node.name === identifier)));
}
function findDefinition(objectScope, identifier) {
const variable = objectScope.variables.find(variable => variable.name === identifier);
return variable.defs.find(def => 'name' in def.name && def.name.name === identifier);
}
export default createRule({
name: 'no-import-module-exports',
meta: {
type: 'problem',
docs: {
category: 'Module systems',
description: 'Forbid import statements with CommonJS module.exports.',
recommended: true,
},
fixable: 'code',
schema: [
{
type: 'object',
properties: {
exceptions: { type: 'array' },
},
additionalProperties: false,
},
],
messages: {
notAllowed: "Cannot use import declarations in modules that export using CommonJS (module.exports = 'foo' or exports.bar = 'hi')",
},
},
defaultOptions: [],
create(context) {
const importDeclarations = [];
const entryPoint = getEntryPoint(context);
const options = context.options[0] || {};
let alreadyReported = false;
return {
ImportDeclaration(node) {
importDeclarations.push(node);
},
MemberExpression(node) {
if (alreadyReported) {
return;
}
const filename = context.physicalFilename;
const isEntryPoint = entryPoint === filename;
const isIdentifier = node.object.type === 'Identifier';
if (!('name' in node.object)) {
return;
}
const hasKeywords = /^(module|exports)$/.test(node.object.name);
const objectScope = hasKeywords
? findScope(context, node.object.name)
: undefined;
const variableDefinition = objectScope && findDefinition(objectScope, node.object.name);
const isImportBinding = variableDefinition?.type === 'ImportBinding';
const hasCJSExportReference = hasKeywords && (!objectScope || objectScope.type === 'module');
if (isIdentifier &&
hasCJSExportReference &&
!isEntryPoint &&
!options.exceptions?.some(glob => minimatch(filename, glob, { nocomment: true })) &&
!isImportBinding) {
for (const importDeclaration of importDeclarations) {
context.report({
node: importDeclaration,
messageId: 'notAllowed',
});
}
alreadyReported = true;
}
},
};
},
});
//# sourceMappingURL=no-import-module-exports.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"no-import-module-exports.js","sourceRoot":"","sources":["../../src/rules/no-import-module-exports.ts"],"names":[],"mappings":"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"}

View File

@@ -0,0 +1,7 @@
export interface Options {
allow?: string[];
forbid?: string[];
}
export type MessageId = 'noAllowed';
declare const _default: import("@typescript-eslint/utils/ts-eslint").RuleModule<"noAllowed", [(Options | undefined)?], import("../utils/create-rule.ts").ImportXPluginDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
export default _default;

View File

@@ -0,0 +1,127 @@
import { makeRe } from 'minimatch';
import { importType, createRule, moduleVisitor, resolve, } from '../utils/index.js';
function normalizeSep(somePath) {
return somePath.split('\\').join('/');
}
function toSteps(somePath) {
return normalizeSep(somePath)
.split('/')
.filter(step => step && step !== '.')
.reduce((acc, step) => {
if (step === '..') {
return acc.slice(0, -1);
}
return [...acc, step];
}, []);
}
const potentialViolationTypes = new Set([
'parent',
'index',
'sibling',
'external',
'internal',
]);
export default createRule({
name: 'no-internal-modules',
meta: {
type: 'suggestion',
docs: {
category: 'Static analysis',
description: 'Forbid importing the submodules of other modules.',
},
schema: [
{
anyOf: [
{
type: 'object',
properties: {
allow: {
type: 'array',
items: {
type: 'string',
},
},
},
additionalProperties: false,
},
{
type: 'object',
properties: {
forbid: {
type: 'array',
items: {
type: 'string',
},
},
},
additionalProperties: false,
},
],
},
],
messages: {
noAllowed: `Reaching to "{{importPath}}" is not allowed.`,
},
},
defaultOptions: [],
create(context) {
const options = context.options[0] || {};
const allowRegexps = (options.allow || [])
.map(p => makeRe(p))
.filter(Boolean);
const forbidRegexps = (options.forbid || [])
.map(p => makeRe(p))
.filter(Boolean);
function reachingAllowed(importPath) {
return allowRegexps.some(re => re.test(importPath));
}
function reachingForbidden(importPath) {
return forbidRegexps.some(re => re.test(importPath));
}
function isAllowViolation(importPath) {
const steps = toSteps(importPath);
const nonScopeSteps = steps.filter(step => step.indexOf('@') !== 0);
if (nonScopeSteps.length <= 1) {
return false;
}
const justSteps = steps.join('/');
if (reachingAllowed(justSteps) || reachingAllowed(`/${justSteps}`)) {
return false;
}
const resolved = resolve(importPath, context);
if (!resolved || reachingAllowed(normalizeSep(resolved))) {
return false;
}
return true;
}
function isForbidViolation(importPath) {
const steps = toSteps(importPath);
const justSteps = steps.join('/');
if (reachingForbidden(justSteps) || reachingForbidden(`/${justSteps}`)) {
return true;
}
const resolved = resolve(importPath, context);
if (resolved && reachingForbidden(normalizeSep(resolved))) {
return true;
}
return false;
}
const isReachViolation = options.forbid
? isForbidViolation
: isAllowViolation;
return moduleVisitor(source => {
const importPath = source.value;
if (potentialViolationTypes.has(importType(importPath, context)) &&
isReachViolation(importPath)) {
context.report({
node: source,
messageId: 'noAllowed',
data: {
importPath,
},
});
}
}, { commonjs: true });
},
});
//# sourceMappingURL=no-internal-modules.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"no-internal-modules.js","sourceRoot":"","sources":["../../src/rules/no-internal-modules.ts"],"names":[],"mappings":"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"}

View File

@@ -0,0 +1,4 @@
import type { TSESLint } from '@typescript-eslint/utils';
export type MessageId = 'noMutable';
declare const _default: TSESLint.RuleModule<"noMutable", [], import("../utils/create-rule.ts").ImportXPluginDocs, TSESLint.RuleListener>;
export default _default;

View File

@@ -0,0 +1,60 @@
import { createRule } from '../utils/index.js';
export default createRule({
name: 'no-mutable-exports',
meta: {
type: 'suggestion',
docs: {
category: 'Helpful warnings',
description: 'Forbid the use of mutable exports with `var` or `let`.',
},
schema: [],
messages: {
noMutable: "Exporting mutable '{{kind}}' binding, use 'const' instead.",
},
},
defaultOptions: [],
create(context) {
function checkDeclaration(node) {
if ('kind' in node && (node.kind === 'var' || node.kind === 'let')) {
context.report({
node,
messageId: 'noMutable',
data: {
kind: node.kind,
},
});
}
}
function checkDeclarationsInScope({ variables }, name) {
for (const variable of variables) {
if (variable.name === name) {
for (const def of variable.defs) {
if (def.type === 'Variable' && def.parent) {
checkDeclaration(def.parent);
}
}
}
}
}
return {
ExportDefaultDeclaration(node) {
const scope = context.sourceCode.getScope(node);
if ('name' in node.declaration) {
checkDeclarationsInScope(scope, node.declaration.name);
}
},
ExportNamedDeclaration(node) {
const scope = context.sourceCode.getScope(node);
if (node.declaration) {
checkDeclaration(node.declaration);
}
else if (!node.source) {
for (const specifier of node.specifiers) {
checkDeclarationsInScope(scope, specifier.local.name);
}
}
},
};
},
});
//# sourceMappingURL=no-mutable-exports.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"no-mutable-exports.js","sourceRoot":"","sources":["../../src/rules/no-mutable-exports.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAI9C,eAAe,UAAU,CAAgB;IACvC,IAAI,EAAE,oBAAoB;IAC1B,IAAI,EAAE;QACJ,IAAI,EAAE,YAAY;QAClB,IAAI,EAAE;YACJ,QAAQ,EAAE,kBAAkB;YAC5B,WAAW,EAAE,wDAAwD;SACtE;QACD,MAAM,EAAE,EAAE;QACV,QAAQ,EAAE;YACR,SAAS,EAAE,4DAA4D;SACxE;KACF;IACD,cAAc,EAAE,EAAE;IAClB,MAAM,CAAC,OAAO;QACZ,SAAS,gBAAgB,CAAC,IAAsC;YAC9D,IAAI,MAAM,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,IAAI,KAAK,KAAK,CAAC,EAAE,CAAC;gBACnE,OAAO,CAAC,MAAM,CAAC;oBACb,IAAI;oBACJ,SAAS,EAAE,WAAW;oBACtB,IAAI,EAAE;wBACJ,IAAI,EAAE,IAAI,CAAC,IAAI;qBAChB;iBACF,CAAC,CAAA;YACJ,CAAC;QACH,CAAC;QAED,SAAS,wBAAwB,CAC/B,EAAE,SAAS,EAAwB,EACnC,IAAY;YAEZ,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;gBACjC,IAAI,QAAQ,CAAC,IAAI,KAAK,IAAI,EAAE,CAAC;oBAC3B,KAAK,MAAM,GAAG,IAAI,QAAQ,CAAC,IAAI,EAAE,CAAC;wBAChC,IAAI,GAAG,CAAC,IAAI,KAAK,UAAU,IAAI,GAAG,CAAC,MAAM,EAAE,CAAC;4BAC1C,gBAAgB,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;wBAC9B,CAAC;oBACH,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO;YACL,wBAAwB,CAAC,IAAI;gBAC3B,MAAM,KAAK,GAAG,OAAO,CAAC,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAA;gBAE/C,IAAI,MAAM,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;oBAC/B,wBAAwB,CAAC,KAAK,EAAE,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAA;gBACxD,CAAC;YACH,CAAC;YACD,sBAAsB,CAAC,IAAI;gBACzB,MAAM,KAAK,GAAG,OAAO,CAAC,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAA;gBAE/C,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;oBACrB,gBAAgB,CAAC,IAAI,CAAC,WAAW,CAAC,CAAA;gBACpC,CAAC;qBAAM,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;oBACxB,KAAK,MAAM,SAAS,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;wBACxC,wBAAwB,CAAC,KAAK,EAAE,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;oBACvD,CAAC;gBACH,CAAC;YACH,CAAC;SACF,CAAA;IACH,CAAC;CACF,CAAC,CAAA"}

View File

@@ -0,0 +1,2 @@
declare const _default: import("@typescript-eslint/utils/ts-eslint").RuleModule<"member", [], import("../utils/create-rule.ts").ImportXPluginDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
export default _default;

View File

@@ -0,0 +1,89 @@
import { importDeclaration, ExportMap, createRule } from '../utils/index.js';
export default createRule({
name: 'no-named-as-default-member',
meta: {
type: 'suggestion',
docs: {
category: 'Helpful warnings',
description: 'Forbid use of exported name as property of default export.',
},
schema: [],
messages: {
member: "Caution: `{{objectName}}` also has a named export `{{propName}}`. Check if you meant to write `import {{{propName}}} from '{{sourcePath}}'` instead.",
},
},
defaultOptions: [],
create(context) {
const fileImports = new Map();
const allPropertyLookups = new Map();
function storePropertyLookup(objectName, propName, node) {
const lookups = allPropertyLookups.get(objectName) || [];
lookups.push({ node, propName });
allPropertyLookups.set(objectName, lookups);
}
return {
ImportDefaultSpecifier(node) {
const declaration = importDeclaration(context, node);
const exportMap = ExportMap.get(declaration.source.value, context);
if (exportMap == null) {
return;
}
if (exportMap.errors.length > 0) {
exportMap.reportErrors(context, declaration);
return;
}
fileImports.set(node.local.name, {
exportMap,
sourcePath: declaration.source.value,
});
},
MemberExpression(node) {
if ('name' in node.object && 'name' in node.property) {
storePropertyLookup(node.object.name, node.property.name, node);
}
},
VariableDeclarator(node) {
const isDestructure = node.id.type === 'ObjectPattern' && node.init?.type === 'Identifier';
if (!isDestructure ||
!node.init ||
!('name' in node.init) ||
!('properties' in node.id)) {
return;
}
const objectName = node.init.name;
for (const prop of node.id.properties) {
if (!('key' in prop) || !('name' in prop.key)) {
continue;
}
storePropertyLookup(objectName, prop.key.name, prop.key);
}
},
'Program:exit'() {
for (const [objectName, lookups] of allPropertyLookups.entries()) {
const fileImport = fileImports.get(objectName);
if (fileImport == null) {
continue;
}
for (const { propName, node } of lookups) {
if (propName === 'default') {
continue;
}
if (!fileImport.exportMap.namespace.has(propName)) {
continue;
}
context.report({
node,
messageId: 'member',
data: {
objectName,
propName,
sourcePath: fileImport.sourcePath,
},
});
}
}
},
};
},
});
//# sourceMappingURL=no-named-as-default-member.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"no-named-as-default-member.js","sourceRoot":"","sources":["../../src/rules/no-named-as-default-member.ts"],"names":[],"mappings":"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"}

View File

@@ -0,0 +1,3 @@
export type MessageId = 'default';
declare const _default: import("@typescript-eslint/utils/ts-eslint").RuleModule<"default", [], import("../utils/create-rule.ts").ImportXPluginDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
export default _default;

View File

@@ -0,0 +1,56 @@
import { importDeclaration, ExportMap, createRule } from '../utils/index.js';
export default createRule({
name: 'no-named-as-default',
meta: {
type: 'problem',
docs: {
category: 'Helpful warnings',
description: 'Forbid use of exported name as identifier of default export.',
},
schema: [],
messages: {
default: "Using exported name '{{name}}' as identifier for default export.",
},
},
defaultOptions: [],
create(context) {
function createCheckDefault(nameKey) {
return function checkDefault(defaultSpecifier) {
const nameValue = defaultSpecifier[nameKey].name;
if (nameValue === 'default') {
return;
}
const declaration = importDeclaration(context, defaultSpecifier);
const exportMapOfImported = ExportMap.get(declaration.source.value, context);
if (exportMapOfImported == null) {
return;
}
if (exportMapOfImported.errors.length > 0) {
exportMapOfImported.reportErrors(context, declaration);
return;
}
if (!exportMapOfImported.hasDefault) {
return;
}
if (!exportMapOfImported.has(nameValue)) {
return;
}
if (exportMapOfImported.exports.has('default') &&
exportMapOfImported.exports.has(nameValue)) {
context.report({
node: defaultSpecifier,
messageId: 'default',
data: {
name: nameValue,
},
});
}
};
}
return {
ImportDefaultSpecifier: createCheckDefault('local'),
ExportDefaultSpecifier: createCheckDefault('exported'),
};
},
});
//# sourceMappingURL=no-named-as-default.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"no-named-as-default.js","sourceRoot":"","sources":["../../src/rules/no-named-as-default.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAI5E,eAAe,UAAU,CAAgB;IACvC,IAAI,EAAE,qBAAqB;IAC3B,IAAI,EAAE;QACJ,IAAI,EAAE,SAAS;QACf,IAAI,EAAE;YACJ,QAAQ,EAAE,kBAAkB;YAC5B,WAAW,EACT,8DAA8D;SACjE;QACD,MAAM,EAAE,EAAE;QACV,QAAQ,EAAE;YACR,OAAO,EACL,kEAAkE;SACrE;KACF;IACD,cAAc,EAAE,EAAE;IAClB,MAAM,CAAC,OAAO;QACZ,SAAS,kBAAkB,CAAC,OAA6B;YACvD,OAAO,SAAS,YAAY,CAC1B,gBAAiD;gBAKjD,MAAM,SAAS,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAC,IAAc,CAAA;gBAE1D,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;oBAC5B,OAAM;gBACR,CAAC;gBAED,MAAM,WAAW,GAAG,iBAAiB,CAAC,OAAO,EAAE,gBAAgB,CAAC,CAAA;gBAEhE,MAAM,mBAAmB,GAAG,SAAS,CAAC,GAAG,CACvC,WAAW,CAAC,MAAM,CAAC,KAAK,EACxB,OAAO,CACR,CAAA;gBAED,IAAI,mBAAmB,IAAI,IAAI,EAAE,CAAC;oBAChC,OAAM;gBACR,CAAC;gBAED,IAAI,mBAAmB,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBAC1C,mBAAmB,CAAC,YAAY,CAAC,OAAO,EAAE,WAAW,CAAC,CAAA;oBACtD,OAAM;gBACR,CAAC;gBAED,IAAI,CAAC,mBAAmB,CAAC,UAAU,EAAE,CAAC;oBAGpC,OAAM;gBACR,CAAC;gBAED,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;oBAExC,OAAM;gBACR,CAAC;gBAED,IACE,mBAAmB,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC;oBAC1C,mBAAmB,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,EAC1C,CAAC;oBACD,OAAO,CAAC,MAAM,CAAC;wBACb,IAAI,EAAE,gBAAgB;wBACtB,SAAS,EAAE,SAAS;wBACpB,IAAI,EAAE;4BACJ,IAAI,EAAE,SAAS;yBAChB;qBACF,CAAC,CAAA;gBACJ,CAAC;YACH,CAAC,CAAA;QACH,CAAC;QACD,OAAO;YACL,sBAAsB,EAAE,kBAAkB,CAAC,OAAO,CAAC;YACnD,sBAAsB,EAAE,kBAAkB,CAAC,UAAU,CAAC;SACvD,CAAA;IACH,CAAC;CACF,CAAC,CAAA"}

View File

@@ -0,0 +1,2 @@
declare const _default: import("@typescript-eslint/utils/ts-eslint").RuleModule<"default", [], import("../utils/create-rule.ts").ImportXPluginDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
export default _default;

View File

@@ -0,0 +1,40 @@
import { createRule, getValue } from '../utils/index.js';
export default createRule({
name: 'no-named-default',
meta: {
type: 'suggestion',
docs: {
category: 'Style guide',
description: 'Forbid named default exports.',
},
schema: [],
messages: {
default: `Use default import syntax to import '{{importName}}'.`,
},
},
defaultOptions: [],
create(context) {
return {
ImportDeclaration(node) {
for (const im of node.specifiers) {
if ('importKind' in im &&
(im.importKind === 'type' ||
im.importKind === 'typeof')) {
continue;
}
if (im.type === 'ImportSpecifier' &&
getValue(im.imported) === 'default') {
context.report({
node: im.local,
messageId: 'default',
data: {
importName: im.local.name,
},
});
}
}
},
};
},
});
//# sourceMappingURL=no-named-default.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"no-named-default.js","sourceRoot":"","sources":["../../src/rules/no-named-default.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAIxD,eAAe,UAAU,CAAgB;IACvC,IAAI,EAAE,kBAAkB;IACxB,IAAI,EAAE;QACJ,IAAI,EAAE,YAAY;QAClB,IAAI,EAAE;YACJ,QAAQ,EAAE,aAAa;YACvB,WAAW,EAAE,+BAA+B;SAC7C;QACD,MAAM,EAAE,EAAE;QACV,QAAQ,EAAE;YACR,OAAO,EAAE,uDAAuD;SACjE;KACF;IACD,cAAc,EAAE,EAAE;IAClB,MAAM,CAAC,OAAO;QACZ,OAAO;YACL,iBAAiB,CAAC,IAAI;gBACpB,KAAK,MAAM,EAAE,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;oBACjC,IACE,YAAY,IAAI,EAAE;wBAClB,CAAC,EAAE,CAAC,UAAU,KAAK,MAAM;4BAEvB,EAAE,CAAC,UAAU,KAAK,QAAQ,CAAC,EAC7B,CAAC;wBACD,SAAQ;oBACV,CAAC;oBAED,IACE,EAAE,CAAC,IAAI,KAAK,iBAAiB;wBAC7B,QAAQ,CAAC,EAAE,CAAC,QAAQ,CAAC,KAAK,SAAS,EACnC,CAAC;wBACD,OAAO,CAAC,MAAM,CAAC;4BACb,IAAI,EAAE,EAAE,CAAC,KAAK;4BACd,SAAS,EAAE,SAAS;4BACpB,IAAI,EAAE;gCACJ,UAAU,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI;6BAC1B;yBACF,CAAC,CAAA;oBACJ,CAAC;gBACH,CAAC;YACH,CAAC;SACF,CAAA;IACH,CAAC;CACF,CAAC,CAAA"}

View File

@@ -0,0 +1,2 @@
declare const _default: import("@typescript-eslint/utils/ts-eslint").RuleModule<"noAllowed", [], import("../utils/create-rule.ts").ImportXPluginDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
export default _default;

View File

@@ -0,0 +1,36 @@
import { createRule, getValue, sourceType } from '../utils/index.js';
export default createRule({
name: 'no-named-export',
meta: {
type: 'suggestion',
docs: {
category: 'Style guide',
description: 'Forbid named exports.',
},
schema: [],
messages: {
noAllowed: 'Named exports are not allowed.',
},
},
defaultOptions: [],
create(context) {
if (sourceType(context) !== 'module') {
return {};
}
return {
ExportAllDeclaration(node) {
context.report({ node, messageId: 'noAllowed' });
},
ExportNamedDeclaration(node) {
if (node.specifiers.length === 0) {
return context.report({ node, messageId: 'noAllowed' });
}
const someNamed = node.specifiers.some(specifier => getValue(specifier.exported) !== 'default');
if (someNamed) {
context.report({ node, messageId: 'noAllowed' });
}
},
};
},
});
//# sourceMappingURL=no-named-export.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"no-named-export.js","sourceRoot":"","sources":["../../src/rules/no-named-export.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAEpE,eAAe,UAAU,CAAC;IACxB,IAAI,EAAE,iBAAiB;IACvB,IAAI,EAAE;QACJ,IAAI,EAAE,YAAY;QAClB,IAAI,EAAE;YACJ,QAAQ,EAAE,aAAa;YACvB,WAAW,EAAE,uBAAuB;SACrC;QACD,MAAM,EAAE,EAAE;QACV,QAAQ,EAAE;YACR,SAAS,EAAE,gCAAgC;SAC5C;KACF;IACD,cAAc,EAAE,EAAE;IAClB,MAAM,CAAC,OAAO;QAEZ,IAAI,UAAU,CAAC,OAAO,CAAC,KAAK,QAAQ,EAAE,CAAC;YACrC,OAAO,EAAE,CAAA;QACX,CAAC;QAED,OAAO;YACL,oBAAoB,CAAC,IAAI;gBACvB,OAAO,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,CAAC,CAAA;YAClD,CAAC;YAED,sBAAsB,CAAC,IAAI;gBACzB,IAAI,IAAI,CAAC,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBACjC,OAAO,OAAO,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,CAAC,CAAA;gBACzD,CAAC;gBAED,MAAM,SAAS,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,CACpC,SAAS,CAAC,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,QAAQ,CAAC,KAAK,SAAS,CACxD,CAAA;gBACD,IAAI,SAAS,EAAE,CAAC;oBACd,OAAO,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,CAAC,CAAA;gBAClD,CAAC;YACH,CAAC;SACF,CAAA;IACH,CAAC;CACF,CAAC,CAAA"}

View File

@@ -0,0 +1,7 @@
import type { TSESLint } from '@typescript-eslint/utils';
export type MessageId = 'noNamespace';
export interface Options {
ignore?: string[];
}
declare const _default: TSESLint.RuleModule<"noNamespace", [(Options | undefined)?], import("../utils/create-rule.ts").ImportXPluginDocs, TSESLint.RuleListener>;
export default _default;

View File

@@ -0,0 +1,136 @@
import { minimatch } from 'minimatch';
import { createRule } from '../utils/index.js';
export default createRule({
name: 'no-namespace',
meta: {
type: 'suggestion',
docs: {
category: 'Style guide',
description: 'Forbid namespace (a.k.a. "wildcard" `*`) imports.',
},
fixable: 'code',
schema: [
{
type: 'object',
properties: {
ignore: {
type: 'array',
items: {
type: 'string',
},
uniqueItems: true,
},
},
},
],
messages: {
noNamespace: 'Unexpected namespace import.',
},
},
defaultOptions: [],
create(context) {
const firstOption = context.options[0] || {};
const ignoreGlobs = firstOption.ignore;
return {
ImportNamespaceSpecifier(node) {
if (ignoreGlobs?.find(glob => minimatch(node.parent.source.value, glob, {
matchBase: true,
nocomment: true,
}))) {
return;
}
const scopeVariables = context.sourceCode.getScope(node).variables;
const namespaceVariable = scopeVariables.find(variable => variable.defs[0].node === node);
const namespaceReferences = namespaceVariable.references;
const namespaceIdentifiers = namespaceReferences.map(reference => reference.identifier);
const canFix = namespaceIdentifiers.length > 0 &&
!usesNamespaceAsObject(namespaceIdentifiers);
context.report({
node,
messageId: `noNamespace`,
fix: canFix
? fixer => {
const scopeManager = context.sourceCode.scopeManager;
const fixes = [];
const importNameConflicts = {};
for (const identifier of namespaceIdentifiers) {
const parent = identifier.parent;
if (parent && parent.type === 'MemberExpression') {
const importName = getMemberPropertyName(parent);
const localConflicts = getVariableNamesInScope(scopeManager, parent);
if (importNameConflicts[importName]) {
for (const c of localConflicts)
importNameConflicts[importName].add(c);
}
else {
importNameConflicts[importName] = localConflicts;
}
}
}
const importNames = Object.keys(importNameConflicts);
const importLocalNames = generateLocalNames(importNames, importNameConflicts, namespaceVariable.name);
const namedImportSpecifiers = importNames.map(importName => importName === importLocalNames[importName]
? importName
: `${importName} as ${importLocalNames[importName]}`);
fixes.push(fixer.replaceText(node, `{ ${namedImportSpecifiers.join(', ')} }`));
for (const identifier of namespaceIdentifiers) {
const parent = identifier.parent;
if (parent && parent.type === 'MemberExpression') {
const importName = getMemberPropertyName(parent);
fixes.push(fixer.replaceText(parent, importLocalNames[importName]));
}
}
return fixes;
}
: null,
});
},
};
},
});
function usesNamespaceAsObject(namespaceIdentifiers) {
return !namespaceIdentifiers.every(identifier => {
const parent = identifier.parent;
return (parent &&
parent.type === 'MemberExpression' &&
(parent.property.type === 'Identifier' ||
parent.property.type === 'Literal'));
});
}
function getMemberPropertyName(memberExpression) {
return memberExpression.property.type === 'Identifier'
? memberExpression.property.name
: memberExpression.property.value;
}
function getVariableNamesInScope(scopeManager, node) {
let currentNode = node;
let scope = scopeManager.acquire(currentNode);
while (scope == null) {
currentNode = currentNode.parent;
scope = scopeManager.acquire(currentNode, true);
}
return new Set([...scope.variables, ...scope.upper.variables].map(variable => variable.name));
}
function generateLocalNames(names, nameConflicts, namespaceName) {
const localNames = {};
for (const name of names) {
let localName;
if (!nameConflicts[name].has(name)) {
localName = name;
}
else if (nameConflicts[name].has(`${namespaceName}_${name}`)) {
for (let i = 1; i < Number.POSITIVE_INFINITY; i++) {
if (!nameConflicts[name].has(`${namespaceName}_${name}_${i}`)) {
localName = `${namespaceName}_${name}_${i}`;
break;
}
}
}
else {
localName = `${namespaceName}_${name}`;
}
localNames[name] = localName;
}
return localNames;
}
//# sourceMappingURL=no-namespace.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"no-namespace.js","sourceRoot":"","sources":["../../src/rules/no-namespace.ts"],"names":[],"mappings":"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"}

View File

@@ -0,0 +1,6 @@
export interface Options {
allow?: string[];
}
export type MessageId = 'builtin';
declare const _default: import("@typescript-eslint/utils/ts-eslint").RuleModule<"builtin", [(Options | undefined)?], import("../utils/create-rule.ts").ImportXPluginDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
export default _default;

View File

@@ -0,0 +1,48 @@
import { importType, createRule, moduleVisitor } from '../utils/index.js';
export default createRule({
name: 'no-nodejs-modules',
meta: {
type: 'suggestion',
docs: {
category: 'Module systems',
description: 'Forbid Node.js builtin modules.',
},
schema: [
{
type: 'object',
properties: {
allow: {
type: 'array',
uniqueItems: true,
items: {
type: 'string',
},
},
},
additionalProperties: false,
},
],
messages: {
builtin: 'Do not import Node.js builtin module "{{moduleName}}"',
},
},
defaultOptions: [],
create(context) {
const options = context.options[0] || {};
const allowed = options.allow || [];
return moduleVisitor((source, node) => {
const moduleName = source.value;
if (!allowed.includes(moduleName) &&
importType(moduleName, context) === 'builtin') {
context.report({
node,
messageId: 'builtin',
data: {
moduleName,
},
});
}
}, { commonjs: true });
},
});
//# sourceMappingURL=no-nodejs-modules.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"no-nodejs-modules.js","sourceRoot":"","sources":["../../src/rules/no-nodejs-modules.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AAQzE,eAAe,UAAU,CAAwB;IAC/C,IAAI,EAAE,mBAAmB;IACzB,IAAI,EAAE;QACJ,IAAI,EAAE,YAAY;QAClB,IAAI,EAAE;YACJ,QAAQ,EAAE,gBAAgB;YAC1B,WAAW,EAAE,iCAAiC;SAC/C;QACD,MAAM,EAAE;YACN;gBACE,IAAI,EAAE,QAAQ;gBACd,UAAU,EAAE;oBACV,KAAK,EAAE;wBACL,IAAI,EAAE,OAAO;wBACb,WAAW,EAAE,IAAI;wBACjB,KAAK,EAAE;4BACL,IAAI,EAAE,QAAQ;yBACf;qBACF;iBACF;gBACD,oBAAoB,EAAE,KAAK;aAC5B;SACF;QACD,QAAQ,EAAE;YACR,OAAO,EAAE,uDAAuD;SACjE;KACF;IACD,cAAc,EAAE,EAAE;IAClB,MAAM,CAAC,OAAO;QACZ,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,EAAE,CAAA;QACxC,MAAM,OAAO,GAAG,OAAO,CAAC,KAAK,IAAI,EAAE,CAAA;QAEnC,OAAO,aAAa,CAClB,CAAC,MAAM,EAAE,IAAI,EAAE,EAAE;YACf,MAAM,UAAU,GAAG,MAAM,CAAC,KAAK,CAAA;YAC/B,IACE,CAAC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC;gBAC7B,UAAU,CAAC,UAAU,EAAE,OAAO,CAAC,KAAK,SAAS,EAC7C,CAAC;gBACD,OAAO,CAAC,MAAM,CAAC;oBACb,IAAI;oBACJ,SAAS,EAAE,SAAS;oBACpB,IAAI,EAAE;wBACJ,UAAU;qBACX;iBACF,CAAC,CAAA;YACJ,CAAC;QACH,CAAC,EACD,EAAE,QAAQ,EAAE,IAAI,EAAE,CACnB,CAAA;IACH,CAAC;CACF,CAAC,CAAA"}

View File

@@ -0,0 +1,3 @@
import type { ModuleOptions } from '../utils/index.js';
declare const _default: import("@typescript-eslint/utils/ts-eslint").RuleModule<"noAllowed", [(ModuleOptions | undefined)?], import("../utils/create-rule.ts").ImportXPluginDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
export default _default;

Some files were not shown because too many files have changed in this diff Show More