eslint-plugin-n
Advanced tools
Comparing version 16.6.2 to 17.0.0-0
@@ -18,10 +18,10 @@ /** | ||
function getExistingExtensions(filePath) { | ||
const basename = path.basename(filePath, path.extname(filePath)) | ||
const directory = path.dirname(filePath) | ||
const extension = path.extname(filePath) | ||
const basename = path.basename(filePath, extension) | ||
try { | ||
return fs | ||
.readdirSync(path.dirname(filePath)) | ||
.filter( | ||
filename => | ||
path.basename(filename, path.extname(filename)) === basename | ||
) | ||
.readdirSync(directory) | ||
.filter(filename => filename.startsWith(`${basename}.`)) | ||
.map(filename => path.extname(filename)) | ||
@@ -78,43 +78,52 @@ } catch (_error) { | ||
// Get extension. | ||
const originalExt = path.extname(name) | ||
const existingExts = getExistingExtensions(filePath) | ||
const ext = path.extname(filePath) || existingExts.join(" or ") | ||
const style = overrideStyle[ext] || defaultStyle | ||
const currentExt = path.extname(name) | ||
const actualExt = path.extname(filePath) | ||
const style = overrideStyle[actualExt] || defaultStyle | ||
const expectedExt = mapTypescriptExtension( | ||
context, | ||
filePath, | ||
actualExt | ||
) | ||
// Verify. | ||
if (style === "always" && ext !== originalExt) { | ||
const fileExtensionToAdd = mapTypescriptExtension( | ||
context, | ||
filePath, | ||
ext | ||
) | ||
if (style === "always" && currentExt !== expectedExt) { | ||
context.report({ | ||
node, | ||
messageId: "requireExt", | ||
data: { ext: fileExtensionToAdd }, | ||
data: { ext: expectedExt }, | ||
fix(fixer) { | ||
if (existingExts.length !== 1) { | ||
return null | ||
} | ||
const index = node.range[1] - 1 | ||
return fixer.insertTextBeforeRange( | ||
[index, index], | ||
fileExtensionToAdd | ||
expectedExt | ||
) | ||
}, | ||
}) | ||
} else if (style === "never" && ext === originalExt) { | ||
} | ||
if ( | ||
style === "never" && | ||
currentExt !== "" && | ||
expectedExt !== "" && | ||
currentExt === expectedExt | ||
) { | ||
const otherExtensions = getExistingExtensions(filePath) | ||
let fix = fixer => { | ||
const index = name.lastIndexOf(currentExt) | ||
const start = node.range[0] + 1 + index | ||
const end = start + currentExt.length | ||
return fixer.removeRange([start, end]) | ||
} | ||
if (otherExtensions.length > 1) { | ||
fix = undefined | ||
} | ||
context.report({ | ||
node, | ||
messageId: "forbidExt", | ||
data: { ext }, | ||
fix(fixer) { | ||
if (existingExts.length !== 1) { | ||
return null | ||
} | ||
const index = name.lastIndexOf(ext) | ||
const start = node.range[0] + 1 + index | ||
const end = start + ext.length | ||
return fixer.removeRange([start, end]) | ||
}, | ||
data: { ext: currentExt }, | ||
fix, | ||
}) | ||
@@ -121,0 +130,0 @@ } |
@@ -12,7 +12,2 @@ /** | ||
const path = require("path") | ||
const resolve = require("resolve") | ||
const { pathToFileURL, fileURLToPath } = require("url") | ||
const { | ||
defaultResolve: importResolve, | ||
} = require("../converted-esm/import-meta-resolve") | ||
const getPackageJson = require("../util/get-package-json") | ||
@@ -33,3 +28,4 @@ const mergeVisitorsInPlace = require("../util/merge-visitors-in-place") | ||
"dns", | ||
/* "domain", */ "events", | ||
/* "domain", */ | ||
"events", | ||
"fs", | ||
@@ -42,3 +38,4 @@ "http", | ||
"path", | ||
/* "punycode", */ "querystring", | ||
/* "punycode", */ | ||
"querystring", | ||
"readline", | ||
@@ -138,18 +135,4 @@ "repl", | ||
let resolved = "" | ||
const moduleId = `${name}/` | ||
try { | ||
resolved = resolve.sync(moduleId, { | ||
basedir: dirPath, | ||
}) | ||
} catch (_error) { | ||
try { | ||
const { url } = importResolve(moduleId, { | ||
parentURL: pathToFileURL(dirPath).href, | ||
}) | ||
resolved = fileURLToPath(url) | ||
} catch (_error) { | ||
continue | ||
} | ||
if (target.filePath == null) { | ||
continue | ||
} | ||
@@ -163,3 +146,3 @@ | ||
name: path | ||
.relative(dirPath, resolved) | ||
.relative(dirPath, target.filePath) | ||
.replace(BACK_SLASH, "/"), | ||
@@ -166,0 +149,0 @@ }, |
@@ -14,2 +14,17 @@ /** | ||
/** | ||
* Reports a missing file from ImportTarget | ||
* @param {RuleContext} context - A context to report. | ||
* @param {import('../util/import-target.js')} target - A list of target information to check. | ||
* @returns {void} | ||
*/ | ||
function markMissing(context, target) { | ||
context.report({ | ||
node: target.node, | ||
loc: target.node.loc, | ||
messageId: "notFound", | ||
data: target, | ||
}) | ||
} | ||
/** | ||
* Checks whether or not each requirement target exists. | ||
@@ -21,3 +36,3 @@ * | ||
* @param {RuleContext} context - A context to report. | ||
* @param {ImportTarget[]} targets - A list of target information to check. | ||
* @param {import('../util/import-target.js')[]} targets - A list of target information to check. | ||
* @returns {void} | ||
@@ -29,10 +44,22 @@ */ | ||
for (const target of targets) { | ||
const missingModule = | ||
if ( | ||
target.moduleName != null && | ||
!allowed.has(target.moduleName) && | ||
target.filePath == null | ||
) { | ||
markMissing(context, target) | ||
continue | ||
} | ||
let missingFile = target.moduleName == null && !exists(target.filePath) | ||
if (target.moduleName != null) { | ||
continue | ||
} | ||
let missingFile = | ||
target.filePath == null ? false : !exists(target.filePath) | ||
if (missingFile && isTypescript(context)) { | ||
const parsed = path.parse(target.filePath) | ||
const pathWithoutExt = path.resolve(parsed.dir, parsed.name) | ||
const reversedExts = mapTypescriptExtension( | ||
@@ -45,4 +72,3 @@ context, | ||
const reversedPaths = reversedExts.map( | ||
reversedExt => | ||
path.resolve(parsed.dir, parsed.name) + reversedExt | ||
reversedExt => pathWithoutExt + reversedExt | ||
) | ||
@@ -54,9 +80,5 @@ missingFile = reversedPaths.every( | ||
} | ||
if (missingModule || missingFile) { | ||
context.report({ | ||
node: target.node, | ||
loc: target.node.loc, | ||
messageId: "notFound", | ||
data: target, | ||
}) | ||
if (missingFile) { | ||
markMissing(context, target) | ||
} | ||
@@ -63,0 +85,0 @@ } |
@@ -62,3 +62,3 @@ /** | ||
} | ||
const relativeTargetPath = toRelative(target.filePath) | ||
const relativeTargetPath = toRelative(target.filePath ?? "") | ||
return ( | ||
@@ -74,2 +74,3 @@ relativeTargetPath !== "" && | ||
!allowed.has(target.moduleName) | ||
if (isPrivateFile() || isDevPackage()) { | ||
@@ -76,0 +77,0 @@ context.report({ |
@@ -41,2 +41,6 @@ /** | ||
module.exports = function exists(filePath) { | ||
if (filePath == null) { | ||
return false | ||
} | ||
let result = cache.get(filePath) | ||
@@ -43,0 +47,0 @@ if (result == null) { |
@@ -7,4 +7,23 @@ /** | ||
const DEFAULT_VALUE = Object.freeze([".js", ".json", ".node"]) | ||
const { getTSConfigForContext } = require("./get-tsconfig") | ||
const isTypescript = require("./is-typescript") | ||
const DEFAULT_JS_VALUE = Object.freeze([ | ||
".js", | ||
".json", | ||
".node", | ||
".mjs", | ||
".cjs", | ||
]) | ||
const DEFAULT_TS_VALUE = Object.freeze([ | ||
".js", | ||
".ts", | ||
".mjs", | ||
".mts", | ||
".cjs", | ||
".cts", | ||
".json", | ||
".node", | ||
]) | ||
/** | ||
@@ -17,3 +36,3 @@ * Gets `tryExtensions` property from a given option object. | ||
function get(option) { | ||
if (option && option.tryExtensions && Array.isArray(option.tryExtensions)) { | ||
if (Array.isArray(option?.tryExtensions)) { | ||
return option.tryExtensions.map(String) | ||
@@ -29,3 +48,3 @@ } | ||
* 2. This checks `settings.n` | `settings.node` property, then returns it if exists. | ||
* 3. This returns `[".js", ".json", ".node"]`. | ||
* 3. This returns `[".js", ".json", ".node", ".mjs", ".cjs"]`. | ||
* | ||
@@ -36,9 +55,19 @@ * @param {RuleContext} context - The rule context. | ||
module.exports = function getTryExtensions(context, optionIndex = 0) { | ||
return ( | ||
get(context.options && context.options[optionIndex]) || | ||
get( | ||
context.settings && (context.settings.n || context.settings.node) | ||
) || | ||
DEFAULT_VALUE | ||
) | ||
const configured = | ||
get(context.options?.[optionIndex]) ?? | ||
get(context.settings?.n) ?? | ||
get(context.settings?.node) | ||
if (configured != null) { | ||
return configured | ||
} | ||
if (isTypescript(context)) { | ||
const tsconfig = getTSConfigForContext(context) | ||
if (tsconfig?.config?.compilerOptions?.allowImportingTsExtensions) { | ||
return DEFAULT_TS_VALUE | ||
} | ||
} | ||
return DEFAULT_JS_VALUE | ||
} | ||
@@ -45,0 +74,0 @@ |
@@ -20,3 +20,3 @@ "use strict" | ||
* @param {string} filename - The path to the file we need to find the tsconfig.json of | ||
* @returns {import("get-tsconfig").TsConfigResult} | ||
* @returns {import("get-tsconfig").TsConfigResult | null} | ||
*/ | ||
@@ -27,7 +27,25 @@ function getTSConfigForFile(filename) { | ||
/** | ||
* Attempts to get the ExtensionMap from the tsconfig of a given file. | ||
* | ||
* @param {import('eslint').Rule.RuleContext} context - The current eslint context | ||
* @returns {import("get-tsconfig").TsConfigResult | null} | ||
*/ | ||
function getTSConfigForContext(context) { | ||
// TODO: remove context.get(PhysicalFilename|Filename) when dropping eslint < v10 | ||
const filename = | ||
context.physicalFilename ?? | ||
context.getPhysicalFilename?.() ?? | ||
context.filename ?? | ||
context.getFilename?.() | ||
return getTSConfigForFile(filename) | ||
} | ||
module.exports = { | ||
getTSConfig, | ||
getTSConfigForFile, | ||
getTSConfigForContext, | ||
} | ||
module.exports.schema = { type: "string" } |
"use strict" | ||
const { getTSConfig, getTSConfigForFile } = require("./get-tsconfig") | ||
const { getTSConfig, getTSConfigForContext } = require("./get-tsconfig") | ||
@@ -35,5 +35,10 @@ const DEFAULT_MAPPING = normalise([ | ||
/** | ||
* @param {Record<string, string>} typescriptExtensionMap A forward extension mapping | ||
* @returns {ExtensionMap} | ||
*/ | ||
function normalise(typescriptExtensionMap) { | ||
const forward = {} | ||
const backward = {} | ||
for (const [typescript, javascript] of typescriptExtensionMap) { | ||
@@ -47,2 +52,3 @@ forward[typescript] = javascript | ||
} | ||
return { forward, backward } | ||
@@ -94,7 +100,7 @@ } | ||
* | ||
* @param {string} filename - The filename we're getting from | ||
* @param {import('eslint').Rule.RuleContext} context - The current file context | ||
* @returns {ExtensionMap} The `typescriptExtensionMap` value, or `null`. | ||
*/ | ||
function getFromTSConfigFromFile(filename) { | ||
return getMappingFromTSConfig(getTSConfigForFile(filename)?.config) | ||
function getFromTSConfigFromFile(context) { | ||
return getMappingFromTSConfig(getTSConfigForContext(context)?.config) | ||
} | ||
@@ -115,14 +121,9 @@ | ||
* @param {import("eslint").Rule.RuleContext} context - The rule context. | ||
* @returns {string[]} A list of extensions. | ||
* @returns {ExtensionMap} A list of extensions. | ||
*/ | ||
module.exports = function getTypescriptExtensionMap(context) { | ||
const filename = | ||
context.physicalFilename ?? | ||
context.getPhysicalFilename?.() ?? | ||
context.filename ?? | ||
context.getFilename?.() // TODO: remove context.get(PhysicalFilename|Filename) when dropping eslint < v10 | ||
return ( | ||
get(context.options?.[0]) || | ||
get(context.settings?.n ?? context.settings?.node) || | ||
getFromTSConfigFromFile(filename) || | ||
getFromTSConfigFromFile(context) || | ||
PRESERVE_MAPPING | ||
@@ -129,0 +130,0 @@ ) |
@@ -7,94 +7,53 @@ /** | ||
const path = require("path") | ||
const { pathToFileURL, fileURLToPath } = require("url") | ||
require("util").inspect.defaultOptions.depth = null | ||
const { resolve } = require("path") | ||
const isBuiltin = require("is-builtin-module") | ||
const resolve = require("resolve") | ||
const { | ||
defaultResolve: importResolve, | ||
} = require("../converted-esm/import-meta-resolve") | ||
const resolver = require("enhanced-resolve") | ||
const isTypescript = require("./is-typescript") | ||
const { getTSConfigForContext } = require("./get-tsconfig.js") | ||
const getTypescriptExtensionMap = require("./get-typescript-extension-map") | ||
function removeTrailWildcard(input) { | ||
if (Array.isArray(input)) { | ||
return [...input].map(removeTrailWildcard) | ||
} | ||
return input.replace(/[/\\*]+$/, "") | ||
} | ||
/** | ||
* Resolve the given id to file paths. | ||
* @param {boolean} isModule The flag which indicates this id is a module. | ||
* @param {string} id The id to resolve. | ||
* @param {object} options The options of node-resolve module. | ||
* It requires `options.basedir`. | ||
* @param {'import' | 'require'} moduleType - whether the target was require-ed or imported | ||
* @returns {string|null} The resolved path. | ||
* Initialize this instance. | ||
* @param {import('eslint').Rule.RuleContext} context - The context for the import origin. | ||
* @returns {import('enhanced-resolve').ResolveOptions['alias'] | undefined} | ||
*/ | ||
function getFilePath(isModule, id, options, moduleType) { | ||
if (moduleType === "import") { | ||
const paths = | ||
options.paths && options.paths.length > 0 | ||
? options.paths.map(p => path.resolve(process.cwd(), p)) | ||
: [options.basedir] | ||
for (const aPath of paths) { | ||
try { | ||
const { url } = importResolve(id, { | ||
parentURL: pathToFileURL(path.join(aPath, "dummy-file.mjs")) | ||
.href, | ||
conditions: ["node", "import", "require"], | ||
}) | ||
function getTSConfigAliases(context) { | ||
const tsConfig = getTSConfigForContext(context) | ||
if (url) { | ||
return fileURLToPath(url) | ||
} | ||
} catch (e) { | ||
continue | ||
} | ||
} | ||
const paths = tsConfig?.config?.compilerOptions?.paths | ||
if (isModule) { | ||
return null | ||
} | ||
return path.resolve( | ||
(options.paths && options.paths[0]) || options.basedir, | ||
id | ||
) | ||
} else { | ||
try { | ||
return resolve.sync(id, options) | ||
} catch (_err) { | ||
try { | ||
const { url } = importResolve(id, { | ||
parentURL: pathToFileURL( | ||
path.join(options.basedir, "dummy-file.js") | ||
).href, | ||
conditions: ["node", "require"], | ||
}) | ||
return fileURLToPath(url) | ||
} catch (err) { | ||
if (isModule) { | ||
return null | ||
} | ||
return path.resolve(options.basedir, id) | ||
} | ||
} | ||
if (paths == null) { | ||
return | ||
} | ||
} | ||
function isNodeModule(name, options) { | ||
try { | ||
return require.resolve(name, options).startsWith(path.sep) | ||
} catch { | ||
return false | ||
} | ||
return Object.entries(paths).map(([name, alias]) => ({ | ||
name: removeTrailWildcard(name), | ||
alias: removeTrailWildcard(alias), | ||
})) | ||
} | ||
/** | ||
* Gets the module name of a given path. | ||
* | ||
* e.g. `eslint/lib/ast-utils` -> `eslint` | ||
* | ||
* @param {string} nameOrPath - A path to get. | ||
* @returns {string} The module name of the path. | ||
* @typedef {Object} Options | ||
* @property {string[]} [extensions] | ||
* @property {string[]} [paths] | ||
* @property {string} basedir | ||
*/ | ||
function getModuleName(nameOrPath) { | ||
let end = nameOrPath.indexOf("/") | ||
if (end !== -1 && nameOrPath[0] === "@") { | ||
end = nameOrPath.indexOf("/", 1 + end) | ||
} | ||
/** | ||
* @typedef { 'unknown' | 'relative' | 'absolute' | 'node' | 'npm' | 'http' } ModuleType | ||
* @typedef { 'import' | 'require' | 'type' } ModuleStyle | ||
*/ | ||
return end === -1 ? nameOrPath : nameOrPath.slice(0, end) | ||
function trimAfter(string, matcher, count = 1) { | ||
return string.split(matcher).slice(0, count).join(matcher) | ||
} | ||
@@ -108,13 +67,18 @@ | ||
* Initialize this instance. | ||
* @param {ASTNode} node - The node of a `require()` or a module declaraiton. | ||
* @param {import('eslint').Rule.RuleContext} context - The context for the import origin. | ||
* @param {import('eslint').Rule.Node} node - The node of a `require()` or a module declaraiton. | ||
* @param {string} name - The name of an import target. | ||
* @param {object} options - The options of `node-resolve` module. | ||
* @param {Options} options - The options of `enhanced-resolve` module. | ||
* @param {'import' | 'require'} moduleType - whether the target was require-ed or imported | ||
*/ | ||
constructor(node, name, options, moduleType) { | ||
const isModule = !/^(?:[./\\]|\w+:)/u.test(name) | ||
constructor(context, node, name, options, moduleType) { | ||
/** | ||
* The context for the import origin | ||
* @type {import('eslint').Rule.Node} | ||
*/ | ||
this.context = context | ||
/** | ||
* The node of a `require()` or a module declaraiton. | ||
* @type {ASTNode} | ||
* @type {import('eslint').Rule.Node} | ||
*/ | ||
@@ -130,25 +94,18 @@ this.node = node | ||
/** | ||
* What type of module is this | ||
* @type {'unknown'|'relative'|'absolute'|'node'|'npm'|'http'|void} | ||
* The import target options. | ||
* @type {Options} | ||
*/ | ||
this.moduleType = "unknown" | ||
this.options = options | ||
if (name.startsWith("./") || name.startsWith(".\\")) { | ||
this.moduleType = "relative" | ||
} else if (name.startsWith("/") || name.startsWith("\\")) { | ||
this.moduleType = "absolute" | ||
} else if (isBuiltin(name)) { | ||
this.moduleType = "node" | ||
} else if (isNodeModule(name, options)) { | ||
this.moduleType = "npm" | ||
} else if (name.startsWith("http://") || name.startsWith("https://")) { | ||
this.moduleType = "http" | ||
} | ||
/** | ||
* What type of module are we looking for? | ||
* @type {ModuleType} | ||
*/ | ||
this.moduleType = this.getModuleType() | ||
/** | ||
* The full path of this import target. | ||
* If the target is a module and it does not exist then this is `null`. | ||
* @type {string|null} | ||
* What import style are we using | ||
* @type {ModuleStyle} | ||
*/ | ||
this.filePath = getFilePath(isModule, name, options, moduleType) | ||
this.moduleStyle = this.getModuleStyle(moduleType) | ||
@@ -158,6 +115,175 @@ /** | ||
* If the target is a relative path then this is `null`. | ||
* @type {string|null} | ||
* @type {string | null} | ||
*/ | ||
this.moduleName = isModule ? getModuleName(name) : null | ||
this.moduleName = this.getModuleName() | ||
/** | ||
* The full path of this import target. | ||
* If the target is a module and it does not exist then this is `null`. | ||
* @type {string | null} | ||
*/ | ||
this.filePath = this.getFilePath() | ||
} | ||
/** | ||
* What type of module is this | ||
* @returns {ModuleType} | ||
*/ | ||
getModuleType() { | ||
if (/^\.{1,2}([\\/]|$)/.test(this.name)) { | ||
return "relative" | ||
} | ||
if (/^[\\/]/.test(this.name)) { | ||
return "absolute" | ||
} | ||
if (isBuiltin(this.name)) { | ||
return "node" | ||
} | ||
if (/^(@[\w~-][\w.~-]*\/)?[\w~-][\w.~-]*/.test(this.name)) { | ||
return "npm" | ||
} | ||
if (/^https?:\/\//.test(this.name)) { | ||
return "http" | ||
} | ||
return "unknown" | ||
} | ||
/** | ||
* What module import style is used | ||
* @param {'import' | 'require'} fallback | ||
* @returns {ModuleStyle} | ||
*/ | ||
getModuleStyle(fallback) { | ||
/** @type {import('eslint').Rule.Node} */ | ||
let node = { parent: this.node } | ||
do { | ||
node = node.parent | ||
// `const {} = require('')` | ||
if ( | ||
node.type === "CallExpression" && | ||
node.callee.name === "require" | ||
) { | ||
return "require" | ||
} | ||
// `import type {} from '';` | ||
if ( | ||
node.type === "ImportDeclaration" && | ||
node.importKind === "type" | ||
) { | ||
return "type" | ||
} | ||
// `import {} from '';` | ||
if ( | ||
node.type === "ImportDeclaration" && | ||
node.importKind === "value" | ||
) { | ||
return "import" | ||
} | ||
} while (node.parent) | ||
return fallback | ||
} | ||
/** | ||
* Get the node or npm module name | ||
* @returns {string} | ||
*/ | ||
getModuleName() { | ||
if (this.moduleType === "relative") return | ||
if (this.moduleType === "npm") { | ||
if (this.name.startsWith("@")) { | ||
return trimAfter(this.name, "/", 2) | ||
} | ||
return trimAfter(this.name, "/") | ||
} | ||
if (this.moduleType === "node") { | ||
if (this.name.startsWith("node:")) { | ||
return trimAfter(this.name.slice(5), "/") | ||
} | ||
return trimAfter(this.name, "/") | ||
} | ||
} | ||
getPaths() { | ||
if (Array.isArray(this.options.paths)) { | ||
return [...this.options.paths, this.options.basedir] | ||
} | ||
return [this.options.basedir] | ||
} | ||
/** | ||
* Resolve the given id to file paths. | ||
* @returns {string | null} The resolved path. | ||
*/ | ||
getFilePath() { | ||
const conditionNames = ["node", "require"] | ||
const { extensions } = this.options | ||
const mainFields = [] | ||
const mainFiles = [] | ||
if (this.moduleStyle === "import") { | ||
conditionNames.push("import") | ||
} | ||
if (this.moduleStyle === "type") { | ||
conditionNames.push("import", "types") | ||
} | ||
if ( | ||
this.moduleStyle === "require" || | ||
this.moduleType === "npm" || | ||
this.moduleType === "node" | ||
) { | ||
mainFields.push("main") | ||
mainFiles.push("index") | ||
} | ||
let alias = undefined | ||
let extensionAlias = undefined | ||
if (isTypescript(this.context)) { | ||
alias = getTSConfigAliases(this.context) | ||
extensionAlias = getTypescriptExtensionMap(this.context).backward | ||
} | ||
const requireResolve = resolver.create.sync({ | ||
conditionNames, | ||
extensions, | ||
mainFields, | ||
mainFiles, | ||
extensionAlias, | ||
alias, | ||
}) | ||
const cwd = this.context.settings?.cwd ?? process.cwd() | ||
for (const directory of this.getPaths()) { | ||
try { | ||
const baseDir = resolve(cwd, directory) | ||
return requireResolve(baseDir, this.name) | ||
} catch { | ||
continue | ||
} | ||
} | ||
if (this.moduleType === "absolute" || this.moduleType === "relative") { | ||
return resolve(this.options.basedir, this.name) | ||
} | ||
return null | ||
} | ||
} |
@@ -71,3 +71,9 @@ /** | ||
targets.push( | ||
new ImportTarget(sourceNode, name, options, "import") | ||
new ImportTarget( | ||
context, | ||
sourceNode, | ||
name, | ||
options, | ||
"import" | ||
) | ||
) | ||
@@ -74,0 +80,0 @@ } |
@@ -63,3 +63,9 @@ /** | ||
targets.push( | ||
new ImportTarget(targetNode, name, options, "require") | ||
new ImportTarget( | ||
context, | ||
targetNode, | ||
name, | ||
options, | ||
"require" | ||
) | ||
) | ||
@@ -66,0 +72,0 @@ } |
{ | ||
"name": "eslint-plugin-n", | ||
"version": "16.6.2", | ||
"version": "17.0.0-0", | ||
"description": "Additional ESLint's rules for Node.js", | ||
"engines": { | ||
"node": ">=16.0.0" | ||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" | ||
}, | ||
@@ -14,7 +14,7 @@ "main": "lib/index.js", | ||
"peerDependencies": { | ||
"eslint": ">=7.0.0" | ||
"eslint": ">=8.23.0" | ||
}, | ||
"dependencies": { | ||
"@eslint-community/eslint-utils": "^4.4.0", | ||
"builtins": "^5.0.1", | ||
"enhanced-resolve": "^5.15.0", | ||
"eslint-plugin-es-x": "^7.5.0", | ||
@@ -27,3 +27,2 @@ "get-tsconfig": "^4.7.0", | ||
"minimatch": "^3.1.2", | ||
"resolve": "^1.22.2", | ||
"semver": "^7.5.3" | ||
@@ -35,4 +34,3 @@ }, | ||
"@typescript-eslint/parser": "^5.60.0", | ||
"esbuild": "^0.18.7", | ||
"eslint": "^8.56.0", | ||
"eslint": "^8", | ||
"eslint-config-prettier": "^8.8.0", | ||
@@ -44,3 +42,2 @@ "eslint-doc-generator": "^1.6.1", | ||
"husky": "^8.0.3", | ||
"import-meta-resolve": "^3.0.0", | ||
"lint-staged": "^13.2.2", | ||
@@ -118,3 +115,6 @@ "markdownlint-cli": "^0.35.0", | ||
"*.{json,js}": "prettier --write --ignore-path .eslintignore" | ||
}, | ||
"imports": { | ||
"#eslint-rule-tester": "./tests/eslint-rule-tester.js" | ||
} | ||
} |
@@ -21,4 +21,7 @@ # eslint-plugin-n | ||
- Requires Node.js `>=16.0.0` | ||
- Requires ESLint `>=7.0.0` | ||
| Version | Supported Node.js | Supported ESLint Version | | ||
|---------|-------------------|---------------------------| | ||
| 17.x | `^18.18.0 \|\| ^20.9.0 \|\| >=21.1.0` | `>=8.23.0` | | ||
| 16.x | `>=16.0.0` | `>=7.0.0` | | ||
| 15.x | `>=12.22.0` | `>=7.0.0` | | ||
@@ -25,0 +28,0 @@ **Note:** It recommends a use of [the "engines" field of package.json](https://docs.npmjs.com/files/package.json#engines). The "engines" field is used by `n/no-unsupported-features/*` rules. |
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
11
21
244
5
308470
77
8573
1
+ Addedenhanced-resolve@^5.15.0
+ Addedenhanced-resolve@5.17.0(transitive)
+ Addedgraceful-fs@4.2.11(transitive)
+ Addedtapable@2.2.1(transitive)
- Removedbuiltins@^5.0.1
- Removedresolve@^1.22.2
- Removedbuiltins@5.1.0(transitive)
- Removedpath-parse@1.0.7(transitive)
- Removedresolve@1.22.8(transitive)
- Removedsupports-preserve-symlinks-flag@1.0.0(transitive)