]> git.proxmox.com Git - pve-eslint.git/blob - eslint/lib/rules/no-restricted-modules.js
c37694f90461f9b4933c67bab0265bd5097a4004
[pve-eslint.git] / eslint / lib / rules / no-restricted-modules.js
1 /**
2 * @fileoverview Restrict usage of specified node modules.
3 * @author Christian Schulz
4 * @deprecated in ESLint v7.0.0
5 */
6 "use strict";
7
8 //------------------------------------------------------------------------------
9 // Rule Definition
10 //------------------------------------------------------------------------------
11
12 const ignore = require("ignore");
13
14 const arrayOfStrings = {
15 type: "array",
16 items: { type: "string" },
17 uniqueItems: true
18 };
19
20 const 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
42 /** @type {import('../shared/types').Rule} */
43 module.exports = {
44 meta: {
45 deprecated: true,
46
47 replacedBy: [],
48
49 type: "suggestion",
50
51 docs: {
52 description: "Disallow specified modules when loaded by `require`",
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.",
77 // eslint-disable-next-line eslint-plugin/report-message-format -- Custom message might not end in a period
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
101 // if no imports are restricted we don't need to check
102 if (Object.keys(restrictedPaths).length === 0 && restrictedPatterns.length === 0) {
103 return {};
104 }
105
106 // relative paths are supported for this rule
107 const ig = ignore({ allowRelativePaths: true }).add(restrictedPatterns);
108
109
110 /**
111 * Function to check if a node is a string literal.
112 * @param {ASTNode} node The node to check.
113 * @returns {boolean} If the node is a string literal.
114 */
115 function isStringLiteral(node) {
116 return node && node.type === "Literal" && typeof node.value === "string";
117 }
118
119 /**
120 * Function to check if a node is a static string template literal.
121 * @param {ASTNode} node The node to check.
122 * @returns {boolean} If the node is a string template literal.
123 */
124 function isStaticTemplateLiteral(node) {
125 return node && node.type === "TemplateLiteral" && node.expressions.length === 0;
126 }
127
128 /**
129 * Function to check if a node is a require call.
130 * @param {ASTNode} node The node to check.
131 * @returns {boolean} If the node is a require call.
132 */
133 function isRequireCall(node) {
134 return node.callee.type === "Identifier" && node.callee.name === "require";
135 }
136
137 /**
138 * Extract string from Literal or TemplateLiteral node
139 * @param {ASTNode} node The node to extract from
140 * @returns {string|null} Extracted string or null if node doesn't represent a string
141 */
142 function getFirstArgumentString(node) {
143 if (isStringLiteral(node)) {
144 return node.value.trim();
145 }
146
147 if (isStaticTemplateLiteral(node)) {
148 return node.quasis[0].value.cooked.trim();
149 }
150
151 return null;
152 }
153
154 /**
155 * Report a restricted path.
156 * @param {node} node representing the restricted path reference
157 * @param {string} name restricted path
158 * @returns {void}
159 * @private
160 */
161 function reportPath(node, name) {
162 const customMessage = restrictedPathMessages[name];
163 const messageId = customMessage
164 ? "customMessage"
165 : "defaultMessage";
166
167 context.report({
168 node,
169 messageId,
170 data: {
171 name,
172 customMessage
173 }
174 });
175 }
176
177 /**
178 * Check if the given name is a restricted path name
179 * @param {string} name name of a variable
180 * @returns {boolean} whether the variable is a restricted path or not
181 * @private
182 */
183 function isRestrictedPath(name) {
184 return Object.prototype.hasOwnProperty.call(restrictedPathMessages, name);
185 }
186
187 return {
188 CallExpression(node) {
189 if (isRequireCall(node)) {
190
191 // node has arguments
192 if (node.arguments.length) {
193 const name = getFirstArgumentString(node.arguments[0]);
194
195 // if first argument is a string literal or a static string template literal
196 if (name) {
197
198 // check if argument value is in restricted modules array
199 if (isRestrictedPath(name)) {
200 reportPath(node, name);
201 }
202
203 if (restrictedPatterns.length > 0 && ig.ignores(name)) {
204 context.report({
205 node,
206 messageId: "patternMessage",
207 data: { name }
208 });
209 }
210 }
211 }
212 }
213 }
214 };
215 }
216 };