]> git.proxmox.com Git - pve-eslint.git/blame - eslint/lib/rules/no-restricted-modules.js
bump version to 8.4.0-3
[pve-eslint.git] / eslint / lib / rules / no-restricted-modules.js
CommitLineData
eb39fafa
DC
1/**
2 * @fileoverview Restrict usage of specified node modules.
3 * @author Christian Schulz
609c276f 4 * @deprecated in ESLint v7.0.0
eb39fafa
DC
5 */
6"use strict";
7
8//------------------------------------------------------------------------------
9// Rule Definition
10//------------------------------------------------------------------------------
11
12const ignore = require("ignore");
13
14const arrayOfStrings = {
15 type: "array",
16 items: { type: "string" },
17 uniqueItems: true
18};
19
20const arrayOfStringsOrObjects = {
21 type: "array",
22 items: {
23 anyOf: [
24 { type: "string" },
25 {
26 type: "object",
27 properties: {
28 name: { type: "string" },
29 message: {
30 type: "string",
31 minLength: 1
32 }
33 },
34 additionalProperties: false,
35 required: ["name"]
36 }
37 ]
38 },
39 uniqueItems: true
40};
41
34eeec05 42/** @type {import('../shared/types').Rule} */
eb39fafa
DC
43module.exports = {
44 meta: {
56c4a2cb
DC
45 deprecated: true,
46
ebb53d86 47 replacedBy: [],
56c4a2cb 48
eb39fafa
DC
49 type: "suggestion",
50
51 docs: {
52 description: "disallow specified modules when loaded by `require`",
eb39fafa
DC
53 recommended: false,
54 url: "https://eslint.org/docs/rules/no-restricted-modules"
55 },
56
57 schema: {
58 anyOf: [
59 arrayOfStringsOrObjects,
60 {
61 type: "array",
62 items: {
63 type: "object",
64 properties: {
65 paths: arrayOfStringsOrObjects,
66 patterns: arrayOfStrings
67 },
68 additionalProperties: false
69 },
70 additionalItems: false
71 }
72 ]
73 },
74
75 messages: {
76 defaultMessage: "'{{name}}' module is restricted from being used.",
609c276f 77 // eslint-disable-next-line eslint-plugin/report-message-format -- Custom message might not end in a period
eb39fafa
DC
78 customMessage: "'{{name}}' module is restricted from being used. {{customMessage}}",
79 patternMessage: "'{{name}}' module is restricted from being used by a pattern."
80 }
81 },
82
83 create(context) {
84 const options = Array.isArray(context.options) ? context.options : [];
85 const isPathAndPatternsObject =
86 typeof options[0] === "object" &&
87 (Object.prototype.hasOwnProperty.call(options[0], "paths") || Object.prototype.hasOwnProperty.call(options[0], "patterns"));
88
89 const restrictedPaths = (isPathAndPatternsObject ? options[0].paths : context.options) || [];
90 const restrictedPatterns = (isPathAndPatternsObject ? options[0].patterns : []) || [];
91
92 const restrictedPathMessages = restrictedPaths.reduce((memo, importName) => {
93 if (typeof importName === "string") {
94 memo[importName] = null;
95 } else {
96 memo[importName.name] = importName.message;
97 }
98 return memo;
99 }, {});
100
609c276f 101 // if no imports are restricted we don't need to check
eb39fafa
DC
102 if (Object.keys(restrictedPaths).length === 0 && restrictedPatterns.length === 0) {
103 return {};
104 }
105
106 const ig = ignore().add(restrictedPatterns);
107
108
109 /**
110 * Function to check if a node is a string literal.
111 * @param {ASTNode} node The node to check.
112 * @returns {boolean} If the node is a string literal.
113 */
114 function isStringLiteral(node) {
115 return node && node.type === "Literal" && typeof node.value === "string";
116 }
117
118 /**
119 * Function to check if a node is a static string template literal.
120 * @param {ASTNode} node The node to check.
121 * @returns {boolean} If the node is a string template literal.
122 */
123 function isStaticTemplateLiteral(node) {
124 return node && node.type === "TemplateLiteral" && node.expressions.length === 0;
125 }
126
127 /**
128 * Function to check if a node is a require call.
129 * @param {ASTNode} node The node to check.
130 * @returns {boolean} If the node is a require call.
131 */
132 function isRequireCall(node) {
133 return node.callee.type === "Identifier" && node.callee.name === "require";
134 }
135
136 /**
137 * Extract string from Literal or TemplateLiteral node
138 * @param {ASTNode} node The node to extract from
139 * @returns {string|null} Extracted string or null if node doesn't represent a string
140 */
141 function getFirstArgumentString(node) {
142 if (isStringLiteral(node)) {
143 return node.value.trim();
144 }
145
146 if (isStaticTemplateLiteral(node)) {
147 return node.quasis[0].value.cooked.trim();
148 }
149
150 return null;
151 }
152
153 /**
154 * Report a restricted path.
155 * @param {node} node representing the restricted path reference
156 * @param {string} name restricted path
157 * @returns {void}
158 * @private
159 */
160 function reportPath(node, name) {
161 const customMessage = restrictedPathMessages[name];
162 const messageId = customMessage
163 ? "customMessage"
164 : "defaultMessage";
165
166 context.report({
167 node,
168 messageId,
169 data: {
170 name,
171 customMessage
172 }
173 });
174 }
175
176 /**
177 * Check if the given name is a restricted path name
178 * @param {string} name name of a variable
179 * @returns {boolean} whether the variable is a restricted path or not
180 * @private
181 */
182 function isRestrictedPath(name) {
183 return Object.prototype.hasOwnProperty.call(restrictedPathMessages, name);
184 }
185
186 return {
187 CallExpression(node) {
188 if (isRequireCall(node)) {
189
190 // node has arguments
191 if (node.arguments.length) {
192 const name = getFirstArgumentString(node.arguments[0]);
193
194 // if first argument is a string literal or a static string template literal
195 if (name) {
196
197 // check if argument value is in restricted modules array
198 if (isRestrictedPath(name)) {
199 reportPath(node, name);
200 }
201
202 if (restrictedPatterns.length > 0 && ig.ignores(name)) {
203 context.report({
204 node,
205 messageId: "patternMessage",
206 data: { name }
207 });
208 }
209 }
210 }
211 }
212 }
213 };
214 }
215};