Skip to content

Allowed custom .js or .json file outputs with --config #75

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

Merged
merged 2 commits into from
Jul 5, 2019
Merged
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
20 changes: 18 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,19 +36,35 @@ TSLint rules without ESLint equivalents will be wrapped with [eslint-plugin-tsli

Each of these flags is optional.

- **[`config`](#config)**: Path to print the generated ESLint configuration file to.
- **[`eslint`](#eslint)**: Path to an ESLint configuration file to read settings from.
- **[`package`](#package)**: Path to a package.json file to read dependencies from.
- **[`tslint`](#tslint)**: Path to a TSLint configuration file to read settings from.
- **[`typescript`](#typescript)**: Path to a TypeScript configuration file to read TypeScript compiler options from.

#### `eslint`
#### `config`

```shell
npx tslint-to-eslint-config --eslint ./path/to/eslintrc.json
npx tslint-to-eslint-config --config .eslintrc.json
```

_Default: `.eslintrc.js`_

Path to print the generated ESLint configuration file to.

The file extension of this path will be used to determine the format of the created file:

- `.js` file paths will be written `module.exports = ...` JavaScript
- Other file paths will default to JSON

#### `eslint`

```shell
npx tslint-to-eslint-config --eslint ./path/to/eslintrc.js
```

_Default: `--config`'s value_

Path to an ESLint configuration file to read settings from.
This isn't yet used for anything, but will eventually inform settings for the generated ESLint configuration file.

Expand Down
14 changes: 9 additions & 5 deletions src/cli/runCli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,17 @@ export const runCli = async (
): Promise<ResultStatus> => {
const command = new Command()
.usage("[options] <file ...> --language [language]")
.option("--eslint [eslint]", "eslint configuration file to convert")
.option("--package [package]", "package configuration file to convert")
.option("--tslint [tslint]", "tslint configuration file to convert")
.option("--typescript [typescript]", "typescript configuration file to convert")
.option("--config [config]", "eslint configuration file to output to")
.option("--eslint [eslint]", "eslint configuration file to convert using")
.option("--package [package]", "package configuration file to convert using")
.option("--tslint [tslint]", "tslint configuration file to convert using")
.option("--typescript [typescript]", "typescript configuration file to convert using")
.option("-V --version", "output the package version");

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

if ({}.hasOwnProperty.call(parsedArgv, "version")) {
dependencies.logger.stdout.write(`${version}${EOL}`);
Expand Down
8 changes: 6 additions & 2 deletions src/conversion/convertConfig.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@ describe("convertConfig", () => {
const dependencies = createStubDependencies({
findOriginalConfigurations: async () => findError,
});
const settings = {};
const settings = {
config: "./eslintrc.js",
};

// Act
const result = await convertConfig(dependencies, settings);
Expand All @@ -46,7 +48,9 @@ describe("convertConfig", () => {
const dependencies = createStubDependencies({
findOriginalConfigurations: async () => findSuccess,
});
const settings = {};
const settings = {
config: "./eslintrc.js",
};

// Act
const result = await convertConfig(dependencies, settings);
Expand Down
6 changes: 5 additions & 1 deletion src/conversion/convertConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,11 @@ export const convertConfig = async (
originalConfigurations.data.tslint.rules,
);

await dependencies.writeConversionResults(ruleConversionResults, originalConfigurations.data);
await dependencies.writeConversionResults(
settings.config,
ruleConversionResults,
originalConfigurations.data,
);
dependencies.reportConversionResults(ruleConversionResults);

return {
Expand Down
55 changes: 55 additions & 0 deletions src/creation/formatting/formatOutput.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { EOL } from "os";

import { formatOutput } from "./formatOutput";

describe("formatOutput", () => {
it("formats output as JavaScript for a .js file path", () => {
// Arrange
const outputPath = ".eslintrc.js";
const configuration = { rules: {} };

// Act
const output = formatOutput(outputPath, configuration);

// Assert
expect(output).toBe(
`module.exports = ${JSON.stringify(configuration, undefined, 4)};${EOL}`,
);
});

it("formats output as JSON for a .json file path", () => {
// Arrange
const outputPath = ".eslintrc.json";
const configuration = { rules: {} };

// Act
const output = formatOutput(outputPath, configuration);

// Assert
expect(output).toBe(`${JSON.stringify(configuration, undefined, 4)}${EOL}`);
});

it("formats output as JSON for an unknown dot file path", () => {
// Arrange
const outputPath = ".eslintrc";
const configuration = { rules: {} };

// Act
const output = formatOutput(outputPath, configuration);

// Assert
expect(output).toBe(`${JSON.stringify(configuration, undefined, 4)}${EOL}`);
});

it("formats output as JSON for an unknown raw file path", () => {
// Arrange
const outputPath = "eslintrc";
const configuration = { rules: {} };

// Act
const output = formatOutput(outputPath, configuration);

// Assert
expect(output).toBe(`${JSON.stringify(configuration, undefined, 4)}${EOL}`);
});
});
17 changes: 17 additions & 0 deletions src/creation/formatting/formatOutput.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { formatJsonOutput } from "./formatters/formatJsonOutput";
import { formatJsOutput } from "./formatters/formatJsOutput";

const formatters = new Map([["js", formatJsOutput]]);

export const formatOutput = (outputPath: string, configuration: unknown): string => {
const customFormatter = formatters.get(getExtension(outputPath));
const formatter = customFormatter === undefined ? formatJsonOutput : formatJsOutput;

return formatter(configuration);
};

const getExtension = (outputPath: string) => {
const periodIndex = outputPath.lastIndexOf(".");

return periodIndex === -1 ? outputPath : outputPath.slice(periodIndex + 1);
};
4 changes: 4 additions & 0 deletions src/creation/formatting/formatters/formatJsOutput.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { EOL } from "os";

export const formatJsOutput = (configuration: unknown) =>
`module.exports = ${JSON.stringify(configuration, undefined, 4)};${EOL}`;
4 changes: 4 additions & 0 deletions src/creation/formatting/formatters/formatJsonOutput.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { EOL } from "os";

export const formatJsonOutput = (configuration: unknown) =>
`${JSON.stringify(configuration, undefined, 4)}${EOL}`;
91 changes: 47 additions & 44 deletions src/creation/writeConversionResults.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { createEmptyConversionResults } from "../conversion/conversionResults.stubs";
import { writeConversionResults } from "./writeConversionResults";
import { formatJsonOutput } from "./formatting/formatters/formatJsonOutput";

const originalConfigurations = {
tslint: {
Expand All @@ -17,29 +18,30 @@ describe("writeConversionResults", () => {
const fileSystem = { writeFile: jest.fn().mockReturnValue(Promise.resolve()) };

// Act
await writeConversionResults({ fileSystem }, conversionResults, originalConfigurations);
await writeConversionResults(
{ fileSystem },
".eslintrc.json",
conversionResults,
originalConfigurations,
);

// Assert
expect(fileSystem.writeFile).toHaveBeenLastCalledWith(
".eslintrc.json",
JSON.stringify(
{
env: {
browser: true,
es6: true,
node: true,
},
parser: "@typescript-eslint/parser",
parserOptions: {
project: "tsconfig.json",
sourceType: "module",
},
plugins: ["@typescript-eslint"],
rules: {},
formatJsonOutput({
env: {
browser: true,
es6: true,
node: true,
},
undefined,
4,
),
parser: "@typescript-eslint/parser",
parserOptions: {
project: "tsconfig.json",
sourceType: "module",
},
plugins: ["@typescript-eslint"],
rules: {},
}),
);
});

Expand All @@ -58,38 +60,39 @@ describe("writeConversionResults", () => {
const fileSystem = { writeFile: jest.fn().mockReturnValue(Promise.resolve()) };

// Act
await writeConversionResults({ fileSystem }, conversionResults, originalConfigurations);
await writeConversionResults(
{ fileSystem },
".eslintrc.json",
conversionResults,
originalConfigurations,
);

// Assert
expect(fileSystem.writeFile).toHaveBeenLastCalledWith(
".eslintrc.json",
JSON.stringify(
{
env: {
browser: true,
es6: true,
node: true,
},
parser: "@typescript-eslint/parser",
parserOptions: {
project: "tsconfig.json",
sourceType: "module",
},
plugins: ["@typescript-eslint", "@typescript-eslint/tslint"],
rules: {
"@typescript-eslint/tslint/config": [
"error",
{
rules: {
"tslint-rule-one": true,
},
formatJsonOutput({
env: {
browser: true,
es6: true,
node: true,
},
parser: "@typescript-eslint/parser",
parserOptions: {
project: "tsconfig.json",
sourceType: "module",
},
plugins: ["@typescript-eslint", "@typescript-eslint/tslint"],
rules: {
"@typescript-eslint/tslint/config": [
"error",
{
rules: {
"tslint-rule-one": true,
},
],
},
},
],
},
undefined,
4,
),
}),
);
});
});
4 changes: 3 additions & 1 deletion src/creation/writeConversionResults.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@ import { RuleConversionResults } from "../rules/convertRules";
import { formatConvertedRules } from "./formatConvertedRules";
import { OriginalConfigurations } from "../input/findOriginalConfigurations";
import { createEnv } from "./eslint/createEnv";
import { formatOutput } from "./formatting/formatOutput";

export type WriteConversionResultsDependencies = {
fileSystem: Pick<FileSystem, "writeFile">;
};

export const writeConversionResults = async (
dependencies: WriteConversionResultsDependencies,
outputPath: string,
ruleConversionResults: RuleConversionResults,
originalConfigurations: OriginalConfigurations,
) => {
Expand All @@ -29,5 +31,5 @@ export const writeConversionResults = async (
rules: formatConvertedRules(ruleConversionResults, originalConfigurations.tslint),
};

await dependencies.fileSystem.writeFile(".eslintrc.json", JSON.stringify(output, undefined, 4));
await dependencies.fileSystem.writeFile(outputPath, formatOutput(outputPath, output));
};
19 changes: 15 additions & 4 deletions src/input/findESLintConfiguration.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
import { findESLintConfiguration } from "./findESLintConfiguration";
import { createStubExec, createStubThrowingExec } from "../adapters/exec.stubs";
import { TSLintToESLintSettings } from "../types";

const createStubRawSettings = (overrides: Partial<TSLintToESLintSettings> = {}) => ({
config: "./eslintrc.js",
eslint: undefined,
...overrides,
});

describe("findESLintConfiguration", () => {
it("returns an error when one occurs", async () => {
Expand All @@ -8,7 +15,7 @@ describe("findESLintConfiguration", () => {
const dependencies = { exec: createStubThrowingExec({ stderr: message }) };

// Act
const result = await findESLintConfiguration(dependencies, undefined);
const result = await findESLintConfiguration(dependencies, createStubRawSettings());

// Assert
expect(result).toEqual(
Expand All @@ -23,7 +30,7 @@ describe("findESLintConfiguration", () => {
const dependencies = { exec: createStubExec() };

// Act
await findESLintConfiguration(dependencies, undefined);
await findESLintConfiguration(dependencies, createStubRawSettings());

// Assert
expect(dependencies.exec).toHaveBeenLastCalledWith("eslint --print-config ./eslintrc.js");
Expand All @@ -32,7 +39,9 @@ describe("findESLintConfiguration", () => {
it("includes a configuration file in the ESLint command when one is provided", async () => {
// Arrange
const dependencies = { exec: createStubExec() };
const config = "./custom/eslintrc.js";
const config = createStubRawSettings({
eslint: "./custom/eslintrc.js",
});

// Act
await findESLintConfiguration(dependencies, config);
Expand All @@ -46,7 +55,9 @@ describe("findESLintConfiguration", () => {
it("applies ESLint defaults when none are provided", async () => {
// Arrange
const dependencies = { exec: createStubExec({ stdout: "{}" }) };
const config = "./custom/eslintrc.js";
const config = createStubRawSettings({
eslint: "./custom/eslintrc.js",
});

// Act
const result = await findESLintConfiguration(dependencies, config);
Expand Down
5 changes: 3 additions & 2 deletions src/input/findESLintConfiguration.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { TSLintToESLintSettings } from "../types";
import { findConfiguration, FindConfigurationDependencies } from "./findConfiguration";

export type ESLintConfiguration = {
Expand All @@ -16,12 +17,12 @@ const defaultESLintConfiguration = {

export const findESLintConfiguration = async (
dependencies: FindConfigurationDependencies,
config: string | undefined,
rawSettings: Pick<TSLintToESLintSettings, "config" | "eslint">,
): Promise<ESLintConfiguration | Error> => {
const rawConfiguration = await findConfiguration<ESLintConfiguration>(
dependencies.exec,
"eslint --print-config",
config || "./eslintrc.js",
rawSettings.eslint || rawSettings.config,
);

return rawConfiguration instanceof Error
Expand Down
Loading