Socket
Socket
Sign inDemoInstall

eslint-plugin-n

Package Overview
Dependencies
101
Maintainers
2
Versions
55
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 17.0.0-6 to 17.0.0-7

lib/eslint-utils.d.ts

36

lib/configs/_commons.js
"use strict"
module.exports = {
commonRules: {
"n/no-deprecated-api": "error",
"n/no-extraneous-import": "error",
"n/no-extraneous-require": "error",
"n/no-exports-assign": "error",
"n/no-missing-import": "error",
"n/no-missing-require": "error",
"n/no-process-exit": "error",
"n/no-unpublished-bin": "error",
"n/no-unpublished-import": "error",
"n/no-unpublished-require": "error",
"n/no-unsupported-features/es-builtins": "error",
"n/no-unsupported-features/es-syntax": "error",
"n/no-unsupported-features/node-builtins": "error",
"n/process-exit-as-throw": "error",
"n/hashbang": "error",
},
}
module.exports.commonRules = /** @type {const} */ ({
"n/no-deprecated-api": "error",
"n/no-extraneous-import": "error",
"n/no-extraneous-require": "error",
"n/no-exports-assign": "error",
"n/no-missing-import": "error",
"n/no-missing-require": "error",
"n/no-process-exit": "error",
"n/no-unpublished-bin": "error",
"n/no-unpublished-import": "error",
"n/no-unpublished-require": "error",
"n/no-unsupported-features/es-builtins": "error",
"n/no-unsupported-features/es-syntax": "error",
"n/no-unsupported-features/node-builtins": "error",
"n/process-exit-as-throw": "error",
"n/hashbang": "error",
})

@@ -6,3 +6,6 @@ "use strict"

