_patch-base.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. "use strict";
  2. // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
  3. // See LICENSE in the project root for license information.
  4. var __importDefault = (this && this.__importDefault) || function (mod) {
  5. return (mod && mod.__esModule) ? mod : { "default": mod };
  6. };
  7. Object.defineProperty(exports, "__esModule", { value: true });
  8. exports.isModuleResolutionError = exports.ESLINT_MAJOR_VERSION = exports.Naming = exports.ModuleResolver = exports.configArrayFactory = exports.eslintFolder = exports.eslintPackageVersion = void 0;
  9. // This is a workaround for https://github.com/eslint/eslint/issues/3458
  10. //
  11. // To correct how ESLint searches for plugin packages, add this line to the top of your project's .eslintrc.js file:
  12. //
  13. // require("@rushstack/eslint-patch/modern-module-resolution");
  14. //
  15. const path_1 = __importDefault(require("path"));
  16. const isModuleResolutionError = (ex) => typeof ex === 'object' && !!ex && 'code' in ex && ex.code === 'MODULE_NOT_FOUND';
  17. exports.isModuleResolutionError = isModuleResolutionError;
  18. const FLAT_CONFIG_REGEX = /eslint\.config\.(cjs|mjs|js)$/i;
  19. // Ex:
  20. // at async ESLint.lintFiles (C:\\path\\to\\\\eslint\\lib\\eslint\\eslint.js:720:21)
  21. const NODE_STACK_REGEX = /^\s*at (?:((?:\[object object\])?[^\\/]+(?: \[as \S+\])?) )?\(?(.*?)(?::(\d+)| (\d+))(?::(\d+))?\)?\s*$/i;
  22. function parseNodeStack(stack) {
  23. const stackTraceMatch = NODE_STACK_REGEX.exec(stack);
  24. if (!stackTraceMatch) {
  25. return undefined;
  26. }
  27. return {
  28. file: stackTraceMatch[2],
  29. method: stackTraceMatch[1],
  30. lineNumber: parseInt(stackTraceMatch[3], 10),
  31. column: stackTraceMatch[4] ? parseInt(stackTraceMatch[4], 10) : undefined
  32. };
  33. }
  34. function getStackTrace() {
  35. const stackObj = {};
  36. const originalStackTraceLimit = Error.stackTraceLimit;
  37. Error.stackTraceLimit = Infinity;
  38. Error.captureStackTrace(stackObj, getStackTrace);
  39. Error.stackTraceLimit = originalStackTraceLimit;
  40. if (!stackObj.stack) {
  41. throw new Error('Unable to capture stack trace');
  42. }
  43. const { stack } = stackObj;
  44. const stackLines = stack.split('\n');
  45. const frames = [];
  46. for (const line of stackLines) {
  47. const frame = parseNodeStack(line);
  48. if (frame) {
  49. frames.push(frame);
  50. }
  51. }
  52. return frames;
  53. }
  54. // Module path for eslintrc.cjs
  55. // Example: ".../@eslint/eslintrc/dist/eslintrc.cjs"
  56. let eslintrcBundlePath = undefined;
  57. // Module path for config-array-factory.js
  58. // Example: ".../@eslint/eslintrc/lib/config-array-factory"
  59. let configArrayFactoryPath = undefined;
  60. // Module path for relative-module-resolver.js
  61. // Example: ".../@eslint/eslintrc/lib/shared/relative-module-resolver"
  62. let moduleResolverPath = undefined;
  63. // Module path for naming.js
  64. // Example: ".../@eslint/eslintrc/lib/shared/naming"
  65. let namingPath = undefined;
  66. // Folder path where ESLint's package.json can be found
  67. // Example: ".../node_modules/eslint"
  68. let eslintFolder = undefined;
  69. exports.eslintFolder = eslintFolder;
  70. // Probe for the ESLint >=9.0.0 flat config layout:
  71. for (let currentModule = module;;) {
  72. if (FLAT_CONFIG_REGEX.test(currentModule.filename)) {
  73. // Obtain the stack trace of the current module, since the
  74. // parent module of a flat config is undefined. From the
  75. // stack trace, we can find the ESLint folder.
  76. const stackTrace = getStackTrace();
  77. const targetFrame = stackTrace.find((frame) => frame.file && frame.file.endsWith('eslint.js'));
  78. if (targetFrame) {
  79. // Walk up the path and continuously attempt to resolve the ESLint folder
  80. let currentPath = targetFrame.file;
  81. while (currentPath) {
  82. const potentialPath = path_1.default.dirname(currentPath);
  83. if (potentialPath === currentPath) {
  84. break;
  85. }
  86. currentPath = potentialPath;
  87. try {
  88. exports.eslintFolder = eslintFolder = path_1.default.dirname(require.resolve('eslint/package.json', { paths: [currentPath] }));
  89. break;
  90. }
  91. catch (ex) {
  92. if (!isModuleResolutionError(ex)) {
  93. throw ex;
  94. }
  95. }
  96. }
  97. }
  98. if (eslintFolder) {
  99. const eslintrcFolderPath = path_1.default.dirname(require.resolve('@eslint/eslintrc/package.json', { paths: [eslintFolder] }));
  100. eslintrcBundlePath = path_1.default.join(eslintrcFolderPath, 'dist/eslintrc.cjs');
  101. }
  102. break;
  103. }
  104. if (!currentModule.parent) {
  105. break;
  106. }
  107. currentModule = currentModule.parent;
  108. }
  109. if (!eslintFolder) {
  110. // Probe for the ESLint >=8.0.0 layout:
  111. for (let currentModule = module;;) {
  112. if (!eslintrcBundlePath) {
  113. if (currentModule.filename.endsWith('eslintrc.cjs')) {
  114. // For ESLint >=8.0.0, all @eslint/eslintrc code is bundled at this path:
  115. // .../@eslint/eslintrc/dist/eslintrc.cjs
  116. try {
  117. const eslintrcFolderPath = path_1.default.dirname(require.resolve('@eslint/eslintrc/package.json', { paths: [currentModule.path] }));
  118. // Make sure we actually resolved the module in our call path
  119. // and not some other spurious dependency.
  120. const resolvedEslintrcBundlePath = path_1.default.join(eslintrcFolderPath, 'dist/eslintrc.cjs');
  121. if (resolvedEslintrcBundlePath === currentModule.filename) {
  122. eslintrcBundlePath = resolvedEslintrcBundlePath;
  123. }
  124. }
  125. catch (ex) {
  126. // Module resolution failures are expected, as we're walking
  127. // up our require stack to look for eslint. All other errors
  128. // are re-thrown.
  129. if (!isModuleResolutionError(ex)) {
  130. throw ex;
  131. }
  132. }
  133. }
  134. }
  135. else {
  136. // Next look for a file in ESLint's folder
  137. // .../eslint/lib/cli-engine/cli-engine.js
  138. try {
  139. const eslintCandidateFolder = path_1.default.dirname(require.resolve('eslint/package.json', {
  140. paths: [currentModule.path]
  141. }));
  142. // Make sure we actually resolved the module in our call path
  143. // and not some other spurious dependency.
  144. if (currentModule.filename.startsWith(eslintCandidateFolder + path_1.default.sep)) {
  145. exports.eslintFolder = eslintFolder = eslintCandidateFolder;
  146. break;
  147. }
  148. }
  149. catch (ex) {
  150. // Module resolution failures are expected, as we're walking
  151. // up our require stack to look for eslint. All other errors
  152. // are re-thrown.
  153. if (!isModuleResolutionError(ex)) {
  154. throw ex;
  155. }
  156. }
  157. }
  158. if (!currentModule.parent) {
  159. break;
  160. }
  161. currentModule = currentModule.parent;
  162. }
  163. }
  164. if (!eslintFolder) {
  165. // Probe for the ESLint >=7.12.0 layout:
  166. for (let currentModule = module;;) {
  167. if (!configArrayFactoryPath) {
  168. // For ESLint >=7.12.0, config-array-factory.js is at this path:
  169. // .../@eslint/eslintrc/lib/config-array-factory.js
  170. try {
  171. const eslintrcFolder = path_1.default.dirname(require.resolve('@eslint/eslintrc/package.json', {
  172. paths: [currentModule.path]
  173. }));
  174. const resolvedConfigArrayFactoryPath = path_1.default.join(eslintrcFolder, '/lib/config-array-factory.js');
  175. if (resolvedConfigArrayFactoryPath === currentModule.filename) {
  176. configArrayFactoryPath = resolvedConfigArrayFactoryPath;
  177. moduleResolverPath = `${eslintrcFolder}/lib/shared/relative-module-resolver`;
  178. namingPath = `${eslintrcFolder}/lib/shared/naming`;
  179. }
  180. }
  181. catch (ex) {
  182. // Module resolution failures are expected, as we're walking
  183. // up our require stack to look for eslint. All other errors
  184. // are re-thrown.
  185. if (!isModuleResolutionError(ex)) {
  186. throw ex;
  187. }
  188. }
  189. }
  190. else if (currentModule.filename.endsWith('cli-engine.js')) {
  191. // Next look for a file in ESLint's folder
  192. // .../eslint/lib/cli-engine/cli-engine.js
  193. try {
  194. const eslintCandidateFolder = path_1.default.dirname(require.resolve('eslint/package.json', {
  195. paths: [currentModule.path]
  196. }));
  197. if (path_1.default.join(eslintCandidateFolder, 'lib/cli-engine/cli-engine.js') === currentModule.filename) {
  198. exports.eslintFolder = eslintFolder = eslintCandidateFolder;
  199. break;
  200. }
  201. }
  202. catch (ex) {
  203. // Module resolution failures are expected, as we're walking
  204. // up our require stack to look for eslint. All other errors
  205. // are rethrown.
  206. if (!isModuleResolutionError(ex)) {
  207. throw ex;
  208. }
  209. }
  210. }
  211. if (!currentModule.parent) {
  212. break;
  213. }
  214. currentModule = currentModule.parent;
  215. }
  216. }
  217. if (!eslintFolder) {
  218. // Probe for the <7.12.0 layout:
  219. for (let currentModule = module;;) {
  220. // For ESLint <7.12.0, config-array-factory.js was at this path:
  221. // .../eslint/lib/cli-engine/config-array-factory.js
  222. if (/[\\/]eslint[\\/]lib[\\/]cli-engine[\\/]config-array-factory\.js$/i.test(currentModule.filename)) {
  223. exports.eslintFolder = eslintFolder = path_1.default.join(path_1.default.dirname(currentModule.filename), '../..');
  224. configArrayFactoryPath = `${eslintFolder}/lib/cli-engine/config-array-factory`;
  225. moduleResolverPath = `${eslintFolder}/lib/shared/relative-module-resolver`;
  226. // The naming module was moved to @eslint/eslintrc in ESLint 7.8.0, which is also when the @eslint/eslintrc
  227. // package was created and added to ESLint, so we need to probe for whether it's in the old or new location.
  228. let eslintrcFolder;
  229. try {
  230. eslintrcFolder = path_1.default.dirname(require.resolve('@eslint/eslintrc/package.json', {
  231. paths: [currentModule.path]
  232. }));
  233. }
  234. catch (ex) {
  235. if (!isModuleResolutionError(ex)) {
  236. throw ex;
  237. }
  238. }
  239. namingPath = `${eslintrcFolder !== null && eslintrcFolder !== void 0 ? eslintrcFolder : eslintFolder}/lib/shared/naming`;
  240. break;
  241. }
  242. if (!currentModule.parent) {
  243. // This was tested with ESLint 6.1.0 .. 7.12.1.
  244. throw new Error('Failed to patch ESLint because the calling module was not recognized.\n' +
  245. 'If you are using a newer ESLint version that may be unsupported, please create a GitHub issue:\n' +
  246. 'https://github.com/microsoft/rushstack/issues');
  247. }
  248. currentModule = currentModule.parent;
  249. }
  250. }
  251. // Detect the ESLint package version
  252. const eslintPackageJsonPath = `${eslintFolder}/package.json`;
  253. const eslintPackageObject = require(eslintPackageJsonPath);
  254. exports.eslintPackageVersion = eslintPackageObject.version;
  255. const ESLINT_MAJOR_VERSION = parseInt(exports.eslintPackageVersion, 10);
  256. exports.ESLINT_MAJOR_VERSION = ESLINT_MAJOR_VERSION;
  257. if (isNaN(ESLINT_MAJOR_VERSION)) {
  258. throw new Error(`Unable to parse ESLint version "${exports.eslintPackageVersion}" in file "${eslintPackageJsonPath}"`);
  259. }
  260. if (!(ESLINT_MAJOR_VERSION >= 6 && ESLINT_MAJOR_VERSION <= 9)) {
  261. throw new Error('The ESLint patch script has only been tested with ESLint version 6.x, 7.x, 8.x, and 9.x.' +
  262. ` (Your version: ${exports.eslintPackageVersion})\n` +
  263. 'Consider reporting a GitHub issue:\n' +
  264. 'https://github.com/microsoft/rushstack/issues');
  265. }
  266. // eslint-disable-next-line @typescript-eslint/no-explicit-any
  267. let configArrayFactory;
  268. if (ESLINT_MAJOR_VERSION >= 8 && eslintrcBundlePath) {
  269. exports.configArrayFactory = configArrayFactory = require(eslintrcBundlePath).Legacy.ConfigArrayFactory;
  270. }
  271. else if (configArrayFactoryPath) {
  272. exports.configArrayFactory = configArrayFactory = require(configArrayFactoryPath).ConfigArrayFactory;
  273. }
  274. // eslint-disable-next-line @typescript-eslint/no-explicit-any
  275. let ModuleResolver;
  276. // eslint-disable-next-line @typescript-eslint/no-explicit-any
  277. let Naming;
  278. if (ESLINT_MAJOR_VERSION >= 8 && eslintrcBundlePath) {
  279. exports.ModuleResolver = ModuleResolver = require(eslintrcBundlePath).Legacy.ModuleResolver;
  280. exports.Naming = Naming = require(eslintrcBundlePath).Legacy.naming;
  281. }
  282. else if (moduleResolverPath && namingPath) {
  283. exports.ModuleResolver = ModuleResolver = require(moduleResolverPath);
  284. exports.Naming = Naming = require(namingPath);
  285. }
  286. //# sourceMappingURL=_patch-base.js.map