Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: first approach to find existing eslint config #724

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions src/cli/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,10 @@ import { findTSLintConfiguration } from "../input/findTSLintConfiguration";
import { findTypeScriptConfiguration } from "../input/findTypeScriptConfiguration";
import { importer, ImporterDependencies } from "../input/importer";
import { mergeLintConfigurations } from "../input/mergeLintConfigurations";
import {
findExistingESLintConfiguration,
FindExistingESLintConfigurationDependencies,
} from "../input/findExistingESLintConfiguration";

const convertFileCommentsDependencies: ConvertFileCommentsDependencies = {
converters: ruleConverters,
Expand Down Expand Up @@ -133,6 +137,10 @@ const findOriginalConfigurationsDependencies: FindOriginalConfigurationsDependen
mergeLintConfigurations,
};

const findExistingESLintConfigurationDependencies: FindExistingESLintConfigurationDependencies = {
globAsync,
};

const collectCommentFileNamesDependencies: CollectCommentFileNamesDependencies = {
findTypeScriptConfiguration: bind(findTypeScriptConfiguration, findConfigurationDependencies),
};
Expand Down Expand Up @@ -216,6 +224,10 @@ const runCliDependencies: RunCliDependencies = {
findOriginalConfigurations,
findOriginalConfigurationsDependencies,
),
findExistingESLintConfiguration: bind(
findExistingESLintConfiguration,
findExistingESLintConfigurationDependencies,
),
logger: processLogger,
};

Expand Down
18 changes: 17 additions & 1 deletion src/cli/runCli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { version } from "../../package.json";
import { Logger } from "../adapters/logger";
import { SansDependencies } from "../binding";
import { Converter } from "../converters/types";
import { findExistingESLintConfiguration } from "../input/findExistingESLintConfiguration";
import {
AllOriginalConfigurations,
findOriginalConfigurations,
Expand All @@ -15,6 +16,7 @@ import { ResultStatus, ResultWithStatus, TSLintToESLintSettings } from "../types

export type RunCliDependencies = {
converters: Converter[];
findExistingESLintConfiguration: SansDependencies<typeof findExistingESLintConfiguration>;
findOriginalConfigurations: SansDependencies<typeof findOriginalConfigurations>;
logger: Logger;
};
Expand All @@ -41,7 +43,6 @@ export const runCli = async (
.option("-V, --version", "output the package version");

const parsedArgv = {
config: "./.eslintrc.js",
...command.parse(rawArgv).opts(),
} as TSLintToESLintSettings;

Expand All @@ -51,6 +52,21 @@ export const runCli = async (
return ResultStatus.Succeeded;
}

// 2-B. Lookup the eslint config file `.eslintrc.*` (js, json, yaml) / package.json file
const eslintConfiguration = await dependencies.findExistingESLintConfiguration();
if (eslintConfiguration.status !== ResultStatus.Succeeded) {
logErrorResult(eslintConfiguration, dependencies.logger);
} else {
if (Array.isArray(eslintConfiguration.data)) {
// Pick the first one, it should take into account the order of
// preference based on official ESLint Docs.
parsedArgv.config = eslintConfiguration.data[0];
} else {
// TODO: We need to keep the current package.json data
parsedArgv.config = "package.json";
}
}

// 3. Any existing linter and TypeScript configurations are read from disk.
const originalConfigurations = await dependencies.findOriginalConfigurations(parsedArgv);
if (originalConfigurations.status !== ResultStatus.Succeeded) {
Expand Down
40 changes: 40 additions & 0 deletions src/input/findExistingESLintConfiguration.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { fsFileSystem } from "../adapters/fsFileSystem";
import { GlobAsync } from "../adapters/globAsync";
import { ResultStatus, ResultWithDataStatus } from "../types";
import { ESLintConfiguration } from "./findESLintConfiguration";

export type FindExistingESLintConfigurationDependencies = {
globAsync: GlobAsync;
};

export const findExistingESLintConfiguration = async (
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Heh, yeah, the return type of this is what I was curious about... At first, I was thinking thinking the calling code will want to know whether this is an npm package style file or an ESLint one. For example, what happens if someone does something like --config ./packages/somewhere/package.json, and wants this to work on the eslintConfig in that nested file?

But, it's really only package.json files that have the odd eslintConfig member... Maybe the writing code would always want to override an existing eslintConfig in the output file if that output file's name ends with "package.json"? What do you think

dependencies: FindExistingESLintConfigurationDependencies,
): Promise<ResultWithDataStatus<ESLintConfiguration | string[]>> => {
const globResult = await dependencies.globAsync(".eslintrc.{js,json,yaml}");
const packageContent = await fsFileSystem.readFile("package.json");
if (!(globResult instanceof Error)) {
return {
data: globResult,
status: ResultStatus.Succeeded,
};
}
if (globResult instanceof Error && packageContent instanceof Error) {
return {
errors: [globResult, packageContent],
status: ResultStatus.Failed,
};
}
if (globResult instanceof Error && typeof packageContent === "string") {
Copy link
Member

@JoshuaKGoldberg JoshuaKGoldberg Sep 22, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit, just marking this down because it confused me at first 😛

Suggested change
if (globResult instanceof Error && typeof packageContent === "string") {
if (typeof packageContent === "string") {

const parsedPackage: Record<string, unknown> = JSON.parse(packageContent);
if (parsedPackage.hasOwnProperty("eslintConfig")) {
return {
data: parsedPackage.eslintConfig as ESLintConfiguration,
status: ResultStatus.Succeeded,
};
}
}
return {
errors: [new Error("Could not find an existing ESLint Config")],
status: ResultStatus.Failed,
};
};