// eslintrc config: https://eslint.org/docs/latest/use/configure/configuration-files
/**
* https://eslint.org/docs/latest/use/configure/configuration-files
* @type {import('eslint').ESLint.ConfigData}
*/
module.exports.eslintrc = {

@@ -34,3 +37,6 @@ env: {

// flat config: https://eslint.org/docs/latest/use/configure/configuration-files-new
/**
* https://eslint.org/docs/latest/use/configure/configuration-files-new
* @type {import('eslint').Linter.FlatConfig}
*/
module.exports.flat = {

@@ -44,3 +50,5 @@ languageOptions: {

},
rules: module.exports.eslintrc.rules,
rules:
/** @type {import('eslint').Linter.RulesRecord} */
(module.exports.eslintrc.rules),
}

@@ -6,3 +6,6 @@ "use strict"

// eslintrc config: https://eslint.org/docs/latest/use/configure/configuration-files
/**
* https://eslint.org/docs/latest/use/configure/configuration-files
* @type {import('eslint').ESLint.ConfigData}
*/
module.exports.eslintrc = {

@@ -31,3 +34,6 @@ env: {

// https://eslint.org/docs/latest/use/configure/configuration-files-new
/**
* https://eslint.org/docs/latest/use/configure/configuration-files-new
* @type {import('eslint').Linter.FlatConfig}
*/
module.exports.flat = {

@@ -41,3 +47,5 @@ languageOptions: {

},
rules: module.exports.eslintrc.rules,
rules:
/** @type {import('eslint').Linter.RulesRecord} */
(module.exports.eslintrc.rules),
}
"use strict"
const getPackageJson = require("../util/get-package-json")
const { getPackageJson } = require("../util/get-package-json")
const moduleConfig = require("./recommended-module")

@@ -8,5 +8,14 @@ const scriptConfig = require("./recommended-script")

const packageJson = getPackageJson()
const isModule = (packageJson && packageJson.type) === "module"
const isModule =
packageJson != null &&
typeof packageJson === "object" &&
"type" in packageJson &&
packageJson.type === "module"
const recommendedConfig = isModule ? moduleConfig : scriptConfig
/**
* https://eslint.org/docs/latest/use/configure/configuration-files
* @type {import('eslint').ESLint.ConfigData}
*/
module.exports.eslintrc = {

@@ -13,0 +22,0 @@ ...recommendedConfig.eslintrc,

@@ -8,48 +8,16 @@ "use strict"

const rules = {
"callback-return": require("./rules/callback-return"),
"exports-style": require("./rules/exports-style"),
"file-extension-in-import": require("./rules/file-extension-in-import"),
"global-require": require("./rules/global-require"),
"handle-callback-err": require("./rules/handle-callback-err"),
"no-callback-literal": require("./rules/no-callback-literal"),
"no-deprecated-api": require("./rules/no-deprecated-api"),
"no-exports-assign": require("./rules/no-exports-assign"),
"no-extraneous-import": require("./rules/no-extraneous-import"),
"no-extraneous-require": require("./rules/no-extraneous-require"),
"no-missing-import": require("./rules/no-missing-import"),
"no-missing-require": require("./rules/no-missing-require"),
"no-mixed-requires": require("./rules/no-mixed-requires"),
"no-new-require": require("./rules/no-new-require"),
"no-path-concat": require("./rules/no-path-concat"),
"no-process-env": require("./rules/no-process-env"),
"no-process-exit": require("./rules/no-process-exit"),
"no-restricted-import": require("./rules/no-restricted-import"),
"no-restricted-require": require("./rules/no-restricted-require"),
"no-sync": require("./rules/no-sync"),
"no-unpublished-bin": require("./rules/no-unpublished-bin"),
"no-unpublished-import": require("./rules/no-unpublished-import"),
"no-unpublished-require": require("./rules/no-unpublished-require"),
"no-unsupported-features/es-builtins": require("./rules/no-unsupported-features/es-builtins"),
"no-unsupported-features/es-syntax": require("./rules/no-unsupported-features/es-syntax"),
"no-unsupported-features/node-builtins": require("./rules/no-unsupported-features/node-builtins"),
"prefer-global/buffer": require("./rules/prefer-global/buffer"),
"prefer-global/console": require("./rules/prefer-global/console"),
"prefer-global/process": require("./rules/prefer-global/process"),
"prefer-global/text-decoder": require("./rules/prefer-global/text-decoder"),
"prefer-global/text-encoder": require("./rules/prefer-global/text-encoder"),
"prefer-global/url-search-params": require("./rules/prefer-global/url-search-params"),
"prefer-global/url": require("./rules/prefer-global/url"),
"prefer-node-protocol": require("./rules/prefer-node-protocol"),
"prefer-promises/dns": require("./rules/prefer-promises/dns"),
"prefer-promises/fs": require("./rules/prefer-promises/fs"),
"process-exit-as-throw": require("./rules/process-exit-as-throw"),
hashbang: require("./rules/hashbang"),
/**
* @typedef {{
'recommended-module': import('eslint').ESLint.ConfigData;
'recommended-script': import('eslint').ESLint.ConfigData;
'recommended': import('eslint').ESLint.ConfigData;
'flat/recommended-module': import('eslint').Linter.FlatConfig;
'flat/recommended-script': import('eslint').Linter.FlatConfig;
'flat/recommended': import('eslint').Linter.FlatConfig;
'flat/mixed-esm-and-cjs': import('eslint').Linter.FlatConfig[];
}} Configs
*/
// Deprecated rules.
"no-hide-core-modules": require("./rules/no-hide-core-modules"),
shebang: require("./rules/shebang"),
}
const mod = {
/** @type {import('eslint').ESLint.Plugin & { configs: Configs }} */
const plugin = {
meta: {

@@ -59,21 +27,69 @@ name: pkg.name,

},
rules,
rules: /** @type {Record<string, import('eslint').Rule.RuleModule>} */ ({
"callback-return": require("./rules/callback-return"),
"exports-style": require("./rules/exports-style"),
"file-extension-in-import": require("./rules/file-extension-in-import"),
"global-require": require("./rules/global-require"),
"handle-callback-err": require("./rules/handle-callback-err"),
"no-callback-literal": require("./rules/no-callback-literal"),
"no-deprecated-api": require("./rules/no-deprecated-api"),
"no-exports-assign": require("./rules/no-exports-assign"),
"no-extraneous-import": require("./rules/no-extraneous-import"),
"no-extraneous-require": require("./rules/no-extraneous-require"),
"no-missing-import": require("./rules/no-missing-import"),
"no-missing-require": require("./rules/no-missing-require"),
"no-mixed-requires": require("./rules/no-mixed-requires"),
"no-new-require": require("./rules/no-new-require"),
"no-path-concat": require("./rules/no-path-concat"),
"no-process-env": require("./rules/no-process-env"),
"no-process-exit": require("./rules/no-process-exit"),
"no-restricted-import": require("./rules/no-restricted-import"),
"no-restricted-require": require("./rules/no-restricted-require"),
"no-sync": require("./rules/no-sync"),
"no-unpublished-bin": require("./rules/no-unpublished-bin"),
"no-unpublished-import": require("./rules/no-unpublished-import"),
"no-unpublished-require": require("./rules/no-unpublished-require"),
"no-unsupported-features/es-builtins": require("./rules/no-unsupported-features/es-builtins"),
"no-unsupported-features/es-syntax": require("./rules/no-unsupported-features/es-syntax"),
"no-unsupported-features/node-builtins": require("./rules/no-unsupported-features/node-builtins"),
"prefer-global/buffer": require("./rules/prefer-global/buffer"),
"prefer-global/console": require("./rules/prefer-global/console"),
"prefer-global/process": require("./rules/prefer-global/process"),
"prefer-global/text-decoder": require("./rules/prefer-global/text-decoder"),
"prefer-global/text-encoder": require("./rules/prefer-global/text-encoder"),
"prefer-global/url-search-params": require("./rules/prefer-global/url-search-params"),
"prefer-global/url": require("./rules/prefer-global/url"),
"prefer-node-protocol": require("./rules/prefer-node-protocol"),
"prefer-promises/dns": require("./rules/prefer-promises/dns"),
"prefer-promises/fs": require("./rules/prefer-promises/fs"),
"process-exit-as-throw": require("./rules/process-exit-as-throw"),
hashbang: require("./rules/hashbang"),
// Deprecated rules.
"no-hide-core-modules": require("./rules/no-hide-core-modules"),
shebang: require("./rules/shebang"),
}),
configs: {
"recommended-module": { plugins: ["n"], ...esmConfig.eslintrc },
"recommended-script": { plugins: ["n"], ...cjsConfig.eslintrc },
recommended: { plugins: ["n"], ...recommendedConfig.eslintrc },
"flat/recommended-module": { ...esmConfig.flat },
"flat/recommended-script": { ...cjsConfig.flat },
"flat/recommended": { ...recommendedConfig.flat },
"flat/mixed-esm-and-cjs": [
{ files: ["**/*.js"], ...recommendedConfig.flat },
{ files: ["**/*.mjs"], ...esmConfig.flat },
{ files: ["**/*.cjs"], ...cjsConfig.flat },
],
},
}
// set configs, e.g. mod.configs["recommended-module"]
// do not defined in the mod obj - to avoid circular dependency
mod.configs = {
"recommended-module": { plugins: ["n"], ...esmConfig.eslintrc },
"recommended-script": { plugins: ["n"], ...cjsConfig.eslintrc },
recommended: { plugins: ["n"], ...recommendedConfig.eslintrc },
"flat/recommended-module": { plugins: { n: mod }, ...esmConfig.flat },
"flat/recommended-script": { plugins: { n: mod }, ...cjsConfig.flat },
"flat/recommended": { plugins: { n: mod }, ...recommendedConfig.flat },
"flat/mixed-esm-and-cjs": [
{ plugins: { n: mod }, files: ["**/*.js"], ...recommendedConfig.flat },
{ plugins: { n: mod }, files: ["**/*.mjs"], ...esmConfig.flat },
{ plugins: { n: mod }, files: ["**/*.cjs"], ...cjsConfig.flat },
],
plugin.configs["flat/recommended-module"].plugins = { n: plugin }
plugin.configs["flat/recommended-script"].plugins = { n: plugin }
plugin.configs["flat/recommended"].plugins = { n: plugin }
for (const config of plugin.configs["flat/mixed-esm-and-cjs"]) {
config.plugins = { n: plugin }
}
module.exports = mod
module.exports = plugin

@@ -7,2 +7,3 @@ /**

/** @type {import('eslint').Rule.RuleModule} */
module.exports = {

@@ -34,5 +35,5 @@ meta: {

* Find the closest parent matching a list of types.
* @param {ASTNode} node The node whose parents we are searching
* @param {Array} types The node types to match
* @returns {ASTNode} The matched node or undefined.
* @param {import('eslint').Rule.Node} node The node whose parents we are searching
* @param {string[]} types The node types to match
* @returns {import('eslint').Rule.Node | null} The matched node or undefined.
*/

@@ -51,3 +52,3 @@ function findClosestParentOfType(node, types) {

* Check to see if a node contains only identifers
* @param {ASTNode} node The node to check
* @param {import('estree').Expression | import('estree').Super} node The node to check
* @returns {boolean} Whether or not the node contains only identifers

@@ -74,3 +75,3 @@ */

* Check to see if a CallExpression is in our callback list.
* @param {ASTNode} node The node to check against our callback names list.
* @param {import('estree').CallExpression} node The node to check against our callback names list.
* @returns {boolean} Whether or not this function matches our callback name.

@@ -87,4 +88,4 @@ */

* Determines whether or not the callback is part of a callback expression.
* @param {ASTNode} node The callback node
* @param {ASTNode} parentNode The expression node
* @param {import('eslint').Rule.Node} node The callback node
* @param {import('estree').Statement} parentNode The expression node
* @returns {boolean} Whether or not this is part of a callback expression

@@ -124,11 +125,10 @@ */

// find the closest block, return or loop
const closestBlock =
findClosestParentOfType(node, [
"BlockStatement",
"ReturnStatement",
"ArrowFunctionExpression",
]) || {}
const closestBlock = findClosestParentOfType(node, [
"BlockStatement",
"ReturnStatement",
"ArrowFunctionExpression",
])
// if our parent is a return we know we're ok
if (closestBlock.type === "ReturnStatement") {
if (closestBlock?.type === "ReturnStatement") {
return

@@ -138,3 +138,3 @@ }

// arrow functions don't always have blocks and implicitly return
if (closestBlock.type === "ArrowFunctionExpression") {
if (closestBlock?.type === "ArrowFunctionExpression") {
return

@@ -144,3 +144,3 @@ }

// block statements are part of functions and most if statements
if (closestBlock.type === "BlockStatement") {
if (closestBlock?.type === "BlockStatement") {
// find the last item in the block

@@ -147,0 +147,0 @@ const lastItem =

@@ -7,2 +7,6 @@ /**

/**
* @typedef {import('estree').Node & { parent?: Node }} Node
*/
/*istanbul ignore next */

@@ -12,10 +16,11 @@ /**

*
* @param {ASTNode} node - The node to get.
* @returns {string|null} The property name if static. Otherwise, null.
* @param {Node} node - The node to get.
* @returns {string | null | undefined} The property name if static. Otherwise, null.
* @private
*/
function getStaticPropertyName(node) {
/** @type {import('estree').Expression | import('estree').PrivateIdentifier | null} */
let prop = null
switch (node && node.type) {
switch (node?.type) {
case "Property":

@@ -33,3 +38,3 @@ case "MethodDefinition":

switch (prop && prop.type) {
switch (prop?.type) {
case "Literal":

@@ -45,3 +50,8 @@ return String(prop.value)

case "Identifier":
if (!node.computed) {
if (
!(
/** @type {import('estree').MemberExpression} */ (node)
.computed
)
) {
return prop.name

@@ -60,3 +70,3 @@ }

*
* @param {ASTNode} node - The node to check.
* @param {Node} node - The node to check.
* @returns {boolean} `true` if the node is assignee.

@@ -66,3 +76,4 @@ */

return (
node.parent.type === "AssignmentExpression" && node.parent.left === node
node.parent?.type === "AssignmentExpression" &&
node.parent.left === node
)

@@ -77,4 +88,4 @@ }

*
* @param {ASTNode} leafNode - The node to get.
* @returns {ASTNode|null} The top assignment expression node, or null.
* @param {Node} leafNode - The node to get.
* @returns {Node|null} The top assignment expression node, or null.
*/

@@ -86,3 +97,3 @@ function getTopAssignment(leafNode) {

while (
node.parent.type === "MemberExpression" &&
node.parent?.type === "MemberExpression" &&
node.parent.object === node

@@ -99,3 +110,3 @@ ) {

// Find the top.
while (node.parent.type === "AssignmentExpression") {
while (node.parent?.type === "AssignmentExpression") {
node = node.parent

@@ -110,7 +121,7 @@ }

*
* @param {ASTNode[]} nodes - The node list to get.
* @returns {ASTNode[]} Gotten top assignment nodes.
* @param {Node[]} nodes - The node list to get.
* @returns {Node[]} Gotten top assignment nodes.
*/
function createAssignmentList(nodes) {
return nodes.map(getTopAssignment).filter(Boolean)
return /** @type {Node[]} */ (nodes.map(getTopAssignment).filter(Boolean))
}

@@ -121,4 +132,4 @@

*
* @param {escope.Scope} scope - The scope to get.
* @returns {ASTNode[]} Gotten MemberExpression node list.
* @param {import('eslint').Scope.Scope} scope - The scope to get.
* @returns {Node[]} Gotten MemberExpression node list.
*/

@@ -131,6 +142,10 @@ function getModuleExportsNodes(scope) {

return variable.references
.map(reference => reference.identifier.parent)
.map(
reference =>
/** @type {Node & { parent: Node }} */ (reference.identifier)
.parent
)
.filter(
node =>
node.type === "MemberExpression" &&
node?.type === "MemberExpression" &&
getStaticPropertyName(node) === "exports"

@@ -143,4 +158,4 @@ )

*
* @param {escope.Scope} scope - The scope to get.
* @returns {ASTNode[]} Gotten Identifier node list.
* @param {import('eslint').Scope.Scope} scope - The scope to get.
* @returns {import('estree').Identifier[]} Gotten Identifier node list.
*/

@@ -152,5 +167,11 @@ function getExportsNodes(scope) {

}
return variable.references.map(reference => reference.identifier)
}
/**
* @param {Node} property
* @param {import('eslint').SourceCode} sourceCode
* @returns {string | null}
*/
function getReplacementForProperty(property, sourceCode) {

@@ -169,3 +190,3 @@ if (property.type !== "Property" || property.kind !== "init") {

let fixedValue = sourceCode.getText(property.value)
if (property.method) {
if (property.value.type === "FunctionExpression" && property.method) {
fixedValue = `function${

@@ -180,2 +201,3 @@ property.value.generator ? "*" : ""

.getCommentsBefore(property)
// @ts-expect-error getText supports both BaseNode and BaseNodeWithoutComments
.map(comment => sourceCode.getText(comment))

@@ -199,2 +221,3 @@ if (property.key.type === "Literal" || property.computed) {

.getCommentsAfter(property)
// @ts-expect-error getText supports both BaseNode and BaseNodeWithoutComments
.map(comment => sourceCode.getText(comment))

@@ -205,8 +228,12 @@ )

// Check for a top level module.exports = { ... }
/**
* Check for a top level module.exports = { ... }
* @param {Node} node
* @returns {node is {parent: import('estree').AssignmentExpression & {parent: import('estree').ExpressionStatement, right: import('estree').ObjectExpression}}}
*/
function isModuleExportsObjectAssignment(node) {
return (
node.parent.type === "AssignmentExpression" &&
node.parent.parent.type === "ExpressionStatement" &&
node.parent.parent.parent.type === "Program" &&
node.parent?.type === "AssignmentExpression" &&
node.parent?.parent?.type === "ExpressionStatement" &&
node.parent.parent.parent?.type === "Program" &&
node.parent.right.type === "ObjectExpression"

@@ -216,9 +243,19 @@ )

// Check for module.exports.foo or module.exports.bar reference or assignment
/**
* Check for module.exports.foo or module.exports.bar reference or assignment
* @param {Node} node
* @returns {node is import('estree').MemberExpression}
*/
function isModuleExportsReference(node) {
return (
node.parent.type === "MemberExpression" && node.parent.object === node
node.parent?.type === "MemberExpression" && node.parent.object === node
)
}
/**
* @param {Node} node
* @param {import('eslint').SourceCode} sourceCode
* @param {import('eslint').Rule.RuleFixer} fixer
* @returns {import('eslint').Rule.Fix | null}
*/
function fixModuleExports(node, sourceCode, fixer) {

@@ -245,2 +282,3 @@ if (isModuleExportsReference(node)) {

/** @type {import('eslint').Rule.RuleModule} */
module.exports = {

@@ -292,4 +330,4 @@ meta: {

*
* @param {ASTNode} node - The node of `exports`/`module.exports`.
* @returns {Location} The location info of reports.
* @param {Node} node - The node of `exports`/`module.exports`.
* @returns {import('estree').SourceLocation} The location info of reports.
*/

@@ -299,4 +337,6 @@ function getLocation(node) {

return {
start: node.loc.start,
end: token.loc.end,
start: /** @type {import('estree').SourceLocation} */ (node.loc)
.start,
end: /** @type {import('estree').SourceLocation} */ (token?.loc)
?.end,
}

@@ -309,2 +349,3 @@ }

*
* @param {import('eslint').Scope.Scope} globalScope
* @returns {void}

@@ -320,5 +361,7 @@ */

// Skip if it's a batch assignment.
const topAssignment = getTopAssignment(node)
if (
topAssignment &&
assignList.length > 0 &&
assignList.indexOf(getTopAssignment(node)) !== -1
assignList.indexOf(topAssignment) !== -1
) {

@@ -341,2 +384,3 @@ continue

*
* @param {import('eslint').Scope.Scope} globalScope
* @returns {void}

@@ -355,3 +399,6 @@ */

if (assignList.length > 0) {
const found = assignList.indexOf(getTopAssignment(node))
const topAssignment = getTopAssignment(node)
const found = topAssignment
? assignList.indexOf(topAssignment)
: -1
if (found !== -1) {

@@ -382,4 +429,8 @@ batchAssignList.push(assignList[found])

const topAssignment = getTopAssignment(node)
// Check if it's a batch assignment.
if (batchAssignList.indexOf(getTopAssignment(node)) !== -1) {
if (
topAssignment &&
batchAssignList.indexOf(topAssignment) !== -1
) {
continue

@@ -386,0 +437,0 @@ }

@@ -9,3 +9,3 @@ /**

const fs = require("fs")
const mapTypescriptExtension = require("../util/map-typescript-extension")
const { convertTsExtensionToJs } = require("../util/map-typescript-extension")
const visitImport = require("../util/visit-import")

@@ -28,3 +28,3 @@

.map(filename => path.extname(filename))
} catch (_error) {
} catch {
return []

@@ -34,2 +34,3 @@ }

/** @type {import('eslint').Rule.RuleModule} */
module.exports = {

@@ -75,3 +76,6 @@ meta: {

// Ignore if it's not resolved to a file or it's a bare module.
if (moduleType !== "relative" && moduleType !== "absolute") {
if (
(moduleType !== "relative" && moduleType !== "absolute") ||
filePath == null
) {
return

@@ -85,3 +89,3 @@ }

const expectedExt = mapTypescriptExtension(
const expectedExt = convertTsExtensionToJs(
context,

@@ -99,3 +103,4 @@ filePath,

fix(fixer) {
const index = node.range[1] - 1
const index =
/** @type {[number, number]} */ (node.range)[1] - 1
return fixer.insertTextBeforeRange(

@@ -117,13 +122,2 @@ [index, index],

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({

@@ -133,3 +127,16 @@ node,

data: { ext: currentExt },
fix,
fix:
otherExtensions.length > 1
? undefined
: fixer => {
const index = name.lastIndexOf(currentExt)
const start =
/** @type {[number, number]} */ (
node.range
)[0] +
1 +
index
const end = start + currentExt.length
return fixer.removeRange([start, end])
},
})

@@ -136,0 +143,0 @@ }

@@ -20,18 +20,12 @@ /**

* Finds the eslint-scope reference in the given scope.
* @param {Object} scope The scope to search.
* @param {ASTNode} node The identifier node.
* @returns {Reference|null} Returns the found reference or null if none were found.
* @param {import('eslint').Scope.Scope} scope The scope to search.
* @param {import('estree').Node} node The identifier node.
* @returns {import('eslint').Scope.Reference|undefined} Returns the found reference or null if none were found.
*/
function findReference(scope, node) {
const references = scope.references.filter(
return scope.references.find(
reference =>
reference.identifier.range[0] === node.range[0] &&
reference.identifier.range[1] === node.range[1]
reference.identifier.range?.[0] === node.range?.[0] &&
reference.identifier.range?.[1] === node.range?.[1]
)
/* istanbul ignore else: correctly returns null */
if (references.length === 1) {
return references[0]
}
return null
}

@@ -41,4 +35,4 @@

* Checks if the given identifier node is shadowed in the given scope.
* @param {Object} scope The current scope.
* @param {ASTNode} node The identifier node to check.
* @param {import('eslint').Scope.Scope} scope The current scope.
* @param {import('estree').Node} node The identifier node to check.
* @returns {boolean} Whether or not the name is shadowed.

@@ -49,5 +43,6 @@ */

return reference && reference.resolved && reference.resolved.defs.length > 0
return Boolean(reference?.resolved?.defs?.length)
}
/** @type {import('eslint').Rule.RuleModule} */
module.exports = {

@@ -78,3 +73,4 @@ meta: {

if (
node.callee.name === "require" &&
/** @type {import('estree').Identifier} */ (node.callee)
.name === "require" &&
!isShadowed(currentScope, node.callee)

@@ -81,0 +77,0 @@ ) {

@@ -7,2 +7,3 @@ /**

/** @type {import('eslint').Rule.RuleModule} */
module.exports = {

@@ -58,4 +59,4 @@ meta: {

* Get the parameters of a given function scope.
* @param {Object} scope The function scope.
* @returns {Array} All parameters of the given scope.
* @param {import('eslint').Scope.Scope} scope The function scope.
* @returns {import('eslint').Scope.Variable[]} All parameters of the given scope.
*/

@@ -71,3 +72,3 @@ function getParameters(scope) {

* Check to see if we're handling the error object properly.
* @param {ASTNode} node The AST node to check.
* @param {import('estree').Node} node The AST node to check.
* @returns {void}

@@ -74,0 +75,0 @@ */

@@ -8,7 +8,8 @@ /**

const path = require("path")
const matcher = require("ignore")
const matcher = require("ignore").default
const getConvertPath = require("../util/get-convert-path")
const getPackageJson = require("../util/get-package-json")
const { getPackageJson } = require("../util/get-package-json")
const getNpmignore = require("../util/get-npmignore")
const { isBinFile } = require("../util/is-bin-file")

@@ -20,41 +21,6 @@ const NODE_SHEBANG = "#!/usr/bin/env node\n"

function simulateNodeResolutionAlgorithm(filePath, binField) {
const possibilities = [filePath]
let newFilePath = filePath.replace(/\.js$/u, "")
possibilities.push(newFilePath)
newFilePath = newFilePath.replace(/[/\\]index$/u, "")
possibilities.push(newFilePath)
return possibilities.includes(binField)
}
/**
* Checks whether or not a given path is a `bin` file.
*
* @param {string} filePath - A file path to check.
* @param {string|object|undefined} binField - A value of the `bin` field of `package.json`.
* @param {string} basedir - A directory path that `package.json` exists.
* @returns {boolean} `true` if the file is a `bin` file.
*/
function isBinFile(filePath, binField, basedir) {
if (!binField) {
return false
}
if (typeof binField === "string") {
return simulateNodeResolutionAlgorithm(
filePath,
path.resolve(basedir, binField)
)
}
return Object.keys(binField).some(key =>
simulateNodeResolutionAlgorithm(
filePath,
path.resolve(basedir, binField[key])
)
)
}
/**
* Gets the shebang line (includes a line ending) from a given code.
*
* @param {SourceCode} sourceCode - A source code object to check.
* @param {import('eslint').SourceCode} sourceCode - A source code object to check.
* @returns {{length: number, bom: boolean, shebang: string, cr: boolean}}

@@ -114,8 +80,8 @@ * shebang's information.

const p = getPackageJson(filePath)
if (!p) {
const packageJson = getPackageJson(filePath)
if (typeof packageJson?.filePath !== "string") {
return {}
}
const packageDirectory = path.dirname(p.filePath)
const packageDirectory = path.dirname(packageJson.filePath)

@@ -134,2 +100,3 @@ const originalAbsolutePath = path.resolve(filePath)

/** @type {{ additionalExecutables: string[] }} */
const { additionalExecutables = [] } = context.options?.[0] ?? {}

@@ -155,3 +122,3 @@

isExecutable.ignored === true ||
isBinFile(convertedAbsolutePath, p.bin, packageDirectory)
isBinFile(convertedAbsolutePath, packageJson?.bin, packageDirectory)
const info = getShebangInfo(sourceCode)

@@ -163,3 +130,6 @@

start: { line: 1, column: 0 },
end: { line: 1, column: sourceCode.lines.at(0).length },
end: {
line: 1,
column: sourceCode.lines.at(0)?.length ?? 0,
},
}

@@ -166,0 +136,0 @@

@@ -7,2 +7,5 @@ /**

const callbackNames = ["callback", "cb"]
/** @type {import('eslint').Rule.RuleModule} */
module.exports = {

@@ -26,12 +29,8 @@ meta: {

create(context) {
const callbackNames = ["callback", "cb"]
function isCallback(name) {
return callbackNames.indexOf(name) > -1
}
return {
CallExpression(node) {
const errorArg = node.arguments[0]
const calleeName = node.callee.name
const calleeName = /** @type {import('estree').Identifier} */ (
node.callee
).name

@@ -41,3 +40,3 @@ if (

!couldBeError(errorArg) &&
isCallback(calleeName)
callbackNames.includes(calleeName)
) {

@@ -56,3 +55,3 @@ context.report({

* Determine if a node has a possiblity to be an Error object
* @param {ASTNode} node ASTNode to check
* @param {import('estree').Node} node ASTNode to check
* @returns {boolean} True if there is a chance it contains an Error obj

@@ -59,0 +58,0 @@ */

@@ -19,2 +19,14 @@ /**

/**
* @typedef DeprecatedInfo
* @property {string} since
* @property {string|{ name: string, supported: string }[]|null} replacedBy
*/
/**
* @typedef ParsedOptions
* @property {import('semver').Range} version
* @property {Set<string>} ignoredGlobalItems
* @property {Set<string>} ignoredModuleItems
*/
/** @type {import('@eslint-community/eslint-utils').TraceMap<DeprecatedInfo>} */
const rawModules = {

@@ -641,4 +653,4 @@ _linklist: {

*
* @param {string|array|null} replacedBy - The text of substitute way.
* @param {Range} version - The configured version range
* @param {DeprecatedInfo["replacedBy"]} replacedBy - The text of substitute way.
* @param {import('semver').Range} version - The configured version range
* @returns {string} Replacement message.

@@ -653,3 +665,7 @@ */

({ supported }) =>
!version.intersects(getSemverRange(`<${supported}`))
!version.intersects(
/** @type {import('semver').Range} */ (
getSemverRange(`<${supported}`)
)
)
)

@@ -680,5 +696,4 @@ .map(({ name }) => name)

* Parses the options.
* @param {RuleContext} context The rule context.
* @returns {{version:Range,ignoredGlobalItems:Set<string>,ignoredModuleItems:Set<string>}} Parsed
* value.
* @param {import('eslint').Rule.RuleContext} context The rule context.
* @returns {ParsedOptions} Parsed options
*/

@@ -694,2 +709,3 @@ function parseOptions(context) {

/** @type {import('eslint').Rule.RuleModule} */
module.exports = {

@@ -746,5 +762,5 @@ meta: {

*
* @param {ASTNode} node - A node to report.
* @param {import('estree').Node} node - A node to report.
* @param {string} name - The name of a deprecated API.
* @param {{since: number, replacedBy: string}} info - Information of the API.
* @param {DeprecatedInfo} info - Information of the API.
* @returns {void}

@@ -755,3 +771,5 @@ */

node,
loc: node.loc,
loc: /** @type {NonNullable<import('estree').Node["loc"]>} */ (
node.loc
),
messageId: "deprecated",

@@ -758,0 +776,0 @@ data: {

@@ -9,2 +9,7 @@ /**

/**
* @param {import('estree').Node} node
* @param {import('eslint').Scope.Scope} scope
* @returns {boolean}
*/
function isExports(node, scope) {

@@ -22,2 +27,7 @@ let variable = null

/**
* @param {import('estree').Node} node
* @param {import('eslint').Scope.Scope} scope
* @returns {boolean}
*/
function isModuleExports(node, scope) {

@@ -39,2 +49,3 @@ let variable = null

/** @type {import('eslint').Rule.RuleModule} */
module.exports = {

@@ -41,0 +52,0 @@ meta: {

@@ -13,2 +13,3 @@ /**

/** @type {import('eslint').Rule.RuleModule} */
module.exports = {

@@ -15,0 +16,0 @@ meta: {

@@ -14,2 +14,3 @@ /**

/** @type {import('eslint').Rule.RuleModule} */
module.exports = {

@@ -16,0 +17,0 @@ meta: {

@@ -12,3 +12,3 @@ /**

const path = require("path")
const getPackageJson = require("../util/get-package-json")
const { getPackageJson } = require("../util/get-package-json")
const mergeVisitorsInPlace = require("../util/merge-visitors-in-place")

@@ -18,2 +18,3 @@ const visitImport = require("../util/visit-import")

/** @type {Set<string|undefined>} */
const CORE_MODULES = new Set([

@@ -54,2 +55,3 @@ "assert",

/** @type {import('eslint').Rule.RuleModule} */
module.exports = {

@@ -95,8 +97,7 @@ meta: {

const packageJson = getPackageJson(filePath)
const deps = new Set(
[].concat(
Object.keys((packageJson && packageJson.dependencies) || {}),
Object.keys((packageJson && packageJson.devDependencies) || {})
)
)
/** @type {Set<string|undefined>} */
const deps = new Set([
...Object.keys(packageJson?.dependencies ?? {}),
...Object.keys(packageJson?.devDependencies ?? {}),
])
const options = context.options[0] || {}

@@ -110,2 +111,3 @@ const allow = options.allow || []

)
/** @type {import('../util/import-target.js')[]} */
const targets = []

@@ -143,3 +145,5 @@

node: target.node,
loc: target.node.loc,
loc: /** @type {NonNullable<import('estree').Node["loc"]>} */ (
target.node.loc
),
messageId: "unexpectedImport",

@@ -155,8 +159,4 @@ data: {

},
].reduce(
(mergedVisitor, thisVisitor) =>
mergeVisitorsInPlace(mergedVisitor, thisVisitor),
{}
)
].reduce(mergeVisitorsInPlace, {})
},
}

@@ -14,2 +14,3 @@ /**

/** @type {import('eslint').Rule.RuleModule} */
module.exports = {

@@ -16,0 +17,0 @@ meta: {

@@ -15,2 +15,3 @@ /**

/** @type {import('eslint').Rule.RuleModule} */
module.exports = {

@@ -17,0 +18,0 @@ meta: {

@@ -68,2 +68,3 @@ /**

/** @type {import('eslint').Rule.RuleModule} */
module.exports = {

@@ -130,3 +131,3 @@ meta: {

* Determines the type of a declaration statement.
* @param {ASTNode} initExpression The init node of the VariableDeclarator.
* @param {import('estree').Node | undefined | null} initExpression The init node of the VariableDeclarator.
* @returns {string} The type of declaration represented by the expression.

@@ -167,3 +168,3 @@ */

* Determines the type of module that is loaded via require.
* @param {ASTNode} initExpression The init node of the VariableDeclarator.
* @param {import('estree').Expression | import('estree').Super} initExpression The init node of the VariableDeclarator.
* @returns {string} The module type.

@@ -176,3 +177,7 @@ */

}
if (initExpression.arguments.length === 0) {
if (
/** @type {import('estree').CallExpression} */ (initExpression)
.arguments.length === 0
) {
// "var x = require();"

@@ -182,3 +187,5 @@ return REQ_COMPUTED

const arg = initExpression.arguments[0]
const arg = /** @type {import('estree').CallExpression} */ (
initExpression
).arguments[0]

@@ -206,6 +213,7 @@ if (arg.type !== "Literal" || typeof arg.value !== "string") {

* contains both require and other declarations.
* @param {ASTNode} declarations The list of VariableDeclarators.
* @param {import('estree').VariableDeclarator[]} declarations The list of VariableDeclarators.
* @returns {boolean} True if the declarations are mixed, false if not.
*/
function isMixed(declarations) {
/** @type {Record<string, boolean>} */
const contains = {}

@@ -228,6 +236,7 @@

* type.
* @param {ASTNode} declarations The list of VariableDeclarators.
* @param {import('estree').VariableDeclarator[]} declarations The list of VariableDeclarators.
* @returns {boolean} True if the declarations are grouped, false if not.
*/
function isGrouped(declarations) {
/** @type {Record<string, boolean>} */
const found = {}

@@ -237,3 +246,9 @@

if (getDeclarationType(declaration.init) === DECL_REQUIRE) {
found[inferModuleType(declaration.init)] = true
found[
inferModuleType(
/** @type {import('estree').Expression} */ (
declaration.init
)
)
] = true
}

@@ -240,0 +255,0 @@ }

@@ -7,2 +7,3 @@ /**

/** @type {import('eslint').Rule.RuleModule} */
module.exports = {

@@ -9,0 +10,0 @@ meta: {

@@ -16,6 +16,6 @@ /**

* Get the first char of the specified template element.
* @param {TemplateLiteral} node The `TemplateLiteral` node to get.
* @param {import('estree').TemplateLiteral} node The `TemplateLiteral` node to get.
* @param {number} i The number of template elements to get first char.
* @param {Set<Node>} sepNodes The nodes of `path.sep`.
* @param {import("escope").Scope} globalScope The global scope object.
* @param {Set<import('estree').Node>} sepNodes The nodes of `path.sep`.
* @param {import("eslint").Scope.Scope} globalScope The global scope object.
* @param {string[]} outNextChars The array to collect chars.

@@ -52,5 +52,5 @@ * @returns {void}

* Get the first char of a given node.
* @param {TemplateLiteral} node The `TemplateLiteral` node to get.
* @param {Set<Node>} sepNodes The nodes of `path.sep`.
* @param {import("escope").Scope} globalScope The global scope object.
* @param {import('estree').Node} node The `TemplateLiteral` node to get.
* @param {Set<import('estree').Node>} sepNodes The nodes of `path.sep`.
* @param {import("eslint").Scope.Scope} globalScope The global scope object.
* @param {string[]} outNextChars The array to collect chars.

@@ -127,2 +127,3 @@ * @returns {void}

}
/** @typedef {import('estree').Identifier & { parent: import('estree').Node }} Identifier */

@@ -133,4 +134,4 @@ /**

* @param {Identifier} node The `__dirname` or `__filename` node to check.
* @param {Set<Node>} sepNodes The nodes of `path.sep`.
* @param {import("escope").Scope} globalScope The global scope object.
* @param {Set<import('estree').Node>} sepNodes The nodes of `path.sep`.
* @param {import("eslint").Scope.Scope} globalScope The global scope object.
* @returns {boolean} `true` if the given Identifier node is followed by string

@@ -141,2 +142,3 @@ * concatenation with a path separator.

const parent = node.parent
/** @type {string[]} */
const nextChars = []

@@ -168,2 +170,3 @@

/** @type {import('eslint').Rule.RuleModule} */
module.exports = {

@@ -188,7 +191,8 @@ meta: {

return {
"Program:exit"(node) {
"Program:exit"(programNode) {
const sourceCode = context.sourceCode ?? context.getSourceCode() // TODO: just use context.sourceCode when dropping eslint < v9
const globalScope =
sourceCode.getScope?.(node) ?? context.getScope()
sourceCode.getScope?.(programNode) ?? context.getScope()
const tracker = new ReferenceTracker(globalScope)
/** @type {Set<import('estree').Node>} */
const sepNodes = new Set()

@@ -213,5 +217,13 @@

})) {
if (isConcat(node, sepNodes, globalScope)) {
if (
isConcat(
/** @type {Identifier} */ (node),
sepNodes,
globalScope
)
) {
context.report({
node: node.parent,
node: /** @type {import('estree').Node & { parent: import('estree').Node }}*/ (
node
).parent,
messageId: "usePathFunctions",

@@ -218,0 +230,0 @@ })

@@ -11,2 +11,10 @@ /**

const querySelector = [
`MemberExpression`,
`[computed!=true]`,
`[object.name="process"]`,
`[property.name="env"]`,
]
/** @type {import('eslint').Rule.RuleModule} */
module.exports = {

@@ -29,14 +37,5 @@ meta: {

return {
MemberExpression(node) {
const objectName = node.object.name
const propertyName = node.property.name
if (
objectName === "process" &&
!node.computed &&
propertyName &&
propertyName === "env"
) {
context.report({ node, messageId: "unexpectedProcessEnv" })
}
/** @param {import('estree').MemberExpression} node */
[querySelector.join("")](node) {
context.report({ node, messageId: "unexpectedProcessEnv" })
},

@@ -43,0 +42,0 @@ }

@@ -7,2 +7,10 @@ /**

const querySelector = [
`CallExpression > `,
`MemberExpression.callee`,
`[object.name="process"]`,
`[property.name="exit"]`,
]
/** @type {import('eslint').Rule.RuleModule} */
module.exports = {

@@ -25,5 +33,4 @@ meta: {

return {
"CallExpression > MemberExpression.callee[object.name = 'process'][property.name = 'exit']"(
node
) {
/** @param {import('estree').MemberExpression & { parent: import('estree').CallExpression}} node */
[querySelector.join("")](node) {
context.report({

@@ -30,0 +37,0 @@ node: node.parent,

@@ -10,2 +10,3 @@ /**

/** @type {import('eslint').Rule.RuleModule} */
module.exports = {

@@ -12,0 +13,0 @@ meta: {

@@ -11,2 +11,3 @@ /**

/** @type {import('eslint').Rule.RuleModule} */
module.exports = {

@@ -13,0 +14,0 @@ meta: {

@@ -14,3 +14,3 @@ /**

":function :not(MemberExpression) > Identifier[name=/Sync$/]",
]
].join(",")

@@ -24,4 +24,5 @@ const disallowedAtRootLevelSelector = [

":not(MemberExpression) > Identifier[name=/Sync$/]",
]
].join(",")
/** @type {import('eslint').Rule.RuleModule} */
module.exports = {

@@ -59,2 +60,7 @@ meta: {

return {
/**
* [node description]
* @param {import('estree').Identifier & {parent: import('estree').Node}} node
* @returns {void}
*/
[selector](node) {

@@ -61,0 +67,0 @@ context.report({

@@ -10,24 +10,6 @@ /**

const getNpmignore = require("../util/get-npmignore")
const getPackageJson = require("../util/get-package-json")
const { getPackageJson } = require("../util/get-package-json")
const { isBinFile } = require("../util/is-bin-file")
/**
* Checks whether or not a given path is a `bin` file.
*
* @param {string} filePath - A file path to check.
* @param {string|object|undefined} binField - A value of the `bin` field of `package.json`.
* @param {string} basedir - A directory path that `package.json` exists.
* @returns {boolean} `true` if the file is a `bin` file.
*/
function isBinFile(filePath, binField, basedir) {
if (!binField) {
return false
}
if (typeof binField === "string") {
return filePath === path.resolve(basedir, binField)
}
return Object.keys(binField).some(
key => filePath === path.resolve(basedir, binField[key])
)
}
/** @type {import('eslint').Rule.RuleModule} */
module.exports = {

@@ -67,9 +49,9 @@ meta: {

// Find package.json
const p = getPackageJson(rawFilePath)
if (!p) {
return
const packageJson = getPackageJson(rawFilePath)
if (typeof packageJson?.filePath !== "string") {
return {}
}
// Convert by convertPath option
const basedir = path.dirname(p.filePath)
const basedir = path.dirname(packageJson.filePath)
const relativePath = getConvertPath(context)(

@@ -81,3 +63,3 @@ path.relative(basedir, rawFilePath).replace(/\\/gu, "/")

// Check this file is bin.
if (!isBinFile(filePath, p.bin, basedir)) {
if (!isBinFile(filePath, packageJson.bin, basedir)) {
return

@@ -84,0 +66,0 @@ }

@@ -13,2 +13,3 @@ /**

/** @type {import('eslint').Rule.RuleModule} */
module.exports = {

@@ -15,0 +16,0 @@ meta: {

@@ -14,2 +14,3 @@ /**

/** @type {import('eslint').Rule.RuleModule} */
module.exports = {

@@ -16,0 +17,0 @@ meta: {

@@ -15,3 +15,4 @@ /**

const trackMap = {
/** @type {Record<'globals' | 'modules', import('../../unsupported-features/types.js').SupportVersionTraceMap>} */
const traceMap = {
globals: {

@@ -620,4 +621,6 @@ // Core js builtins

},
modules: {},
}
/** @type {import('eslint').Rule.RuleModule} */
module.exports = {

@@ -642,3 +645,3 @@ meta: {

enum: Array.from(
enumeratePropertyNames(trackMap.globals)
enumeratePropertyNames(traceMap.globals)
),

@@ -657,3 +660,3 @@ },

"Program:exit"() {
checkUnsupportedBuiltins(context, trackMap)
checkUnsupportedBuiltins(context, traceMap)
},

@@ -660,0 +663,0 @@ }

@@ -20,4 +20,4 @@ /**

/**
* @typedef {Object} ESSyntax
* @property {string[]} aliases
* @typedef ESSyntax
* @property {string[]} [aliases]
* @property {string | null} supported

@@ -28,3 +28,3 @@ * @property {string} [strictMode]

/**
* @typedef {Object} RuleMap
* @typedef RuleMap
* @property {string} ruleId

@@ -34,2 +34,3 @@ * @property {string} feature

* @property {import("semver").Range} supported
* @property {import("semver").Range} [strictMode]
* @property {boolean} deprecated

@@ -63,4 +64,8 @@ */

ignoreNames: ignoreNames,
supported: getSemverRange(meta.supported ?? "<0"),
strictMode: getSemverRange(meta.strictMode),
supported: /** @type {import("semver").Range} */ (
getSemverRange(meta.supported ?? "<0")
),
strictMode: meta.strictMode
? getSemverRange(meta.strictMode)
: undefined,
deprecated: Boolean(meta.deprecated),

@@ -72,6 +77,7 @@ }

* Parses the options.
* @param {RuleContext} context The rule context.
* @returns {{version:Range,ignores:Set<string>}} Parsed value.
* @param {import('eslint').Rule.RuleContext} context The rule context.
* @returns {{version: import('semver').Range,ignores:Set<string>}} Parsed value.
*/
function parseOptions(context) {
/** @type {{ ignores?: string[] }} */
const raw = context.options[0] || {}

@@ -86,5 +92,5 @@ const version = getConfiguredNodeVersion(context)

* Find the scope that a given node belongs to.
* @param {Scope} initialScope The initial scope to find.
* @param {Node} node The AST node.
* @returns {Scope} The scope that the node belongs to.
* @param {import('eslint').Scope.Scope} initialScope The initial scope to find.
* @param {import('estree').Node} node The AST node.
* @returns {import('eslint').Scope.Scope} The scope that the node belongs to.
*/

@@ -94,3 +100,3 @@ function normalizeScope(initialScope, node) {

while (scope && scope.block === node) {
while (scope?.block === node && scope.upper) {
scope = scope.upper

@@ -102,2 +108,7 @@ }

/**
* @param {import('eslint').Rule.RuleContext} context
* @param {import('estree').Node} node
* @returns {boolean}
*/
function isStrict(context, node) {

@@ -111,4 +122,4 @@ const sourceCode = context.sourceCode ?? context.getSourceCode() // TODO: just use context.sourceCode when dropping eslint < v9

* Define the visitor object as merging the rules of eslint-plugin-es-x.
* @param {RuleContext} context The rule context.
* @param {{version:Range,ignores:Set<string>}} options The options.
* @param {import('eslint').Rule.RuleContext} context The rule context.
* @param {ReturnType<parseOptions>} options The options.
* @returns {object} The defined visitor.

@@ -129,3 +140,6 @@ */

.map(rule => {
const esRule = esRules[rule.ruleId]
const esRule = /** @type {import('eslint').Rule.RuleModule} */ (
esRules[rule.ruleId]
)
/** @type {Partial<import('eslint').Rule.RuleContext>} */
const esContext = {

@@ -144,3 +158,10 @@ report(descriptor) {

if (rule.strictMode != null) {
if (isStrict(context, descriptor.node) === false) {
if (
isStrict(
context,
/** @type {{ node: import('estree').Node}} */ (
descriptor
).node
) === false
) {
descriptor.data.supported = rule.strictMode.raw

@@ -154,3 +175,3 @@ } else if (

descriptor.messageId =
const messageId =
rule.supported.raw === "<0"

@@ -160,3 +181,3 @@ ? "not-supported-yet"

super.report(descriptor)
super.report({ ...descriptor, messageId })
},

@@ -167,3 +188,5 @@ }

return esRule.create(esContext)
return esRule.create(
/** @type {import('eslint').Rule.RuleContext} */ (esContext)
)
})

@@ -173,2 +196,3 @@ .reduce(mergeVisitorsInPlace, {})

/** @type {import('eslint').Rule.RuleModule} */
module.exports = {

@@ -175,0 +199,0 @@ meta: {

@@ -136,7 +136,7 @@ {

"supported": ">=0.10.0",
"deprecated": true
"supported": ">=0.10.0"
},
"no-date-prototype-togmtstring": {
"supported": ">=0.10.0",
"deprecated": true
"supported": ">=0.10.0"
},

@@ -157,3 +157,3 @@ "no-default-parameters": {

"supported": ">=0.10.0",
"deprecated": true
"supported": ">=0.10.0"
},

@@ -246,3 +246,3 @@ "no-exponential-operators": {

"supported": ">=0.10.0",
"deprecated": true
"supported": ">=0.10.0"
},

@@ -530,3 +530,3 @@ "no-logical-assignment-operators": {

"supported": ">=0.10.0",
"deprecated": true
"supported": ">=0.10.0"
},

@@ -533,0 +533,0 @@ "no-string-fromcodepoint": {

@@ -19,6 +19,11 @@ /**

const trackMap = {
/**
* @typedef TraceMap
* @property {import('@eslint-community/eslint-utils').TraceMap<boolean>} globals
* @property {import('@eslint-community/eslint-utils').TraceMap<boolean>} modules
*/
const traceMap = {
globals: {
queueMicrotask: {
[READ]: { supported: ["12.0.0"], experimental: "11.0.0" },
[READ]: { supported: ["12.0.0"], experimental: ["11.0.0"] },
},

@@ -33,24 +38,25 @@ require: {

}
Object.assign(trackMap.globals, {
Buffer: trackMap.modules.buffer.Buffer,
Object.assign(traceMap.globals, {
Buffer: traceMap.modules.buffer.Buffer,
TextDecoder: {
...trackMap.modules.util.TextDecoder,
...traceMap.modules.util.TextDecoder,
[READ]: { supported: ["11.0.0"] },
},
TextEncoder: {
...trackMap.modules.util.TextEncoder,
...traceMap.modules.util.TextEncoder,
[READ]: { supported: ["11.0.0"] },
},
URL: {
...trackMap.modules.url.URL,
...traceMap.modules.url.URL,
[READ]: { supported: ["10.0.0"] },
},
URLSearchParams: {
...trackMap.modules.url.URLSearchParams,
...traceMap.modules.url.URLSearchParams,
[READ]: { supported: ["10.0.0"] },
},
console: trackMap.modules.console,
process: trackMap.modules.process,
console: traceMap.modules.console,
process: traceMap.modules.process,
})
/** @type {import('eslint').Rule.RuleModule} */
module.exports = {

@@ -76,4 +82,4 @@ meta: {

new Set([
...enumeratePropertyNames(trackMap.globals),
...enumeratePropertyNames(trackMap.modules),
...enumeratePropertyNames(traceMap.globals),
...enumeratePropertyNames(traceMap.modules),
])

@@ -93,3 +99,3 @@ ),

"Program:exit"() {
checkUnsupportedBuiltins(context, trackMap)
checkUnsupportedBuiltins(context, traceMap)
},

@@ -96,0 +102,0 @@ }

@@ -10,3 +10,3 @@ /**

const trackMap = {
const traceMap = {
globals: {

@@ -16,8 +16,8 @@ Buffer: { [READ]: true },

modules: {
buffer: {
Buffer: { [READ]: true },
},
buffer: { Buffer: { [READ]: true } },
"node:buffer": { Buffer: { [READ]: true } },
},
}
/** @type {import('eslint').Rule.RuleModule} */
module.exports = {

@@ -45,3 +45,3 @@ meta: {

"Program:exit"() {
checkForPreferGlobal(context, trackMap)
checkForPreferGlobal(context, traceMap)
},

@@ -48,0 +48,0 @@ }

@@ -10,3 +10,3 @@ /**

const trackMap = {
const traceMap = {
globals: {

@@ -17,5 +17,7 @@ console: { [READ]: true },

console: { [READ]: true },
"node:console": { [READ]: true },
},
}
/** @type {import('eslint').Rule.RuleModule} */
module.exports = {

@@ -42,3 +44,3 @@ meta: {

"Program:exit"() {
checkForPreferGlobal(context, trackMap)
checkForPreferGlobal(context, traceMap)
},

@@ -45,0 +47,0 @@ }

@@ -10,3 +10,3 @@ /**

const trackMap = {
const traceMap = {
globals: {

@@ -17,5 +17,7 @@ process: { [READ]: true },

process: { [READ]: true },
"node:process": { [READ]: true },
},
}
/** @type {import('eslint').Rule.RuleModule} */
module.exports = {

@@ -42,3 +44,3 @@ meta: {

"Program:exit"() {
checkForPreferGlobal(context, trackMap)
checkForPreferGlobal(context, traceMap)
},

@@ -45,0 +47,0 @@ }

@@ -10,3 +10,3 @@ /**

const trackMap = {
const traceMap = {
globals: {

@@ -16,8 +16,8 @@ TextDecoder: { [READ]: true },

modules: {
util: {
TextDecoder: { [READ]: true },
},
util: { TextDecoder: { [READ]: true } },
"node:util": { TextDecoder: { [READ]: true } },
},
}
/** @type {import('eslint').Rule.RuleModule} */
module.exports = {

@@ -45,3 +45,3 @@ meta: {

"Program:exit"() {
checkForPreferGlobal(context, trackMap)
checkForPreferGlobal(context, traceMap)
},

@@ -48,0 +48,0 @@ }

@@ -10,3 +10,3 @@ /**

const trackMap = {
const traceMap = {
globals: {

@@ -16,8 +16,8 @@ TextEncoder: { [READ]: true },

modules: {
util: {
TextEncoder: { [READ]: true },
},
util: { TextEncoder: { [READ]: true } },
"node:util": { TextEncoder: { [READ]: true } },
},
}
/** @type {import('eslint').Rule.RuleModule} */
module.exports = {

@@ -45,3 +45,3 @@ meta: {

"Program:exit"() {
checkForPreferGlobal(context, trackMap)
checkForPreferGlobal(context, traceMap)
},

@@ -48,0 +48,0 @@ }

@@ -10,3 +10,3 @@ /**

const trackMap = {
const traceMap = {
globals: {

@@ -16,8 +16,8 @@ URLSearchParams: { [READ]: true },

modules: {
url: {
URLSearchParams: { [READ]: true },
},
url: { URLSearchParams: { [READ]: true } },
"node:url": { URLSearchParams: { [READ]: true } },
},
}
/** @type {import('eslint').Rule.RuleModule} */
module.exports = {

@@ -45,3 +45,3 @@ meta: {

"Program:exit"() {
checkForPreferGlobal(context, trackMap)
checkForPreferGlobal(context, traceMap)
},

@@ -48,0 +48,0 @@ }

@@ -10,3 +10,3 @@ /**

const trackMap = {
const traceMap = {
globals: {

@@ -16,8 +16,8 @@ URL: { [READ]: true },

modules: {
url: {
URL: { [READ]: true },
},
url: { URL: { [READ]: true } },
"node:url": { URL: { [READ]: true } },
},
}
/** @type {import('eslint').Rule.RuleModule} */
module.exports = {

@@ -44,3 +44,3 @@ meta: {

"Program:exit"() {
checkForPreferGlobal(context, trackMap)
checkForPreferGlobal(context, traceMap)
},

@@ -47,0 +47,0 @@ }

@@ -16,2 +16,10 @@ /**

const supportedRangeForEsm = /** @type {import('semver').Range} */ (
getSemverRange("^12.20.0 || >= 14.13.1")
)
const supportedRangeForCjs = /** @type {import('semver').Range} */ (
getSemverRange("^14.18.0 || >= 16.0.0")
)
/** @type {import('eslint').Rule.RuleModule} */
module.exports = {

@@ -41,2 +49,9 @@ meta: {

create(context) {
/**
* @param {import('estree').Node} node
* @param {object} options
* @param {string} options.name
* @param {number} options.argumentsLength
* @returns {node is import('estree').CallExpression}
*/
function isCallExpression(node, { name, argumentsLength }) {

@@ -65,2 +80,6 @@ if (node?.type !== "CallExpression") {

/**
* @param {import('estree').Node} node
* @returns {node is import('estree').Literal}
*/
function isStringLiteral(node) {

@@ -70,25 +89,34 @@ return node?.type === "Literal" && typeof node.type === "string"

/**
* @param {import('estree').Node | undefined} node
* @returns {node is import('estree').CallExpression}
*/
function isStaticRequire(node) {
return (
node != null &&
isCallExpression(node, {
name: "require",
argumentsLength: 1,
}) && isStringLiteral(node.arguments[0])
}) &&
isStringLiteral(node.arguments[0])
)
}
/**
* @param {import('eslint').Rule.RuleContext} context
* @param {import('../util/import-target.js').ModuleStyle} moduleStyle
* @returns {boolean}
*/
function isEnablingThisRule(context, moduleStyle) {
const version = getConfiguredNodeVersion(context)
const supportedVersionForEsm = "^12.20.0 || >= 14.13.1"
// Only check Node.js version because this rule is meaningless if configured Node.js version doesn't match semver range.
if (!version.intersects(getSemverRange(supportedVersionForEsm))) {
if (!version.intersects(supportedRangeForEsm)) {
return false
}
const supportedVersionForCjs = "^14.18.0 || >= 16.0.0"
// Only check when using `require`
if (
moduleStyle === "require" &&
!version.intersects(getSemverRange(supportedVersionForCjs))
!version.intersects(supportedRangeForCjs)
) {

@@ -101,2 +129,3 @@ return false

/** @type {import('../util/import-target.js')[]} */
const targets = []

@@ -125,3 +154,3 @@ return [

const { value } = node
const { value } = /** @type {{ value: string }}*/ (node)
if (

@@ -143,3 +172,4 @@ typeof value !== "string" ||

fix(fixer) {
const firstCharacterIndex = node.range[0] + 1
const firstCharacterIndex =
(node?.range?.[0] ?? 0) + 1
return fixer.replaceTextRange(

@@ -146,0 +176,0 @@ [firstCharacterIndex, firstCharacterIndex],

@@ -13,3 +13,4 @@ /**

const trackMap = {
/** @type {import('@eslint-community/eslint-utils').TraceMap<boolean>} */
const traceMap = {
dns: {

@@ -36,4 +37,5 @@ lookup: { [CALL]: true },

}
trackMap["node:dns"] = trackMap.dns
traceMap["node:dns"] = traceMap.dns
/** @type {import('eslint').Rule.RuleModule} */
module.exports = {

@@ -62,4 +64,4 @@ meta: {

const references = [
...tracker.iterateCjsReferences(trackMap),
...tracker.iterateEsmReferences(trackMap),
...tracker.iterateCjsReferences(traceMap),
...tracker.iterateEsmReferences(traceMap),
]

@@ -66,0 +68,0 @@

@@ -9,3 +9,4 @@ /**

const trackMap = {
/** @type {import('@eslint-community/eslint-utils').TraceMap<boolean>} */
const traceMap = {
fs: {

@@ -38,4 +39,5 @@ access: { [CALL]: true },

}
trackMap["node:fs"] = trackMap.fs
traceMap["node:fs"] = traceMap.fs
/** @type {import('eslint').Rule.RuleModule} */
module.exports = {

@@ -63,4 +65,4 @@ meta: {

const references = [
...tracker.iterateCjsReferences(trackMap),
...tracker.iterateEsmReferences(trackMap),
...tracker.iterateCjsReferences(traceMap),
...tracker.iterateEsmReferences(traceMap),
]

@@ -67,0 +69,0 @@

@@ -8,2 +8,3 @@ /* eslint-disable eslint-plugin/prefer-message-ids */

/** @type {typeof import('../types-code-path-analysis/code-path-analyzer.js')} */
const CodePathAnalyzer = safeRequire(

@@ -13,2 +14,3 @@ "eslint/lib/linter/code-path-analysis/code-path-analyzer",

)
/** @type {typeof import('../types-code-path-analysis/code-path-segment.js')} */
const CodePathSegment = safeRequire(

@@ -18,2 +20,3 @@ "eslint/lib/linter/code-path-analysis/code-path-segment",

)
/** @type {typeof import('../types-code-path-analysis/code-path.js')} */
const CodePath = safeRequire(

@@ -24,4 +27,3 @@ "eslint/lib/linter/code-path-analysis/code-path",

const originalLeaveNode =
CodePathAnalyzer && CodePathAnalyzer.prototype.leaveNode
const originalLeaveNode = CodePathAnalyzer?.prototype?.leaveNode

@@ -31,3 +33,3 @@ /**

* @param {...string} moduleNames - module names to import.
* @returns {object|null} The imported object, or null.
* @returns {*} The imported object, or null.
*/

@@ -38,3 +40,3 @@ function safeRequire(...moduleNames) {

return require(moduleName)
} catch (_err) {
} catch {
// Ignore.

@@ -50,4 +52,4 @@ }

*
* @param {CodePathAnalyzer} analyzer - The instance.
* @param {ASTNode} node - The current AST node.
* @param {import('../types-code-path-analysis/code-path-analyzer.js')} analyzer - The instance.
* @param {import('eslint').Rule.Node} node - The current AST node.
* @returns {void}

@@ -105,3 +107,3 @@ */

*
* @param {ASTNode} node - A node to check.
* @param {import('eslint').Rule.Node} node - A node to check.
* @returns {boolean} `true` if the node is `process.exit()`.

@@ -125,4 +127,4 @@ */

*
* @this CodePathAnalyzer
* @param {ASTNode} node - A node to be left.
* @this {import('../types-code-path-analysis/code-path-analyzer.js')}
* @param {import('eslint').Rule.Node} node - A node to be left.
* @returns {void}

@@ -156,2 +158,3 @@ */

/** @type {import('eslint').Rule.RuleModule} */
module.exports = {

@@ -158,0 +161,0 @@ meta: {

@@ -15,5 +15,5 @@ /**

replacedBy: ["n/hashbang"],
docs: { ...hashbang.meta.docs, recommended: false },
docs: { ...hashbang.meta?.docs, recommended: false },
},
create: hashbang.create,
}

@@ -5,3 +5,3 @@ "use strict"

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
const assert = {

@@ -45,24 +45,24 @@ assert: { [READ]: { supported: ["0.5.9"] } },

assert.strict = {
...assert,
[READ]: { supported: ["9.9.0", "8.13.0"] },
...assert,
}
/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
module.exports = {
assert: {
...assert,
[READ]: { supported: ["0.1.21"] },
...assert,
},
"node:assert": {
...assert,
[READ]: { supported: ["14.13.1", "12.20.0"] },
...assert,
},
"assert/strict": {
...assert.strict,
[READ]: { supported: ["15.0.0"] },
...assert.strict,
},
"node:assert/strict": {
...assert.strict,
[READ]: { supported: ["15.0.0"] },
...assert.strict,
},
}

@@ -5,3 +5,3 @@ "use strict"

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
const async_hooks = {

@@ -29,3 +29,3 @@ createHook: { [READ]: { experimental: ["8.1.0"] } },

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
module.exports = {

@@ -32,0 +32,0 @@ async_hooks: {

@@ -5,3 +5,3 @@ "use strict"

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
const buffer = {

@@ -46,3 +46,3 @@ constants: { [READ]: { supported: ["8.2.0"] } },

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
module.exports = {

@@ -49,0 +49,0 @@ buffer: {

@@ -5,3 +5,3 @@ "use strict"

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
const child_process = {

@@ -18,3 +18,3 @@ exec: { [READ]: { supported: ["0.1.90"] } },

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
module.exports = {

@@ -21,0 +21,0 @@ child_process: {

@@ -5,3 +5,3 @@ "use strict"

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
const cluster = {

@@ -22,3 +22,3 @@ isMaster: { [READ]: { supported: ["0.8.1"], deprecated: ["16.0.0"] } },

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
module.exports = {

@@ -25,0 +25,0 @@ cluster: {

@@ -5,3 +5,3 @@ "use strict"

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
const console = {

@@ -38,3 +38,3 @@ profile: { [READ]: { supported: ["8.0.0"] } },

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
module.exports = {

@@ -41,0 +41,0 @@ console: {

@@ -5,3 +5,3 @@ "use strict"

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
const WebCrypto = {

@@ -28,3 +28,3 @@ [READ]: { experimental: ["15.0.0"], supported: ["19.0.0"] },

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
const crypto = {

@@ -121,3 +121,3 @@ constants: { [READ]: { supported: ["6.3.0"] } },

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
module.exports = {

@@ -124,0 +124,0 @@ crypto: {

@@ -5,3 +5,3 @@ "use strict"

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
const dgram = {

@@ -12,3 +12,3 @@ createSocket: { [READ]: { supported: ["0.1.99"] } },

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
module.exports = {

@@ -15,0 +15,0 @@ dgram: {

@@ -5,3 +5,3 @@ "use strict"

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
const diagnostics_channel = {

@@ -17,3 +17,3 @@ hasSubscribers: { [READ]: { supported: ["15.1.0", "14.17.0"] } },

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
module.exports = {

@@ -20,0 +20,0 @@ diagnostics_channel: {

@@ -5,3 +5,3 @@ "use strict"

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
const dns = {

@@ -60,3 +60,3 @@ Resolver: { [READ]: { supported: ["8.3.0"] } },

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
module.exports = {

@@ -63,0 +63,0 @@ dns: { ...dns, [READ]: { supported: ["0.1.16"] } },

@@ -5,3 +5,3 @@ "use strict"

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
const domain = {

@@ -12,3 +12,3 @@ create: { [READ]: { supported: ["0.7.8"] } },

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
module.exports = {

@@ -15,0 +15,0 @@ domain: {

@@ -5,3 +5,3 @@ "use strict"

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
const EventEmitterStatic = {

@@ -31,3 +31,3 @@ defaultMaxListeners: { [READ]: { supported: ["0.11.2"] } },

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
const events = {

@@ -59,3 +59,3 @@ Event: { [READ]: { experimental: ["14.5.0"], supported: ["15.4.0"] } },

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
module.exports = {

@@ -62,0 +62,0 @@ events: {

@@ -5,3 +5,3 @@ "use strict"

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
const promises_api = {

@@ -42,3 +42,3 @@ constants: { [READ]: { supported: ["18.4.0", "16.17.0"] } },

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
const callback_api = {

@@ -99,3 +99,3 @@ access: { [READ]: { supported: ["0.11.15"] } },

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
const synchronous_api = {

@@ -150,3 +150,3 @@ accessSync: { [READ]: { supported: ["0.11.15"] } },

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
const fs = {

@@ -174,3 +174,3 @@ promises: {

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
module.exports = {

@@ -177,0 +177,0 @@ fs: {

@@ -5,3 +5,3 @@ "use strict"

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
const http = {

@@ -26,3 +26,3 @@ METHODS: { [READ]: { supported: ["0.11.8"] } },

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
module.exports = {

@@ -29,0 +29,0 @@ http: {

@@ -5,3 +5,3 @@ "use strict"

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
const http2 = {

@@ -28,3 +28,3 @@ constants: { [READ]: { supported: ["8.4.0"] } },

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
module.exports = {

@@ -31,0 +31,0 @@ http2: {

@@ -5,3 +5,3 @@ "use strict"

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
const http = {

@@ -16,3 +16,3 @@ globalAgent: { [READ]: { supported: ["0.5.9"] } },

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
module.exports = {

@@ -19,0 +19,0 @@ http: {

@@ -5,3 +5,3 @@ "use strict"

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
const common_objects = {

@@ -15,3 +15,3 @@ console: { [READ]: { supported: ["8.0.0"] } },

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
const promises_api = {

@@ -22,3 +22,3 @@ Session: { [READ]: { supported: ["19.0.0"] } },

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
const callback_api = {

@@ -29,3 +29,3 @@ Session: { [READ]: { supported: ["8.0.0"] } },

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
module.exports = {

@@ -32,0 +32,0 @@ inspector: {

@@ -5,3 +5,3 @@ "use strict"

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
const Module = {

@@ -25,3 +25,3 @@ builtinModules: { [READ]: { supported: ["9.3.0", "8.10.0", "6.13.0"] } },

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
module.exports = {

@@ -28,0 +28,0 @@ module: {

@@ -5,3 +5,3 @@ "use strict"

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
const net = {

@@ -28,3 +28,3 @@ connect: { [READ]: { supported: ["0.0.1"] } },

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
module.exports = {

@@ -31,0 +31,0 @@ net: {

@@ -5,3 +5,3 @@ "use strict"

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
const os = {

@@ -36,3 +36,3 @@ EOL: { [READ]: { supported: ["0.7.8"] } },

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
module.exports = {

@@ -39,0 +39,0 @@ os: {

@@ -5,3 +5,3 @@ "use strict"

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
const path = {

@@ -23,3 +23,3 @@ delimiter: { [READ]: { supported: ["0.9.3"] } },

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
module.exports = {

@@ -26,0 +26,0 @@ path: {

@@ -5,3 +5,3 @@ "use strict"

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
const perf_hooks = {

@@ -24,3 +24,3 @@ performance: { [READ]: { supported: ["8.5.0"] } },

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
module.exports = {

@@ -27,0 +27,0 @@ perf_hooks: {

@@ -5,3 +5,3 @@ "use strict"

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
const process = {

@@ -121,3 +121,3 @@ allowedNodeEnvironmentFlags: { [READ]: { supported: ["10.10.0"] } },

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
module.exports = {

@@ -124,0 +124,0 @@ process: {

@@ -5,3 +5,3 @@ "use strict"

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
const punycode = {

@@ -16,3 +16,3 @@ ucs2: { [READ]: { supported: ["0.7.0"] } },

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
module.exports = {

@@ -19,0 +19,0 @@ punycode: {

@@ -5,3 +5,3 @@ "use strict"

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
const querystring = {

@@ -16,3 +16,3 @@ decode: { [READ]: { supported: ["0.1.99"] } },

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
module.exports = {

@@ -19,0 +19,0 @@ querystring: {

@@ -5,3 +5,3 @@ "use strict"

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
const promises_api = {

@@ -13,3 +13,3 @@ createInterface: { [READ]: { supported: ["17.0.0"] } },

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
const readline = {

@@ -30,3 +30,3 @@ promises: {

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
module.exports = {

@@ -33,0 +33,0 @@ readline: {

@@ -7,3 +7,3 @@ "use strict"

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
const Readable = {

@@ -17,3 +17,3 @@ [READ]: { supported: ["0.9.4"] },

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
const Writable = {

@@ -25,3 +25,3 @@ [READ]: { supported: ["0.9.4"] },

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
const Duplex = {

@@ -36,3 +36,3 @@ [READ]: { supported: ["0.9.4"] },

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
const StreamPromise = {

@@ -43,3 +43,3 @@ pipeline: { [READ]: { supported: ["15.0.0"] } },

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
const Stream = {

@@ -66,3 +66,3 @@ promises: {

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
const StreamWeb = {

@@ -100,3 +100,3 @@ ReadableStream: {

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
module.exports = {

@@ -130,10 +130,4 @@ stream: {

"stream/consumers": {
[READ]: { supported: ["16.7.0"] },
...StreamConsumer,
},
"node:stream/consumers": {
[READ]: { supported: ["16.7.0"] },
...StreamConsumer,
},
"stream/consumers": { ...StreamConsumer },
"node:stream/consumers": { ...StreamConsumer },
}

@@ -5,3 +5,3 @@ "use strict"

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
const string_decoder = {

@@ -11,3 +11,3 @@ StringDecoder: { [READ]: { supported: ["0.1.99"] } },

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
module.exports = {

@@ -14,0 +14,0 @@ string_decoder: {

@@ -5,3 +5,3 @@ "use strict"

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
const test = {

@@ -38,3 +38,3 @@ run: { [READ]: { supported: ["18.9.0", "16.19.0"] } },

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
module.exports = {

@@ -41,0 +41,0 @@ "node:test": {

@@ -5,3 +5,3 @@ "use strict"

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
const promises_api = {

@@ -17,3 +17,3 @@ setTimeout: { [READ]: { supported: ["15.0.0"] } },

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
const timers = {

@@ -36,3 +36,3 @@ Immediate: { [READ]: { supported: ["0.9.1"] } },

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
module.exports = {

@@ -39,0 +39,0 @@ timers: {

@@ -5,3 +5,3 @@ "use strict"

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
const tls = {

@@ -28,3 +28,3 @@ rootCertificates: { [READ]: { supported: ["12.3.0"] } },

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
module.exports = {

@@ -31,0 +31,0 @@ tls: {

@@ -5,3 +5,3 @@ "use strict"

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
const trace_events = {

@@ -12,3 +12,3 @@ createTracing: { [READ]: { supported: ["10.0.0"] } },

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
module.exports = {

@@ -15,0 +15,0 @@ trace_events: {

@@ -5,3 +5,3 @@ "use strict"

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
const tty = {

@@ -13,3 +13,3 @@ isatty: { [READ]: { supported: ["0.5.8"] } },

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
module.exports = {

@@ -16,0 +16,0 @@ tty: {

@@ -5,3 +5,3 @@ "use strict"

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
const url = {

@@ -24,3 +24,3 @@ domainToASCII: { [READ]: { supported: ["7.4.0", "6.13.0"] } },

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
module.exports = {

@@ -27,0 +27,0 @@ url: {

@@ -5,3 +5,3 @@ "use strict"

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
const types = {

@@ -56,3 +56,3 @@ [READ]: { supported: ["10.0.0"] },

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
const deprecated = {

@@ -80,3 +80,3 @@ _extend: { [READ]: { supported: ["0.7.5"], deprecated: ["6.0.0"] } },

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
const util = {

@@ -121,3 +121,3 @@ promisify: {

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
module.exports = {

@@ -124,0 +124,0 @@ util: util,

@@ -5,3 +5,3 @@ "use strict"

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
const v8 = {

@@ -48,3 +48,3 @@ serialize: { [READ]: { supported: ["8.0.0"] } },

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
module.exports = {

@@ -51,0 +51,0 @@ v8: { ...v8, [READ]: { supported: ["1.0.0"] } },

@@ -5,3 +5,3 @@ "use strict"

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
const vm = {

@@ -22,3 +22,3 @@ compileFunction: { [READ]: { supported: ["10.10.0"] } },

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
module.exports = {

@@ -25,0 +25,0 @@ vm: vm,

@@ -5,3 +5,3 @@ "use strict"

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
const wasi = {

@@ -11,3 +11,3 @@ WASI: { [READ]: { supported: ["13.3.0", "12.16.0"] } },

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
module.exports = {

@@ -14,0 +14,0 @@ wasi: wasi,

@@ -5,3 +5,3 @@ "use strict"

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
const worker_threads = {

@@ -38,3 +38,3 @@ isMainThread: { [READ]: { supported: ["10.5.0"] } },

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
module.exports = {

@@ -41,0 +41,0 @@ worker_threads: {

@@ -5,3 +5,3 @@ "use strict"

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
const zlib = {

@@ -47,3 +47,3 @@ constants: { [READ]: { supported: ["7.0.0"] } },

/** @type {import('../types.js').SupportVersionTree} */
/** @type {import('../types.js').SupportVersionTraceMap} */
module.exports = {

@@ -50,0 +50,0 @@ zlib: zlib,

"use strict"
/** @type {import('./types.js').SupportVersionTree} */
/** @type {import('./types.js').SupportVersionTraceMap} */
const NodeBuiltinModules = {

@@ -5,0 +5,0 @@ ...require("./node-builtins-modules/assert.js"),

"use strict"
/**
* @typedef {Object} SupportInfo
* @property {string[]} experimental The node versions in which experimental support was added
* @property {string[]} supported The node versions in which stable support was added
* @property {string[]} deprecated The node versions in which support was removed
* @typedef {(
* | import("@eslint-community/eslint-utils").READ
* | import("@eslint-community/eslint-utils").CALL
* | import("@eslint-community/eslint-utils").CONSTRUCT
* )} UTIL_SYMBOL
*/
/**
* @typedef {{
* [key: readonly unique symbol]: SupportInfo | undefined;
* [key: string]: SupportVersionTree | undefined;
* }} SupportVersionTree
* @typedef SupportInfo
* @property {string[]} [experimental] The node versions in which experimental support was added
* @property {string[]} [supported] The node versions in which stable support was added
* @property {string[]} [deprecated] The node versions in which support was removed
*/
/**
* @typedef DeprecatedInfo
* @property {string} since
* @property {string|{ name: string, supported: string }[]|null} replacedBy
*/
/** @typedef {import('@eslint-community/eslint-utils').TraceMap<DeprecatedInfo>} DeprecatedInfoTraceMap */
/** @typedef {import('@eslint-community/eslint-utils').TraceMap<SupportInfo>} SupportVersionTraceMap */
/**
* @typedef SupportVersionBuiltins
* @property {SupportVersionTraceMap} globals
* @property {SupportVersionTraceMap} modules
*/
module.exports = {}

@@ -11,7 +11,7 @@ /**

const isTypescript = require("./is-typescript")
const mapTypescriptExtension = require("../util/map-typescript-extension")
const { convertJsExtensionToTs } = require("../util/map-typescript-extension")
/**
* Reports a missing file from ImportTarget
* @param {RuleContext} context - A context to report.
* @param {import('eslint').Rule.RuleContext} context - A context to report.
* @param {import('../util/import-target.js')} target - A list of target information to check.

@@ -23,5 +23,7 @@ * @returns {void}

node: target.node,
loc: target.node.loc,
loc: /** @type {import('eslint').AST.SourceLocation} */ (
target.node.loc
),
messageId: "notFound",
data: target,
data: /** @type {Record<string, *>} */ (target),
})

@@ -36,3 +38,3 @@ }

*
* @param {RuleContext} context - A context to report.
* @param {import('eslint').Rule.RuleContext} context - A context to report.
* @param {import('../util/import-target.js')[]} targets - A list of target information to check.

@@ -44,3 +46,3 @@ * @returns {void}

for (const target of targets) {
target: for (const target of targets) {
if (

@@ -55,31 +57,33 @@ target.moduleName != null &&

if (target.moduleName != null) {
if (
target.moduleName != null ||
target.filePath == null ||
exists(target.filePath)
) {
continue
}
let missingFile =
target.filePath == null ? false : !exists(target.filePath)
if (isTypescript(context) === false) {
markMissing(context, target)
continue
}
if (missingFile && isTypescript(context)) {
const parsed = path.parse(target.filePath)
const pathWithoutExt = path.resolve(parsed.dir, parsed.name)
const parsed = path.parse(target.filePath)
const pathWithoutExt = path.resolve(parsed.dir, parsed.name)
const reversedExts = mapTypescriptExtension(
context,
target.filePath,
parsed.ext,
true
)
const reversedPaths = reversedExts.map(
reversedExt => pathWithoutExt + reversedExt
)
missingFile = reversedPaths.every(
reversedPath =>
target.moduleName == null && !exists(reversedPath)
)
const reversedExtensions = convertJsExtensionToTs(
context,
target.filePath,
parsed.ext
)
for (const reversedExtension of reversedExtensions) {
const reversedPath = pathWithoutExt + reversedExtension
if (exists(reversedPath)) {
continue target
}
}
if (missingFile) {
markMissing(context, target)
}
markMissing(context, target)
}

@@ -86,0 +90,0 @@ }

@@ -8,3 +8,3 @@ /**

const getAllowModules = require("./get-allow-modules")
const getPackageJson = require("./get-package-json")
const { getPackageJson } = require("./get-package-json")

@@ -16,5 +16,5 @@ /**

*
* @param {RuleContext} context - A context to report.
* @param {import('eslint').Rule.RuleContext} context - A context to report.
* @param {string} filePath - The current file path.
* @param {ImportTarget[]} targets - A list of target information to check.
* @param {import('./import-target.js')[]} targets - A list of target information to check.
* @returns {void}

@@ -48,5 +48,7 @@ */

node: target.node,
loc: target.node.loc,
loc: /** @type {import('eslint').AST.SourceLocation} */ (
target.node.loc
),
messageId: "extraneous",
data: target,
data: /** @type {Record<string, *>} */ (target),
})

@@ -53,0 +55,0 @@ }

@@ -8,5 +8,10 @@ /**

const { ReferenceTracker } = require("@eslint-community/eslint-utils")
const extendTrackmapWithNodePrefix = require("./extend-trackmap-with-node-prefix")
/**
* @typedef TraceMap
* @property {import('@eslint-community/eslint-utils').TraceMap<boolean>} globals
* @property {import('@eslint-community/eslint-utils').TraceMap<boolean>} modules
*/
/**
* Verifier for `prefer-global/*` rules.

@@ -17,8 +22,8 @@ */

* Initialize this instance.
* @param {RuleContext} context The rule context to report.
* @param {{modules:object,globals:object}} trackMap The track map.
* @param {import('eslint').Rule.RuleContext} context The rule context to report.
* @param {TraceMap} traceMap The track map.
*/
constructor(context, trackMap) {
constructor(context, traceMap) {
this.context = context
this.trackMap = trackMap
this.traceMap = traceMap
this.verify =

@@ -35,3 +40,3 @@ context.options[0] === "never"

verifyToPreferGlobals() {
const { context, trackMap } = this
const { context, traceMap } = this
const sourceCode = context.sourceCode ?? context.getSourceCode() // TODO: just use context.sourceCode when dropping eslint < v9

@@ -44,7 +49,5 @@ const scope =

const modules = extendTrackmapWithNodePrefix(trackMap.modules)
for (const { node } of [
...tracker.iterateCjsReferences(modules),
...tracker.iterateEsmReferences(modules),
...tracker.iterateCjsReferences(traceMap.modules),
...tracker.iterateEsmReferences(traceMap.modules),
]) {

@@ -60,3 +63,3 @@ context.report({ node, messageId: "preferGlobal" })

verifyToPreferModules() {
const { context, trackMap } = this
const { context, traceMap } = this
const sourceCode = context.sourceCode ?? context.getSourceCode() // TODO: just use context.sourceCode when dropping eslint < v9

@@ -68,3 +71,3 @@ const scope =

for (const { node } of tracker.iterateGlobalReferences(
trackMap.globals
traceMap.globals
)) {

@@ -76,4 +79,9 @@ context.report({ node, messageId: "preferModule" })

module.exports = function checkForPreferGlobal(context, trackMap) {
new Verifier(context, trackMap).verify()
/**
* @param {import('eslint').Rule.RuleContext} context
* @param {TraceMap} traceMap
* @returns {void}
*/
module.exports = function checkForPreferGlobal(context, traceMap) {
new Verifier(context, traceMap).verify()
}

@@ -11,3 +11,3 @@ /**

const getNpmignore = require("./get-npmignore")
const getPackageJson = require("./get-package-json")
const { getPackageJson } = require("./get-package-json")

@@ -19,10 +19,10 @@ /**

*
* @param {RuleContext} context - A context to report.
* @param {import('eslint').Rule.RuleContext} context - A context to report.
* @param {string} filePath - The current file path.
* @param {ImportTarget[]} targets - A list of target information to check.
* @param {import('./import-target.js')[]} targets - A list of target information to check.
* @returns {void}
*/
exports.checkPublish = function checkPublish(context, filePath, targets) {
const packageInfo = getPackageJson(filePath)
if (!packageInfo) {
const packageJson = getPackageJson(filePath)
if (typeof packageJson?.filePath !== "string") {
return

@@ -33,3 +33,3 @@ }

// More information: https://docs.npmjs.com/cli/v8/configuring-npm/package-json#private
if (packageInfo.private === true) {
if (packageJson.private === true) {
return

@@ -40,4 +40,5 @@ }

const convertPath = getConvertPath(context)
const basedir = path.dirname(packageInfo.filePath)
const basedir = path.dirname(packageJson.filePath)
/** @type {(fullPath: string) => string} */
const toRelative = fullPath => {

@@ -49,11 +50,9 @@ const retv = path.relative(basedir, fullPath).replace(/\\/gu, "/")

const devDependencies = new Set(
Object.keys(packageInfo.devDependencies || {})
Object.keys(packageJson.devDependencies ?? {})
)
const dependencies = new Set(
[].concat(
Object.keys(packageInfo.dependencies || {}),
Object.keys(packageInfo.peerDependencies || {}),
Object.keys(packageInfo.optionalDependencies || {})
)
)
const dependencies = new Set([
...Object.keys(packageJson?.dependencies ?? {}),
...Object.keys(packageJson?.peerDependencies ?? {}),
...Object.keys(packageJson?.optionalDependencies ?? {}),
])

@@ -82,3 +81,5 @@ if (!npmignore.match(toRelative(filePath))) {

node: target.node,
loc: target.node.loc,
loc: /** @type {import('estree').SourceLocation} */ (
target.node.loc
),
messageId: "notPublished",

@@ -85,0 +86,0 @@ data: { name: target.moduleName || target.name },

@@ -12,3 +12,3 @@ /**

/**
* @typedef {Object} DefinitionData
* @typedef DefinitionData
* @property {string | string[]} name The name to disallow.

@@ -20,5 +20,5 @@ * @property {string} [message] The custom message to show.

* Check if matched or not.
* @param {InstanceType<Minimatch>} matcher The matcher.
* @param {Minimatch} matcher The matcher.
* @param {boolean} absolute The flag that the matcher is for absolute paths.
* @param {ImportTarget} importee The importee information.
* @param {import('./import-target.js')} importee The importee information.
*/

@@ -59,3 +59,3 @@ function match(matcher, absolute, { filePath, name }) {

* Check if a given importee is disallowed.
* @param {ImportTarget} importee The importee to check.
* @param {import('./import-target.js')} importee The importee to check.
* @returns {boolean} `true` if the importee is disallowed.

@@ -88,4 +88,4 @@ */

* Create restrictions.
* @param {(string | DefinitionData | GlobDefinition)[]} defs Definitions.
* @returns {(Restriction | GlobRestriction)[]} Created restrictions.
* @param {(string | DefinitionData)[]} defs Definitions.
* @returns {(Restriction)[]} Created restrictions.
*/

@@ -98,4 +98,4 @@ function createRestrictions(defs) {

* Checks if given importees are disallowed or not.
* @param {RuleContext} context - A context to report.
* @param {ImportTarget[]} targets - A list of target information to check.
* @param {import('eslint').Rule.RuleContext} context - A context to report.
* @param {import('./import-target.js')[]} targets - A list of target information to check.
* @returns {void}

@@ -102,0 +102,0 @@ */

@@ -14,11 +14,8 @@ /**

/**
* @typedef {Object} SupportInfo
* @property {string[]} supported The stably supported version. If `null` is present, it hasn't been supported yet.
* @property {string} [experimental] The added version as experimental.
*/
/**
* Parses the options.
* @param {RuleContext} context The rule context.
* @returns {{version:Range,ignores:Set<string>}} Parsed value.
* @param {import('eslint').Rule.RuleContext} context The rule context.
* @returns {Readonly<{
* version: import('semver').Range,
* ignores: Set<string>
* }>} Parsed value.
*/

@@ -35,4 +32,4 @@ function parseOptions(context) {

* Check if it has been supported.
* @param {SupportInfo} info The support info.
* @param {Range} configured The configured version range.
* @param {import('../unsupported-features/types.js').SupportInfo} info The support info.
* @param {import('semver').Range} configured The configured version range.
*/

@@ -54,2 +51,6 @@ function isSupported({ supported }, configured) {

if (range == null) {
return false
}
return configured.intersects(range)

@@ -60,8 +61,8 @@ }

* Get the formatted text of a given supported version.
* @param {SupportInfo} info The support info.
* @returns {null|string}
* @param {import('../unsupported-features/types.js').SupportInfo} info The support info.
* @returns {string | undefined}
*/
function supportedVersionToString({ supported }) {
if (supported == null || supported.length === 0) {
return null
return
}

@@ -82,4 +83,4 @@

* Verify the code to report unsupported APIs.
* @param {RuleContext} context The rule context.
* @param {{modules:object,globals:object}} trackMap The map for APIs to report.
* @param {import('eslint').Rule.RuleContext} context The rule context.
* @param {import('../unsupported-features/types.js').SupportVersionBuiltins} traceMap The map for APIs to report.
* @returns {void}

@@ -89,3 +90,3 @@ */

context,
trackMap
traceMap
) {

@@ -97,5 +98,5 @@ const options = parseOptions(context)

const references = [
...tracker.iterateCjsReferences(trackMap.modules || {}),
...tracker.iterateEsmReferences(trackMap.modules || {}),
...tracker.iterateGlobalReferences(trackMap.globals || {}),
...tracker.iterateCjsReferences(traceMap.modules ?? {}),
...tracker.iterateEsmReferences(traceMap.modules ?? {}),
...tracker.iterateGlobalReferences(traceMap.globals ?? {}),
]

@@ -111,22 +112,13 @@

const supportedVersion = supportedVersionToString(info)
if (supportedVersion == null) {
context.report({
node,
messageId: "not-supported-yet",
data: {
name: path.join("."),
version: options.version.raw,
},
})
} else {
context.report({
node,
messageId: "not-supported-till",
data: {
name: path.join("."),
supported: supportedVersionToString(info),
version: options.version.raw,
},
})
}
context.report({
node,
messageId: supportedVersion
? "not-supported-till"
: "not-supported-yet",
data: {
name: path.join("."),
supported: /** @type string */ (supportedVersion),
version: options.version.raw,
},
})
}

@@ -133,0 +125,0 @@ }

@@ -10,23 +10,31 @@ /**

/** @typedef {import('../unsupported-features/types.js').DeprecatedInfoTraceMap} DeprecatedInfoTraceMap */
/** @typedef {import('../unsupported-features/types.js').SupportVersionTraceMap} SupportVersionTraceMap */
/**
* @template {SupportVersionTraceMap | DeprecatedInfoTraceMap} TraceMap
* Enumerate property names of a given object recursively.
* @param {import('../unsupported-features/types.js').SupportVersionTree} trackMap The map for APIs to enumerate.
* @param {TraceMap} traceMap The map for APIs to enumerate.
* @param {string[]} [path] The path to the current map.
* @param {WeakSet} [recursionSet] A WeakSet used to block recursion (eg Module, Module.Module, Module.Module.Module)
* @param {WeakSet<TraceMap>} [recursionSet] A WeakSet used to block recursion (eg Module, Module.Module, Module.Module.Module)
* @returns {IterableIterator<string>} The property names of the map.
*/
function* enumeratePropertyNames(
trackMap,
traceMap,
path = [],
recursionSet = new WeakSet()
) {
if (recursionSet.has(trackMap)) {
if (recursionSet.has(traceMap)) {
return
}
for (const key of Object.getOwnPropertyNames(trackMap)) {
const childValue = trackMap[key]
for (const key of Object.getOwnPropertyNames(traceMap)) {
const childValue = traceMap[key]
const childPath = [...path, key]
const childName = unprefixNodeColon(childPath.join("."))
if (childValue == null) {
continue
}
if (childValue[CALL]) {

@@ -47,3 +55,3 @@ yield `${childName}()`

childPath,
recursionSet.add(trackMap)
recursionSet.add(traceMap)
)

@@ -50,0 +58,0 @@ }

@@ -53,3 +53,6 @@ /**

} catch (error) {
if (error.code !== "ENOENT") {
if (
error instanceof Error &&
("code" in error === false || error.code !== "ENOENT")
) {
throw error

@@ -56,0 +59,0 @@ }

"use strict"
const isCoreModule = require("is-core-module")
const isBuiltinModule = require("is-builtin-module")
/**
* Extend trackMap.modules with `node:` prefixed modules
* @param {Object} modules Like `{assert: foo}`
* @returns {Object} Like `{assert: foo}, "node:assert": foo}`
* Extend traceMap.modules with `node:` prefixed modules
* @template {import('@eslint-community/eslint-utils').TraceMap<*>} TraceMap
* @param {TraceMap} modules Like `{assert: foo}`
* @returns {TraceMap} Like `{assert: foo}, "node:assert": foo}`
*/
module.exports = function extendTrackMapWithNodePrefix(modules) {
module.exports = function extendTraceMapWithNodePrefix(modules) {
const ret = {

@@ -16,4 +17,5 @@ ...modules,

.map(([name, value]) => [`node:${name}`, value])
// Note: "999" arbitrary to check current/future Node.js version
.filter(([name]) => isCoreModule(name, "999"))
.filter(([name]) =>
isBuiltinModule(/** @type {string} */ (name))
)
),

@@ -20,0 +22,0 @@ }

@@ -7,3 +7,6 @@ /**

const DEFAULT_VALUE = Object.freeze([])
/**
* @type {string[]}
*/
const DEFAULT_VALUE = []

@@ -13,7 +16,7 @@ /**

*
* @param {object|undefined} option - An option object to get.
* @param {{allowModules:? string[]}|undefined} option - An option object to get.
* @returns {string[]|null} The `allowModules` value, or `null`.
*/
function get(option) {
if (option && option.allowModules && Array.isArray(option.allowModules)) {
if (Array.isArray(option?.allowModules)) {
return option.allowModules.map(String)

@@ -31,3 +34,3 @@ }

*
* @param {RuleContext} context - The rule context.
* @param {import('eslint').Rule.RuleContext} context - The rule context.
* @returns {string[]} A list of extensions.

@@ -37,6 +40,5 @@ */

return (
get(context.options && context.options[0]) ||
get(
context.settings && (context.settings.n || context.settings.node)
) ||
get(context.options[0]) ??
get(context.settings?.n) ??
get(context.settings?.node) ??
DEFAULT_VALUE

@@ -43,0 +45,0 @@ )

@@ -7,4 +7,3 @@ /**

const { Range } = require("semver") // eslint-disable-line no-unused-vars
const getPackageJson = require("./get-package-json")
const { getPackageJson } = require("./get-package-json")
const getSemverRange = require("./get-semver-range")

@@ -15,20 +14,25 @@

*
* @param {object|undefined} option - An option object to get.
* @returns {string[]|null} The `allowModules` value, or `null`.
* @param {Record<string, string>|undefined} option - An option object to get.
* @returns {import("semver").Range|undefined} The `allowModules` value, or `null`.
*/
function get(option) {
if (option && option.version) {
return option.version
function getVersionRange(option) {
if (option?.version) {
return getSemverRange(option.version)
}
return null
}
/**
* @typedef {{ [EngineName in 'npm' | 'node' | string]?: string }} Engines
*/
/**
* Get the `engines.node` field of package.json.
* @param {string} filename The path to the current linting file.
* @returns {Range|null} The range object of the `engines.node` field.
* @param {import('eslint').Rule.RuleContext} context The path to the current linting file.
* @returns {import("semver").Range|undefined} The range object of the `engines.node` field.
*/
function getEnginesNode(filename) {
function getEnginesNode(context) {
const filename = context.filename ?? context.getFilename()
const info = getPackageJson(filename)
return getSemverRange(info && info.engines && info.engines.node)
const engines = /** @type {Engines | undefined} */ (info?.engines)
if (typeof engines?.node === "string") {
return getSemverRange(engines?.node)
}
}

@@ -43,17 +47,13 @@

*
* @param {string|undefined} version The version range text.
* @param {string} filename The path to the current linting file.
* @param {import('eslint').Rule.RuleContext} context The version range text.
* This will be used to look package.json up if `version` is not a valid version range.
* @returns {Range} The configured version range.
* @returns {import("semver").Range} The configured version range.
*/
module.exports = function getConfiguredNodeVersion(context) {
const version =
get(context.options && context.options[0]) ||
get(context.settings && (context.settings.n || context.settings.node))
const filePath = context.filename ?? context.getFilename()
return (
getSemverRange(version) ||
getEnginesNode(filePath) ||
getSemverRange(">=16.0.0")
getVersionRange(context.options?.[0]) ??
getVersionRange(context.settings?.n) ??
getVersionRange(context.settings?.node) ??
getEnginesNode(context) ??
/** @type {import("semver").Range} */ (getSemverRange(">=16.0.0"))
)

@@ -60,0 +60,0 @@ }

@@ -10,5 +10,11 @@ /**

/**
* @param {any} x - An any value.
* @returns {any} Always `x`.
* @typedef PathConvertion
* @property {string[]} include
* @property {string[]} exclude
* @property {[string, string]} replace
*/
/** @typedef {PathConvertion[] | Record<string, [ string, string ]>} ConvertPath */
/** @typedef {{match: (filePath: string) => boolean, convert: (filePath: string) => string}} Converter */
/** @type {Converter['convert']} */
function identity(x) {

@@ -19,30 +25,34 @@ return x

/**
* Converts old-style value to new-style value.
* Ensures the given value is a string array.
*
* @param {any} x - The value to convert.
* @returns {({include: string[], exclude: string[], replace: string[]})[]} Normalized value.
* @param {unknown[]} x - The value to ensure.
* @returns {string[]} The string array.
*/
function normalizeValue(x) {
function toStringArray(x) {
if (Array.isArray(x)) {
return x
return x.map(String)
}
return Object.keys(x).map(pattern => ({
include: [pattern],
exclude: [],
replace: x[pattern],
}))
return []
}
/**
* Ensures the given value is a string array.
* Converts old-style value to new-style value.
*
* @param {any} x - The value to ensure.
* @returns {string[]} The string array.
* @param {ConvertPath} x - The value to convert.
* @returns {PathConvertion[]} Normalized value.
*/
function toStringArray(x) {
function normalizeValue(x) {
if (Array.isArray(x)) {
return x.map(String)
return x.map(({ include, exclude, replace }) => ({
include: toStringArray(include),
exclude: toStringArray(exclude),
replace: replace,
}))
}
return []
return Object.entries(x).map(([pattern, replace]) => ({
include: [pattern],
exclude: [],
replace: replace,
}))
}

@@ -66,3 +76,3 @@

* @param {string[]} excludePatterns - The glob patterns to exclude files.
* @returns {function} Created predicate function.
* @returns {Converter['match']} Created predicate function.
*/

@@ -83,3 +93,3 @@ function createMatch(includePatterns, excludePatterns) {

* @param {string} toStr - A new string to replace.
* @returns {function} A function which replaces a given path.
* @returns {Converter['convert']} A function which replaces a given path.
*/

@@ -94,4 +104,4 @@ function defineConvert(fromRegexp, toStr) {

*
* @param {{match: function, convert: function}} converters - A list of converters to combine.
* @returns {function} A function which replaces a given path.
* @param {Converter[]} converters - A list of converters to combine.
* @returns {Converter['convert']} A function which replaces a given path.
*/

@@ -112,11 +122,7 @@ function combine(converters) {

*
* @param {object|undefined} option - An option object to get.
* @returns {function|null} A function which converts a path., or `null`.
* @param {{convertPath?: ConvertPath}|undefined} option - An option object to get.
* @returns {Converter['convert']|null} A function which converts a path., or `null`.
*/
function parse(option) {
if (
!option ||
!option.convertPath ||
typeof option.convertPath !== "object"
) {
if (option?.convertPath == null) {
return null

@@ -127,4 +133,2 @@ }

for (const pattern of normalizeValue(option.convertPath)) {
const include = toStringArray(pattern.include)
const exclude = toStringArray(pattern.exclude)
const fromRegexp = new RegExp(String(pattern.replace[0]))

@@ -134,3 +138,3 @@ const toStr = String(pattern.replace[1])

converters.push({
match: createMatch(include, exclude),
match: createMatch(pattern.include, pattern.exclude),
convert: defineConvert(fromRegexp, toStr),

@@ -150,11 +154,10 @@ })

*
* @param {RuleContext} context - The rule context.
* @returns {function} A function which converts a path.
* @param {import('eslint').Rule.RuleContext} context - The rule context.
* @returns {Converter['convert']} A function which converts a path.
*/
module.exports = function getConvertPath(context) {
return (
parse(context.options && context.options[0]) ||
parse(
context.settings && (context.settings.n || context.settings.node)
) ||
parse(context.options?.[0]) ??
parse(context.settings?.n) ??
parse(context.settings?.node) ??
identity

@@ -161,0 +164,0 @@ )

@@ -9,6 +9,6 @@ /**

const path = require("path")
const ignore = require("ignore")
const ignore = require("ignore").default
const Cache = require("./cache")
const exists = require("./exists")
const getPackageJson = require("./get-package-json")
const { getPackageJson } = require("./get-package-json")

@@ -33,5 +33,5 @@ const cache = new Cache()

/**
* @param {function} f - A function.
* @param {function} g - A function.
* @returns {function} A logical-and function of `f` and `g`.
* @param {(filePath: string) => boolean} f - A function.
* @param {(filePath: string) => boolean} g - A function.
* @returns {(filePath: string) => boolean} A logical-and function of `f` and `g`.
*/

@@ -43,14 +43,18 @@ function and(f, g) {

/**
* @param {function} f - A function.
* @param {function} g - A function.
* @param {function|null} h - A function.
* @returns {function} A logical-or function of `f`, `g`, and `h`.
* @param {(filePath: string) => boolean} f - A function.
* @param {(filePath: string) => boolean} g - A function.
* @param {(filePath: string) => boolean} [h] - A function.
* @returns {(filePath: string) => boolean} A logical-or function of `f`, `g`, and `h`.
*/
function or(f, g, h) {
return filePath => f(filePath) || g(filePath) || (h && h(filePath))
if (h == null) {
return filePath => f(filePath) || g(filePath)
}
return filePath => f(filePath) || g(filePath) || h(filePath)
}
/**
* @param {function} f - A function.
* @returns {function} A logical-not function of `f`.
* @param {(filePath: string) => boolean} f - A function.
* @returns {(filePath: string) => boolean} A logical-not function of `f`.
*/

@@ -64,9 +68,15 @@ function not(f) {

*
* @param {object} p - An object of package.json.
* @returns {function} A function which checks whether or not a given file is ignoreable.
* @param {import('type-fest').JsonObject} packageJson - An object of package.json.
* @returns {(filePath: string) => boolean} A function which checks whether or not a given file is ignoreable.
*/
function filterNeverIgnoredFiles(p) {
const basedir = path.dirname(p.filePath)
function filterNeverIgnoredFiles(packageJson) {
if (typeof packageJson?.filePath !== "string") {
return () => false
}
const basedir = path.dirname(packageJson.filePath)
const mainFilePath =
typeof p.main === "string" ? path.join(basedir, p.main) : null
typeof packageJson.main === "string"
? path.join(basedir, packageJson.main)
: null

@@ -82,7 +92,7 @@ return filePath =>

*
* @param {string[]|null} files - File names of whitelist.
* @returns {function|null} A function which checks whether or not a given file should be ignored.
* @param {unknown} files - File names of whitelist.
* @returns {((filePath: string) => boolean) | null} A function which checks whether or not a given file should be ignored.
*/
function parseWhiteList(files) {
if (!files || !Array.isArray(files)) {
if (Array.isArray(files) === false) {
return null

@@ -122,3 +132,3 @@ }

* @param {boolean} filesFieldExists - `true` if `files` field of `package.json` exists.
* @returns {function|null} A function which checks whether or not a given file should be ignored.
* @returns {((filePath: string) => boolean)|null} A function which checks whether or not a given file should be ignored.
*/

@@ -151,3 +161,3 @@ function parseNpmignore(basedir, filesFieldExists) {

* @param {string} startPath - A file path to lookup.
* @returns {object}
* @returns {{ match: (filePath: string) => boolean }}
* An object to check whther or not a given path should be ignored.

@@ -160,36 +170,39 @@ * The object has a method `match`.

const p = getPackageJson(startPath)
if (p) {
const data = cache.get(p.filePath)
if (data) {
return data
}
const packageJson = getPackageJson(startPath)
if (typeof packageJson?.filePath !== "string") {
return retv
}
const filesIgnore = parseWhiteList(p.files)
const npmignoreIgnore = parseNpmignore(
path.dirname(p.filePath),
Boolean(filesIgnore)
)
const data = cache.get(packageJson.filePath)
if (data) {
return data
}
if (filesIgnore && npmignoreIgnore) {
retv.match = and(
filterNeverIgnoredFiles(p),
or(isAncestorFiles, filesIgnore, npmignoreIgnore)
)
} else if (filesIgnore) {
retv.match = and(
filterNeverIgnoredFiles(p),
or(isAncestorFiles, filesIgnore)
)
} else if (npmignoreIgnore) {
retv.match = and(
filterNeverIgnoredFiles(p),
or(isAncestorFiles, npmignoreIgnore)
)
}
const filesIgnore = parseWhiteList(packageJson.files)
cache.set(p.filePath, retv)
const npmignoreIgnore = parseNpmignore(
path.dirname(packageJson.filePath),
Boolean(filesIgnore)
)
if (filesIgnore && npmignoreIgnore) {
retv.match = and(
filterNeverIgnoredFiles(packageJson),
or(isAncestorFiles, filesIgnore, npmignoreIgnore)
)
} else if (filesIgnore) {
retv.match = and(
filterNeverIgnoredFiles(packageJson),
or(isAncestorFiles, filesIgnore)
)
} else if (npmignoreIgnore) {
retv.match = and(
filterNeverIgnoredFiles(packageJson),
or(isAncestorFiles, npmignoreIgnore)
)
}
cache.set(packageJson.filePath, retv)
return retv
}

@@ -19,3 +19,3 @@ /**

* @param {string} dir - The path to a directory to read.
* @returns {object|null} The read `package.json` data, or null.
* @returns {import('type-fest').JsonObject|null} The read `package.json` data, or null.
*/

@@ -28,7 +28,11 @@ function readPackageJson(dir) {

if (typeof data === "object" && data !== null) {
if (
data != null &&
typeof data === "object" &&
Array.isArray(data) === false
) {
data.filePath = filePath
return data
}
} catch (_err) {
} catch {
// do nothing.

@@ -45,6 +49,6 @@ }

* @param {string} [startPath] - A file path to lookup.
* @returns {object|null} A found `package.json` data or `null`.
* @returns {import('type-fest').JsonObject|null} A found `package.json` data or `null`.
* This object have additional property `filePath`.
*/
module.exports = function getPackageJson(startPath = "a.js") {
function getPackageJson(startPath = "a.js") {
const startDir = path.dirname(path.resolve(startPath))

@@ -79,1 +83,3 @@ let dir = startDir

}
module.exports = { getPackageJson }

@@ -7,3 +7,4 @@ /**

const DEFAULT_VALUE = Object.freeze([])
/** @type {string[]} */
const DEFAULT_VALUE = []

@@ -13,10 +14,9 @@ /**

*
* @param {object|undefined} option - An option object to get.
* @returns {string[]|null} The `allowModules` value, or `null`.
* @param {{ resolvePaths: unknown[] } | undefined} option - An option object to get.
* @returns {string[] | undefined} The `allowModules` value, or `null`.
*/
function get(option) {
if (option && option.resolvePaths && Array.isArray(option.resolvePaths)) {
if (Array.isArray(option?.resolvePaths)) {
return option.resolvePaths.map(String)
}
return null
}

@@ -31,3 +31,3 @@

*
* @param {RuleContext} context - The rule context.
* @param {import('eslint').Rule.RuleContext} context - The rule context.
* @returns {string[]} A list of extensions.

@@ -37,6 +37,5 @@ */

return (
get(context.options && context.options[optionIndex]) ||
get(
context.settings && (context.settings.n || context.settings.node)
) ||
get(context.options?.[optionIndex]) ??
get(context.settings?.n) ??
get(context.settings?.node) ??
DEFAULT_VALUE

@@ -43,0 +42,0 @@ )

@@ -13,19 +13,20 @@ /**

* @param {string} x The text expression for a semver range.
* @returns {Range|null} The range object of a given range text.
* @returns {Range|undefined} The range object of a given range text.
* It's null if the `x` is not a valid range text.
*/
module.exports = function getSemverRange(x) {
const s = String(x)
let ret = cache.get(s) || null
const stringVersion = String(x)
const cached = cache.get(stringVersion)
if (cached != null) {
return cached
}
if (!ret) {
try {
ret = new Range(s)
} catch (_error) {
// Ignore parsing error.
}
cache.set(s, ret)
try {
const output = new Range(stringVersion)
cache.set(stringVersion, output)
return output
} catch {
// Ignore parsing error.
cache.set(stringVersion, null)
}
return ret
}

@@ -10,11 +10,7 @@ /**

const DEFAULT_JS_VALUE = Object.freeze([
/** @type {string[]} */
const DEFAULT_JS_VALUE = [".js", ".json", ".node", ".mjs", ".cjs"]
/** @type {string[]} */
const DEFAULT_TS_VALUE = [
".js",
".json",
".node",
".mjs",
".cjs",
])
const DEFAULT_TS_VALUE = Object.freeze([
".js",
".ts",

@@ -27,3 +23,3 @@ ".mjs",

".node",
])
]

@@ -33,4 +29,4 @@ /**

*
* @param {object|undefined} option - An option object to get.
* @returns {string[]|null} The `tryExtensions` value, or `null`.
* @param {{ tryExtensions: unknown[] } | undefined} option - An option object to get.
* @returns {string[] | undefined} The `tryExtensions` value, or `null`.
*/

@@ -41,3 +37,2 @@ function get(option) {

}
return null
}

@@ -52,3 +47,3 @@

*
* @param {RuleContext} context - The rule context.
* @param {import('eslint').Rule.RuleContext} context - The rule context.
* @returns {string[]} A list of extensions.

@@ -66,9 +61,14 @@ */

if (isTypescript(context)) {
const tsconfig = getTSConfigForContext(context)
if (tsconfig?.config?.compilerOptions?.allowImportingTsExtensions) {
return DEFAULT_TS_VALUE
}
if (isTypescript(context) === false) {
return DEFAULT_JS_VALUE
}
const allowImportingTsExtensions =
getTSConfigForContext(context)?.config?.compilerOptions
?.allowImportingTsExtensions
if (allowImportingTsExtensions === true) {
return DEFAULT_TS_VALUE
}
return DEFAULT_JS_VALUE

@@ -75,0 +75,0 @@ }

@@ -30,3 +30,3 @@ "use strict"

/**
* @typedef {Object} ExtensionMap
* @typedef ExtensionMap
* @property {Record<string, string>} forward Convert from typescript to javascript

@@ -37,7 +37,10 @@ * @property {Record<string, string[]>} backward Convert from javascript to typescript

/**
* @param {Record<string, string>} typescriptExtensionMap A forward extension mapping
* @param {[string, string][]} typescriptExtensionMap A forward extension mapping
* @returns {ExtensionMap}
*/
function normalise(typescriptExtensionMap) {
/** @type {Record<string, string>} */
const forward = {}
/** @type {Record<string, string[]>} */
const backward = {}

@@ -61,3 +64,3 @@

* @param {import("get-tsconfig").TsConfigJsonResolved} [tsconfig] - The resolved tsconfig
* @returns {ExtensionMap} The `typescriptExtensionMap` value, or `null`.
* @returns {ExtensionMap | null} The `typescriptExtensionMap` value, or `null`.
*/

@@ -67,3 +70,3 @@ function getMappingFromTSConfig(tsconfig) {

if ({}.hasOwnProperty.call(tsConfigMapping, jsx)) {
if (jsx != null && {}.hasOwnProperty.call(tsConfigMapping, jsx)) {
return tsConfigMapping[jsx]

@@ -76,9 +79,16 @@ }

/**
* @typedef Options
* @property {[string, string][] | keyof tsConfigMapping} typescriptExtensionMap
* @property {string | null} tsconfigPath
*/
/**
* Gets `typescriptExtensionMap` property from a given option object.
*
* @param {object|undefined} option - An option object to get.
* @returns {ExtensionMap} The `typescriptExtensionMap` value, or `null`.
* @param {Options} [option] - An option object to get.
* @returns {ExtensionMap | null} The `typescriptExtensionMap` value, or `null`.
*/
function get(option) {
if (
typeof option?.typescriptExtensionMap === "string" &&
{}.hasOwnProperty.call(tsConfigMapping, option?.typescriptExtensionMap)

@@ -104,3 +114,3 @@ ) {

* @param {import('eslint').Rule.RuleContext} context - The current file context
* @returns {ExtensionMap} The `typescriptExtensionMap` value, or `null`.
* @returns {ExtensionMap | null} The `typescriptExtensionMap` value, or `null`.
*/

@@ -107,0 +117,0 @@ function getFromTSConfigFromFile(context) {

@@ -8,3 +8,3 @@ /**

const { resolve } = require("path")
const isBuiltin = require("is-builtin-module")
const isBuiltinModule = require("is-builtin-module")
const resolver = require("enhanced-resolve")

@@ -16,8 +16,22 @@

/**
* @overload
* @param {string[]} input
* @returns {string[]}
*/
/**
* @overload
* @param {string} input
* @returns {string}
*/
/**
* @param {string | string[]} input
* @returns {string | string[]}
*/
function removeTrailWildcard(input) {
if (Array.isArray(input)) {
return [...input].map(removeTrailWildcard)
if (typeof input === "string") {
return input.replace(/[/\\*]+$/, "")
}
return input.replace(/[/\\*]+$/, "")
return input.map(removeTrailWildcard)
}

@@ -46,3 +60,3 @@

/**
* @typedef {Object} Options
* @typedef Options
* @property {string[]} [extensions]

@@ -52,7 +66,11 @@ * @property {string[]} [paths]

*/
/** @typedef { 'unknown' | 'relative' | 'absolute' | 'node' | 'npm' | 'http' } ModuleType */
/** @typedef { 'import' | 'require' | 'type' } ModuleStyle */
/**
* @typedef { 'unknown' | 'relative' | 'absolute' | 'node' | 'npm' | 'http' } ModuleType
* @typedef { 'import' | 'require' | 'type' } ModuleStyle
* @param {string} string The string to manipulate
* @param {string} matcher The character to use as a segmenter
* @param {Number} [count=1] How many segments to keep
* @returns {string}
*/
function trimAfter(string, matcher, count = 1) {

@@ -62,2 +80,4 @@ return string.split(matcher).slice(0, count).join(matcher)

/** @typedef {import('estree').Node & { parent?: Node }} Node */
/**

@@ -70,3 +90,3 @@ * Information of an import target.

* @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 {Node} node - The node of a `require()` or a module declaraiton.
* @param {string} name - The name of an import target.

@@ -79,3 +99,3 @@ * @param {Options} options - The options of `enhanced-resolve` module.

* The context for the import origin
* @type {import('eslint').Rule.Node}
* @type {import('eslint').Rule.RuleContext}
*/

@@ -86,3 +106,3 @@ this.context = context

* The node of a `require()` or a module declaraiton.
* @type {import('eslint').Rule.Node}
* @type {Node}
*/

@@ -118,3 +138,3 @@ this.node = node

* If the target is a relative path then this is `null`.
* @type {string | null}
* @type {string | undefined}
*/

@@ -144,3 +164,3 @@ this.moduleName = this.getModuleName()

if (isBuiltin(this.name)) {
if (isBuiltinModule(this.name)) {
return "node"

@@ -166,12 +186,14 @@ }

getModuleStyle(fallback) {
/** @type {import('eslint').Rule.Node} */
let node = { parent: this.node }
let node = this.node
do {
node = node.parent
if (node.parent == null) {
break
}
// `const {} = require('')`
if (
node.type === "CallExpression" &&
node.callee.name === "require"
node.parent.type === "CallExpression" &&
node.parent.callee.type === "Identifier" &&
node.parent.callee.name === "require"
) {

@@ -181,17 +203,12 @@ return "require"

// `import type {} from '';`
if (
node.type === "ImportDeclaration" &&
node.importKind === "type"
) {
return "type"
// `import {} from '';`
if (node.parent.type === "ImportDeclaration") {
// `import type {} from '';`
return "importKind" in node.parent &&
node.parent.importKind === "type"
? "type"
: "import"
}
// `import {} from '';`
if (
node.type === "ImportDeclaration" &&
node.importKind === "value"
) {
return "import"
}
node = node.parent
} while (node.parent)

@@ -204,3 +221,3 @@

* Get the node or npm module name
* @returns {string}
* @returns {string | undefined}
*/

@@ -227,2 +244,5 @@ getModuleName() {

/**
* @returns {string[]}
*/
getPaths() {

@@ -285,3 +305,4 @@ if (Array.isArray(this.options.paths)) {

const baseDir = resolve(cwd, directory)
return requireResolve(baseDir, this.name)
const resolved = requireResolve(baseDir, this.name)
if (typeof resolved === "string") return resolved
} catch {

@@ -288,0 +309,0 @@ continue

@@ -10,3 +10,3 @@ "use strict"

*
* @param {RuleContext} context - A context
* @param {import('eslint').Rule.RuleContext} context - A context
* @returns {boolean}

@@ -13,0 +13,0 @@ */

@@ -17,22 +17,10 @@ "use strict"

* @param {string} fallbackExtension The non-typescript fallback
* @param {boolean} reverse Execute a reverse path mapping
* @returns {string} The file extension to append to the import statement.
*/
module.exports = function mapTypescriptExtension(
context,
filePath,
fallbackExtension,
reverse = false
) {
const { forward, backward } = getTypescriptExtensionMap(context)
function convertTsExtensionToJs(context, filePath, fallbackExtension) {
const { forward } = getTypescriptExtensionMap(context)
const ext = path.extname(filePath)
if (reverse) {
if (isTypescript(context) && ext in backward) {
return backward[ext]
}
return [fallbackExtension]
} else {
if (isTypescript(context) && ext in forward) {
return forward[ext]
}
if (isTypescript(context) && ext in forward) {
return forward[ext]
}

@@ -42,1 +30,29 @@

}
/**
* Maps the typescript file extension that should be added in an import statement,
* based on the given file extension of the referenced file OR fallsback to the original given extension.
*
* For example, in typescript, when referencing another typescript from a typescript file,
* a .js extension should be used instead of the original .ts extension of the referenced file.
*
* @param {import('eslint').Rule.RuleContext} context
* @param {string} filePath The filePath of the import
* @param {string} fallbackExtension The non-typescript fallback
* @returns {string[]} The file extension to append to the import statement.
*/
function convertJsExtensionToTs(context, filePath, fallbackExtension) {
const { backward } = getTypescriptExtensionMap(context)
const ext = path.extname(filePath)
if (isTypescript(context) && Object.hasOwn(backward, ext)) {
return backward[ext]
}
return [fallbackExtension]
}
module.exports = {
convertTsExtensionToJs,
convertJsExtensionToTs,
}

@@ -10,5 +10,5 @@ /**

* This function modifies `visitor1` directly to merge.
* @param {Visitor} visitor1 The visitor which is assigned.
* @param {Visitor} visitor2 The visitor which is assigning.
* @returns {Visitor} `visitor1`.
* @param {import('eslint').Rule.RuleListener} visitor1 The visitor which is assigned.
* @param {import('eslint').Rule.RuleListener} visitor2 The visitor which is assigning.
* @returns {import('eslint').Rule.RuleListener} `visitor1`.
*/

@@ -20,14 +20,22 @@ module.exports = function mergeVisitorsInPlace(visitor1, visitor2) {

if (typeof handler1 === "function") {
if (handler1._handlers) {
handler1._handlers.push(handler2)
} else {
const handlers = [handler1, handler2]
visitor1[key] = Object.assign(dispatch.bind(null, handlers), {
_handlers: handlers,
})
}
} else {
if (typeof handler1 !== "function") {
visitor1[key] = handler2
continue
}
if (typeof handler2 !== "function") {
continue
}
if ("_handlers" in handler1 && Array.isArray(handler1._handlers)) {
handler1._handlers.push(handler2)
continue
}
const handlers = [handler1, handler2]
// @ts-expect-error - This is because its expecting a function that can match all {Rule.RuleListener[string]} functions!
visitor1[key] = Object.assign(dispatch.bind(null, handlers), {
_handlers: handlers,
})
}

@@ -34,0 +42,0 @@

@@ -7,5 +7,15 @@ /**

/**
* @param {unknown} path
* @returns {string}
*/
module.exports = function stripImportPathParams(path) {
const i = path.toString().indexOf("!")
return i === -1 ? path : path.slice(0, i)
const pathString = String(path)
const index = pathString.indexOf("!")
if (index === -1) {
return pathString
}
return pathString.slice(0, index)
}

@@ -8,3 +8,3 @@ /**

const path = require("path")
const isCoreModule = require("is-core-module")
const isBuiltinModule = require("is-builtin-module")
const getResolvePaths = require("./get-resolve-paths")

@@ -15,3 +15,12 @@ const getTryExtensions = require("./get-try-extensions")

/** @typedef {import('@typescript-eslint/typescript-estree').TSESTree.ImportDeclaration} ImportDeclaration */
/**
* @typedef VisitImportOptions
* @property {boolean} [includeCore=false] The flag to include core modules.
* @property {number} [optionIndex=0] The index of rule options.
* @property {boolean} [ignoreTypeImport=false] The flag to ignore typescript type imports.
*/
/**
* Gets a list of `import`/`export` declaration targets.

@@ -21,15 +30,13 @@ *

*
* @param {RuleContext} context - The rule context.
* @param {Object} [options] - The flag to include core modules.
* @param {boolean} [options.includeCore] - The flag to include core modules.
* @param {number} [options.optionIndex] - The index of rule options.
* @param {boolean} [options.ignoreTypeImport] - The flag to ignore typescript type imports.
* @param {import('eslint').Rule.RuleContext} context - The rule context.
* @param {VisitImportOptions} options - The flag to include core modules.
* @param {function(ImportTarget[]):void} callback The callback function to get result.
* @returns {ImportTarget[]} A list of found target's information.
* @returns {import('eslint').Rule.RuleListener} A list of found target's information.
*/
module.exports = function visitImport(
context,
{ includeCore = false, optionIndex = 0, ignoreTypeImport = false } = {},
{ includeCore = false, optionIndex = 0, ignoreTypeImport = false },
callback
) {
/** @type {import('./import-target.js')[]} */
const targets = []

@@ -43,16 +50,37 @@ const basedir = path.dirname(

/**
* @param {(
* | import('estree').ExportAllDeclaration
* | import('estree').ExportNamedDeclaration
* | import('estree').ImportDeclaration
* | import('estree').ImportExpression
* )} node
*/
function addTarget(node) {
if (node.source == null || node.source.type !== "Literal") {
return
}
const name = stripImportPathParams(node.source?.value)
if (includeCore === true || isBuiltinModule(name) === false) {
targets.push(
new ImportTarget(context, node.source, name, options, "import")
)
}
}
return {
[[
"ExportAllDeclaration",
"ExportNamedDeclaration",
"ImportDeclaration",
"ImportExpression",
]](node) {
const sourceNode = node.source
// skip `import(foo)`
ExportAllDeclaration(node) {
addTarget(node)
},
ExportNamedDeclaration(node) {
addTarget(node)
},
ImportDeclaration(node) {
if (node.source?.value == null) {
return
}
if (
node.type === "ImportExpression" &&
sourceNode &&
sourceNode.type !== "Literal"
ignoreTypeImport === true &&
/** @type {ImportDeclaration} */ (node).importKind === "type"
) {

@@ -62,24 +90,10 @@ return

// skip `import type { foo } from 'bar'` (for eslint-typescript)
if (
ignoreTypeImport &&
node.type === "ImportDeclaration" &&
node.importKind === "type"
) {
addTarget(node)
},
ImportExpression(node) {
if (node.source?.type !== "Literal") {
return
}
const name = sourceNode && stripImportPathParams(sourceNode.value)
// Note: "999" arbitrary to check current/future Node.js version
if (name && (includeCore || !isCoreModule(name, "999"))) {
targets.push(
new ImportTarget(
context,
sourceNode,
name,
options,
"import"
)
)
}
addTarget(node)
},

@@ -86,0 +100,0 @@

@@ -13,3 +13,3 @@ /**

} = require("@eslint-community/eslint-utils")
const isCoreModule = require("is-core-module")
const isBuiltinModule = require("is-builtin-module")
const getResolvePaths = require("./get-resolve-paths")

@@ -21,2 +21,7 @@ const getTryExtensions = require("./get-try-extensions")

/**
* @typedef VisitRequireOptions
* @property {boolean} [includeCore=false] The flag to include core modules.
*/
/**
* Gets a list of `require()` targets.

@@ -26,13 +31,13 @@ *

*
* @param {RuleContext} context - The rule context.
* @param {Object} [options] - The flag to include core modules.
* @param {boolean} [options.includeCore] - The flag to include core modules.
* @param {function(ImportTarget[]):void} callback The callback function to get result.
* @returns {Object} The visitor.
* @param {import('eslint').Rule.RuleContext} context - The rule context.
* @param {VisitRequireOptions} options - The flag to include core modules.
* @param {function(ImportTarget[]): void} callback The callback function to get result.
* @returns {import('eslint').Rule.RuleListener} The visitor.
*/
module.exports = function visitRequire(
context,
{ includeCore = false } = {},
{ includeCore = false },
callback
) {
/** @type {import('./import-target.js')[]} */
const targets = []

@@ -60,7 +65,14 @@ const basedir = path.dirname(

for (const { node } of references) {
if (node.type !== "CallExpression") {
continue
}
const targetNode = node.arguments[0]
const rawName = getStringIfConstant(targetNode)
const name = rawName && stripImportPathParams(rawName)
// Note: "999" arbitrary to check current/future Node.js version
if (name && (includeCore || !isCoreModule(name, "999"))) {
if (typeof rawName !== "string") {
continue
}
const name = stripImportPathParams(rawName)
if (includeCore || !isBuiltinModule(name)) {
targets.push(

@@ -67,0 +79,0 @@ new ImportTarget(

{
"name": "eslint-plugin-n",
"version": "17.0.0-6",
"version": "17.0.0-7",
"description": "Additional ESLint's rules for Node.js",

@@ -9,11 +9,14 @@ "engines": {

"main": "lib/index.js",
"types": "types/index.d.ts",
"files": [
"lib/",
"configs/"
"configs/",
"types/index.d.ts"
],
"peerDependencies": {
"eslint": "^8.23.0 || >=9.0.0-0"
"eslint": ">=8.23.0"
},
"dependencies": {
"@eslint-community/eslint-utils": "^4.4.0",
"@types/eslint": "^8.56.2",
"enhanced-resolve": "^5.15.0",

@@ -25,3 +28,2 @@ "eslint-plugin-es-x": "^7.5.0",

"is-builtin-module": "^3.2.1",
"is-core-module": "^2.12.1",
"minimatch": "^9.0.0",

@@ -31,6 +33,9 @@ "semver": "^7.5.3"

"devDependencies": {
"@eslint/js": "^8.43.0",
"@eslint/js": "^9.0.0",
"@types/eslint": "^8.56.2",
"@types/estree": "^1.0.5",
"@types/node": "^20.11.0",
"@typescript-eslint/parser": "^7.0.0",
"eslint": "^8",
"@typescript-eslint/typescript-estree": "^6.18.1",
"eslint": "^9.0.0",
"eslint-config-prettier": "^9.1.0",

@@ -52,2 +57,3 @@ "eslint-doc-generator": "^1.6.1",

"rimraf": "^5.0.1",
"type-fest": "^4.9.0",
"typescript": "^5.1.3"

@@ -66,9 +72,9 @@ },

"postversion": "git push && git push --tags",
"prepack": "tsc --emitDeclarationOnly",
"prepare": "husky",
"pretest": "npm run -s lint",
"preversion": "npm test",
"test": "nyc npm run -s test:_mocha",
"test:_mocha": "_mocha --reporter progress --timeout 4000 \"tests/lib/**/*.js\"",
"test": "run-p lint:* test:types test:tests",
"test:mocha": "_mocha --reporter progress --timeout 4000",
"test:ci": "nyc npm run -s test:_mocha",
"test:tests": "npm run test:mocha \"tests/lib/**/*.js\"",
"test:types": "tsc --noEmit --emitDeclarationOnly false",
"update:eslint-docs": "eslint-doc-generator",

@@ -75,0 +81,0 @@ "version": "npm run -s build && eslint lib/rules --fix && git add .",

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Packages

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc