@nx/eslint 19.3.0-beta.0 → 19.3.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +4 -4
- package/src/executors/lint/lint.impl.js +15 -6
- package/src/plugins/plugin.js +166 -48
- package/src/utils/config-file.js +11 -10
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@nx/eslint",
|
3
|
-
"version": "19.3.0-beta.
|
3
|
+
"version": "19.3.0-beta.1",
|
4
4
|
"private": false,
|
5
5
|
"description": "The ESLint plugin for Nx contains executors, generators and utilities used for linting JavaScript/TypeScript projects within an Nx workspace.",
|
6
6
|
"repository": {
|
@@ -35,12 +35,12 @@
|
|
35
35
|
"eslint": "^8.0.0 || ^9.0.0"
|
36
36
|
},
|
37
37
|
"dependencies": {
|
38
|
-
"@nx/devkit": "19.3.0-beta.
|
39
|
-
"@nx/js": "19.3.0-beta.
|
38
|
+
"@nx/devkit": "19.3.0-beta.1",
|
39
|
+
"@nx/js": "19.3.0-beta.1",
|
40
40
|
"semver": "^7.5.3",
|
41
41
|
"tslib": "^2.3.0",
|
42
42
|
"typescript": "~5.4.2",
|
43
|
-
"@nx/linter": "19.3.0-beta.
|
43
|
+
"@nx/linter": "19.3.0-beta.1"
|
44
44
|
},
|
45
45
|
"peerDependenciesMeta": {
|
46
46
|
"@zkochan/js-yaml": {
|
@@ -77,15 +77,24 @@ async function run(options, context) {
|
|
77
77
|
catch (err) {
|
78
78
|
if (err.message.includes('You must therefore provide a value for the "parserOptions.project" property for @typescript-eslint/parser')) {
|
79
79
|
const ruleName = err.message.match(/rule '([^']+)':/)?.[1];
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
eslintConfigPathForError =
|
80
|
+
const reportedFile = err.message.match(/Occurred while linting (.+)$/)?.[1];
|
81
|
+
let eslintConfigPathForError = `for the project "${projectName}"`;
|
82
|
+
if (eslintConfigPath) {
|
83
|
+
eslintConfigPathForError = `"${path_1.posix.relative(context.root, eslintConfigPath)}"`;
|
84
|
+
}
|
85
|
+
else {
|
86
|
+
const configPathForfile = hasFlatConfig
|
87
|
+
? (0, config_file_1.findFlatConfigFile)(projectRoot, context.root)
|
88
|
+
: (0, config_file_1.findOldConfigFile)(reportedFile ?? projectRoot, context.root);
|
89
|
+
if (configPathForfile) {
|
90
|
+
eslintConfigPathForError = `"${path_1.posix.relative(context.root, configPathForfile)}"`;
|
91
|
+
}
|
84
92
|
}
|
85
93
|
console.error(`
|
86
|
-
Error: You have attempted to use ${ruleName ? `the lint rule ${ruleName}` : 'a lint rule'} which requires the full TypeScript type-checker to be available, but you do not have
|
94
|
+
Error: You have attempted to use ${ruleName ? `the lint rule "${ruleName}"` : 'a lint rule'} which requires the full TypeScript type-checker to be available, but you do not have "parserOptions.project" configured to point at your project tsconfig.json files in the relevant TypeScript file "overrides" block of your ESLint config ${eslintConfigPathForError}
|
95
|
+
${reportedFile ? `Occurred while linting ${reportedFile}` : ''}
|
87
96
|
|
88
|
-
Please see https://nx.dev/
|
97
|
+
Please see https://nx.dev/recipes/tips-n-tricks/eslint for full guidance on how to resolve this issue.
|
89
98
|
`);
|
90
99
|
return {
|
91
100
|
success: false,
|
package/src/plugins/plugin.js
CHANGED
@@ -2,24 +2,27 @@
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
3
|
exports.createNodes = exports.createNodesV2 = void 0;
|
4
4
|
const devkit_1 = require("@nx/devkit");
|
5
|
+
const calculate_hash_for_create_nodes_1 = require("@nx/devkit/src/utils/calculate-hash-for-create-nodes");
|
5
6
|
const node_fs_1 = require("node:fs");
|
6
7
|
const node_path_1 = require("node:path");
|
8
|
+
const file_hasher_1 = require("nx/src/hasher/file-hasher");
|
9
|
+
const cache_directory_1 = require("nx/src/utils/cache-directory");
|
7
10
|
const globs_1 = require("nx/src/utils/globs");
|
8
11
|
const workspace_context_1 = require("nx/src/utils/workspace-context");
|
12
|
+
const semver_1 = require("semver");
|
9
13
|
const config_file_1 = require("../utils/config-file");
|
10
14
|
const resolve_eslint_class_1 = require("../utils/resolve-eslint-class");
|
11
|
-
const semver_1 = require("semver");
|
12
|
-
const cache_directory_1 = require("nx/src/utils/cache-directory");
|
13
|
-
const file_hasher_1 = require("nx/src/hasher/file-hasher");
|
14
|
-
const calculate_hash_for_create_nodes_1 = require("@nx/devkit/src/utils/calculate-hash-for-create-nodes");
|
15
15
|
const DEFAULT_EXTENSIONS = ['ts', 'tsx', 'js', 'jsx', 'html', 'vue'];
|
16
|
-
const
|
16
|
+
const PROJECT_CONFIG_FILENAMES = ['project.json', 'package.json'];
|
17
|
+
const ESLINT_CONFIG_GLOB_V1 = (0, globs_1.combineGlobPatterns)(config_file_1.ESLINT_CONFIG_FILENAMES.map((f) => `**/${f}`));
|
18
|
+
const ESLINT_CONFIG_GLOB_V2 = (0, globs_1.combineGlobPatterns)([
|
17
19
|
...config_file_1.ESLINT_CONFIG_FILENAMES.map((f) => `**/${f}`),
|
18
|
-
|
19
|
-
config_file_1.baseEsLintFlatConfigFile,
|
20
|
+
...PROJECT_CONFIG_FILENAMES.map((f) => `**/${f}`),
|
20
21
|
]);
|
21
22
|
function readTargetsCache(cachePath) {
|
22
|
-
return
|
23
|
+
return process.env.NX_CACHE_PROJECT_GRAPH !== 'false' && (0, node_fs_1.existsSync)(cachePath)
|
24
|
+
? (0, devkit_1.readJsonFile)(cachePath)
|
25
|
+
: {};
|
23
26
|
}
|
24
27
|
function writeTargetsToCache(cachePath, results) {
|
25
28
|
(0, devkit_1.writeJsonFile)(cachePath, results);
|
@@ -32,11 +35,9 @@ const internalCreateNodes = async (configFilePath, options, context, projectsCac
|
|
32
35
|
context.configFiles = context.configFiles ?? [];
|
33
36
|
// Create a Set of all the directories containing eslint configs, and a
|
34
37
|
// list of globs to exclude from child projects
|
35
|
-
const eslintRoots = new Set();
|
36
38
|
const nestedEslintRootPatterns = [];
|
37
39
|
for (const configFile of context.configFiles) {
|
38
40
|
const eslintRootDir = (0, node_path_1.dirname)(configFile);
|
39
|
-
eslintRoots.add(eslintRootDir);
|
40
41
|
if (eslintRootDir !== configDir && isSubDir(configDir, eslintRootDir)) {
|
41
42
|
nestedEslintRootPatterns.push(`${eslintRootDir}/**/*`);
|
42
43
|
}
|
@@ -47,7 +48,6 @@ const internalCreateNodes = async (configFilePath, options, context, projectsCac
|
|
47
48
|
const excludePatterns = dedupedProjectRoots.map((root) => `${root}/**/*`);
|
48
49
|
const ESLint = await (0, resolve_eslint_class_1.resolveESLintClass)((0, config_file_1.isFlatConfig)(configFilePath));
|
49
50
|
const eslintVersion = ESLint.version;
|
50
|
-
const childProjectRoots = new Set();
|
51
51
|
const projects = {};
|
52
52
|
await Promise.all(dedupedProjectRoots.map(async (childProjectRoot, index) => {
|
53
53
|
// anything after is either a nested project or a sibling project, can be excluded
|
@@ -66,18 +66,80 @@ const internalCreateNodes = async (configFilePath, options, context, projectsCac
|
|
66
66
|
const eslint = new ESLint({
|
67
67
|
cwd: (0, node_path_1.join)(context.workspaceRoot, childProjectRoot),
|
68
68
|
});
|
69
|
+
let hasNonIgnoredLintableFiles = false;
|
69
70
|
for (const file of lintableFiles) {
|
70
71
|
if (!(await eslint.isPathIgnored((0, node_path_1.join)(context.workspaceRoot, file)))) {
|
71
|
-
|
72
|
+
hasNonIgnoredLintableFiles = true;
|
72
73
|
break;
|
73
74
|
}
|
74
75
|
}
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
76
|
+
if (!hasNonIgnoredLintableFiles) {
|
77
|
+
// No lintable files in the project, store in the cache and skip further processing
|
78
|
+
projectsCache[hash] = {};
|
79
|
+
return;
|
80
|
+
}
|
81
|
+
const project = getProjectUsingESLintConfig(configFilePath, childProjectRoot, eslintVersion, options, context);
|
82
|
+
if (project) {
|
83
|
+
projects[childProjectRoot] = project;
|
84
|
+
// Store project into the cache
|
85
|
+
projectsCache[hash] = { [childProjectRoot]: project };
|
86
|
+
}
|
87
|
+
else {
|
88
|
+
// No project found, store in the cache
|
89
|
+
projectsCache[hash] = {};
|
90
|
+
}
|
91
|
+
}));
|
92
|
+
return {
|
93
|
+
projects,
|
94
|
+
};
|
95
|
+
};
|
96
|
+
let collectingLintableFilesPromise;
|
97
|
+
const internalCreateNodesV2 = async (configFilePath, options, context, eslintConfigFiles, allProjectRoots, projectRootsByEslintRoots, lintableFilesPerProjectRoot, projectsCache) => {
|
98
|
+
const configDir = (0, node_path_1.dirname)(configFilePath);
|
99
|
+
const ESLint = await (0, resolve_eslint_class_1.resolveESLintClass)((0, config_file_1.isFlatConfig)(configFilePath));
|
100
|
+
const eslintVersion = ESLint.version;
|
101
|
+
const projects = {};
|
102
|
+
await Promise.all(projectRootsByEslintRoots.get(configDir).map(async (projectRoot) => {
|
103
|
+
const parentConfigs = eslintConfigFiles.filter((eslintConfig) => isSubDir(projectRoot, (0, node_path_1.dirname)(eslintConfig)));
|
104
|
+
const hash = await (0, calculate_hash_for_create_nodes_1.calculateHashForCreateNodes)(projectRoot, options, {
|
105
|
+
configFiles: eslintConfigFiles,
|
106
|
+
nxJsonConfiguration: context.nxJsonConfiguration,
|
107
|
+
workspaceRoot: context.workspaceRoot,
|
108
|
+
}, [...parentConfigs, (0, node_path_1.join)(projectRoot, '.eslintignore')]);
|
109
|
+
if (projectsCache[hash]) {
|
110
|
+
// We can reuse the projects in the cache.
|
111
|
+
Object.assign(projects, projectsCache[hash]);
|
112
|
+
return;
|
113
|
+
}
|
114
|
+
if (!lintableFilesPerProjectRoot.size) {
|
115
|
+
collectingLintableFilesPromise ??= collectLintableFilesByProjectRoot(lintableFilesPerProjectRoot, allProjectRoots, options, context);
|
116
|
+
await collectingLintableFilesPromise;
|
117
|
+
collectingLintableFilesPromise = null;
|
118
|
+
}
|
119
|
+
const eslint = new ESLint({
|
120
|
+
cwd: (0, node_path_1.join)(context.workspaceRoot, projectRoot),
|
121
|
+
});
|
122
|
+
let hasNonIgnoredLintableFiles = false;
|
123
|
+
for (const file of lintableFilesPerProjectRoot.get(projectRoot) ?? []) {
|
124
|
+
if (!(await eslint.isPathIgnored((0, node_path_1.join)(context.workspaceRoot, file)))) {
|
125
|
+
hasNonIgnoredLintableFiles = true;
|
126
|
+
break;
|
127
|
+
}
|
128
|
+
}
|
129
|
+
if (!hasNonIgnoredLintableFiles) {
|
130
|
+
// No lintable files in the project, store in the cache and skip further processing
|
131
|
+
projectsCache[hash] = {};
|
132
|
+
return;
|
133
|
+
}
|
134
|
+
const project = getProjectUsingESLintConfig(configFilePath, projectRoot, eslintVersion, options, context);
|
135
|
+
if (project) {
|
136
|
+
projects[projectRoot] = project;
|
137
|
+
// Store project into the cache
|
138
|
+
projectsCache[hash] = { [projectRoot]: project };
|
139
|
+
}
|
140
|
+
else {
|
141
|
+
// No project found, store in the cache
|
142
|
+
projectsCache[hash] = {};
|
81
143
|
}
|
82
144
|
}));
|
83
145
|
return {
|
@@ -85,13 +147,16 @@ const internalCreateNodes = async (configFilePath, options, context, projectsCac
|
|
85
147
|
};
|
86
148
|
};
|
87
149
|
exports.createNodesV2 = [
|
88
|
-
|
150
|
+
ESLINT_CONFIG_GLOB_V2,
|
89
151
|
async (configFiles, options, context) => {
|
152
|
+
options = normalizeOptions(options);
|
90
153
|
const optionsHash = (0, file_hasher_1.hashObject)(options);
|
91
154
|
const cachePath = (0, node_path_1.join)(cache_directory_1.workspaceDataDirectory, `eslint-${optionsHash}.hash`);
|
92
155
|
const targetsCache = readTargetsCache(cachePath);
|
156
|
+
const { eslintConfigFiles, projectRoots, projectRootsByEslintRoots } = splitConfigFiles(configFiles);
|
157
|
+
const lintableFilesPerProjectRoot = new Map();
|
93
158
|
try {
|
94
|
-
return await (0, devkit_1.createNodesFromFiles)((configFile, options, context) =>
|
159
|
+
return await (0, devkit_1.createNodesFromFiles)((configFile, options, context) => internalCreateNodesV2(configFile, options, context, eslintConfigFiles, projectRoots, projectRootsByEslintRoots, lintableFilesPerProjectRoot, targetsCache), eslintConfigFiles, options, context);
|
95
160
|
}
|
96
161
|
finally {
|
97
162
|
writeTargetsToCache(cachePath, targetsCache);
|
@@ -99,43 +164,95 @@ exports.createNodesV2 = [
|
|
99
164
|
},
|
100
165
|
];
|
101
166
|
exports.createNodes = [
|
102
|
-
|
167
|
+
ESLINT_CONFIG_GLOB_V1,
|
103
168
|
(configFilePath, options, context) => {
|
104
169
|
devkit_1.logger.warn('`createNodes` is deprecated. Update your plugin to utilize createNodesV2 instead. In Nx 20, this will change to the createNodesV2 API.');
|
105
170
|
return internalCreateNodes(configFilePath, options, context, {});
|
106
171
|
},
|
107
172
|
];
|
108
|
-
function
|
109
|
-
const
|
173
|
+
function splitConfigFiles(configFiles) {
|
174
|
+
const eslintConfigFiles = [];
|
175
|
+
const projectRoots = new Set();
|
176
|
+
for (const configFile of configFiles) {
|
177
|
+
if (PROJECT_CONFIG_FILENAMES.includes((0, node_path_1.basename)(configFile))) {
|
178
|
+
projectRoots.add((0, node_path_1.dirname)(configFile));
|
179
|
+
}
|
180
|
+
else {
|
181
|
+
eslintConfigFiles.push(configFile);
|
182
|
+
}
|
183
|
+
}
|
184
|
+
const uniqueProjectRoots = Array.from(projectRoots);
|
185
|
+
const projectRootsByEslintRoots = groupProjectRootsByEslintRoots(eslintConfigFiles, uniqueProjectRoots);
|
186
|
+
return {
|
187
|
+
eslintConfigFiles,
|
188
|
+
projectRoots: uniqueProjectRoots,
|
189
|
+
projectRootsByEslintRoots,
|
190
|
+
};
|
191
|
+
}
|
192
|
+
function groupProjectRootsByEslintRoots(eslintConfigFiles, projectRoots) {
|
193
|
+
const projectRootsByEslintRoots = new Map();
|
194
|
+
for (const eslintConfig of eslintConfigFiles) {
|
195
|
+
projectRootsByEslintRoots.set((0, node_path_1.dirname)(eslintConfig), []);
|
196
|
+
}
|
197
|
+
for (const projectRoot of projectRoots) {
|
198
|
+
const eslintRoot = getRootForDirectory(projectRoot, projectRootsByEslintRoots);
|
199
|
+
if (eslintRoot) {
|
200
|
+
projectRootsByEslintRoots.get(eslintRoot).push(projectRoot);
|
201
|
+
}
|
202
|
+
}
|
203
|
+
return projectRootsByEslintRoots;
|
204
|
+
}
|
205
|
+
async function collectLintableFilesByProjectRoot(lintableFilesPerProjectRoot, projectRoots, options, context) {
|
206
|
+
const lintableFiles = await (0, workspace_context_1.globWithWorkspaceContext)(context.workspaceRoot, [
|
207
|
+
`**/*.{${options.extensions.join(',')}}`,
|
208
|
+
]);
|
209
|
+
for (const projectRoot of projectRoots) {
|
210
|
+
lintableFilesPerProjectRoot.set(projectRoot, []);
|
211
|
+
}
|
212
|
+
for (const file of lintableFiles) {
|
213
|
+
const projectRoot = getRootForDirectory((0, node_path_1.dirname)(file), lintableFilesPerProjectRoot);
|
214
|
+
if (projectRoot) {
|
215
|
+
lintableFilesPerProjectRoot.get(projectRoot).push(file);
|
216
|
+
}
|
217
|
+
}
|
218
|
+
}
|
219
|
+
function getRootForDirectory(directory, roots) {
|
220
|
+
let currentPath = (0, node_path_1.normalize)(directory);
|
221
|
+
while (currentPath !== (0, node_path_1.dirname)(currentPath)) {
|
222
|
+
if (roots.has(currentPath)) {
|
223
|
+
return currentPath;
|
224
|
+
}
|
225
|
+
currentPath = (0, node_path_1.dirname)(currentPath);
|
226
|
+
}
|
227
|
+
return roots.has(currentPath) ? currentPath : null;
|
228
|
+
}
|
229
|
+
function getProjectUsingESLintConfig(configFilePath, projectRoot, eslintVersion, options, context) {
|
110
230
|
const rootEslintConfig = [
|
111
231
|
config_file_1.baseEsLintConfigFile,
|
112
232
|
config_file_1.baseEsLintFlatConfigFile,
|
113
233
|
...config_file_1.ESLINT_CONFIG_FILENAMES,
|
114
234
|
].find((f) => (0, node_fs_1.existsSync)((0, node_path_1.join)(context.workspaceRoot, f)));
|
115
235
|
// Add a lint target for each child project without an eslint config, with the root level config as an input
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
standaloneSrcPath = 'src';
|
122
|
-
}
|
123
|
-
else if ((0, node_fs_1.existsSync)((0, node_path_1.join)(context.workspaceRoot, projectRoot, 'lib'))) {
|
124
|
-
standaloneSrcPath = 'lib';
|
125
|
-
}
|
236
|
+
let standaloneSrcPath;
|
237
|
+
if (projectRoot === '.' &&
|
238
|
+
(0, node_fs_1.existsSync)((0, node_path_1.join)(context.workspaceRoot, projectRoot, 'package.json'))) {
|
239
|
+
if ((0, node_fs_1.existsSync)((0, node_path_1.join)(context.workspaceRoot, projectRoot, 'src'))) {
|
240
|
+
standaloneSrcPath = 'src';
|
126
241
|
}
|
127
|
-
if (
|
128
|
-
|
242
|
+
else if ((0, node_fs_1.existsSync)((0, node_path_1.join)(context.workspaceRoot, projectRoot, 'lib'))) {
|
243
|
+
standaloneSrcPath = 'lib';
|
129
244
|
}
|
130
|
-
const eslintConfigs = [configFilePath];
|
131
|
-
if (rootEslintConfig && !eslintConfigs.includes(rootEslintConfig)) {
|
132
|
-
eslintConfigs.unshift(rootEslintConfig);
|
133
|
-
}
|
134
|
-
projects[projectRoot] = {
|
135
|
-
targets: buildEslintTargets(eslintConfigs, eslintVersion, projectRoot, context.workspaceRoot, options, standaloneSrcPath),
|
136
|
-
};
|
137
245
|
}
|
138
|
-
|
246
|
+
if (projectRoot === '.' && !standaloneSrcPath) {
|
247
|
+
return null;
|
248
|
+
}
|
249
|
+
const eslintConfigs = [configFilePath];
|
250
|
+
if (rootEslintConfig && !eslintConfigs.includes(rootEslintConfig)) {
|
251
|
+
eslintConfigs.unshift(rootEslintConfig);
|
252
|
+
}
|
253
|
+
return {
|
254
|
+
targets: buildEslintTargets(eslintConfigs, eslintVersion, projectRoot, context.workspaceRoot, options, standaloneSrcPath),
|
255
|
+
};
|
139
256
|
}
|
140
257
|
function buildEslintTargets(eslintConfigs, eslintVersion, projectRoot, workspaceRoot, options, standaloneSrcPath) {
|
141
258
|
const isRootProject = projectRoot === '.';
|
@@ -172,16 +289,17 @@ function buildEslintTargets(eslintConfigs, eslintVersion, projectRoot, workspace
|
|
172
289
|
return targets;
|
173
290
|
}
|
174
291
|
function normalizeOptions(options) {
|
175
|
-
|
176
|
-
|
292
|
+
const normalizedOptions = {
|
293
|
+
targetName: options.targetName ?? 'lint',
|
294
|
+
};
|
177
295
|
// Normalize user input for extensions (strip leading . characters)
|
178
296
|
if (Array.isArray(options.extensions)) {
|
179
|
-
|
297
|
+
normalizedOptions.extensions = options.extensions.map((f) => f.replace(/^\.+/, ''));
|
180
298
|
}
|
181
299
|
else {
|
182
|
-
|
300
|
+
normalizedOptions.extensions = DEFAULT_EXTENSIONS;
|
183
301
|
}
|
184
|
-
return
|
302
|
+
return normalizedOptions;
|
185
303
|
}
|
186
304
|
/**
|
187
305
|
* Determines if `child` is a subdirectory of `parent`. This is a simplified
|
package/src/utils/config-file.js
CHANGED
@@ -27,31 +27,32 @@ exports.isFlatConfig = isFlatConfig;
|
|
27
27
|
// https://eslint.org/docs/latest/use/configure/configuration-files#configuration-file-resolution
|
28
28
|
function findFlatConfigFile(directory, workspaceRoot) {
|
29
29
|
let currentDir = (0, path_1.resolve)(workspaceRoot, directory);
|
30
|
-
|
31
|
-
return getConfigFileInDirectory(currentDir, exports.ESLINT_FLAT_CONFIG_FILENAMES);
|
32
|
-
}
|
33
|
-
while (currentDir !== workspaceRoot) {
|
30
|
+
while (true) {
|
34
31
|
const configFilePath = getConfigFileInDirectory(currentDir, exports.ESLINT_FLAT_CONFIG_FILENAMES);
|
35
32
|
if (configFilePath) {
|
36
33
|
return configFilePath;
|
37
34
|
}
|
35
|
+
if (currentDir === workspaceRoot) {
|
36
|
+
break;
|
37
|
+
}
|
38
38
|
currentDir = (0, path_1.dirname)(currentDir);
|
39
39
|
}
|
40
40
|
return null;
|
41
41
|
}
|
42
42
|
exports.findFlatConfigFile = findFlatConfigFile;
|
43
43
|
function findOldConfigFile(filePathOrDirectory, workspaceRoot) {
|
44
|
-
let currentDir = (0,
|
45
|
-
|
46
|
-
|
47
|
-
if (currentDir === workspaceRoot) {
|
48
|
-
return getConfigFileInDirectory(currentDir, exports.ESLINT_OLD_CONFIG_FILENAMES);
|
44
|
+
let currentDir = (0, path_1.resolve)(workspaceRoot, filePathOrDirectory);
|
45
|
+
if (!(0, fs_1.statSync)(currentDir).isDirectory()) {
|
46
|
+
currentDir = (0, path_1.dirname)(currentDir);
|
49
47
|
}
|
50
|
-
while (
|
48
|
+
while (true) {
|
51
49
|
const configFilePath = getConfigFileInDirectory(currentDir, exports.ESLINT_OLD_CONFIG_FILENAMES);
|
52
50
|
if (configFilePath) {
|
53
51
|
return configFilePath;
|
54
52
|
}
|
53
|
+
if (currentDir === workspaceRoot) {
|
54
|
+
break;
|
55
|
+
}
|
55
56
|
currentDir = (0, path_1.dirname)(currentDir);
|
56
57
|
}
|
57
58
|
return null;
|