Skip to content

Commit 1ddc3ad

Browse files
author
Josh Goldberg
committed
Allowed custom .js or .json file outputs with --config
As before, the output path defaults to `--eslintrc.js`. `--eslint` will default to `--config` which has that default. The format of the output path depends on its file extension, with JavaScript for `.js` files and JSON otherwise. The README.md list of flags is getting a little long so I added a quick manual table of contents. Will try to remember to split that into a separate PR...
1 parent 00ba52e commit 1ddc3ad

15 files changed

+198
-63
lines changed

README.md

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,35 @@ TSLint rules without ESLint equivalents will be wrapped with [eslint-plugin-tsli
3535

3636
Each of these flags is optional.
3737

38-
#### `eslint`
38+
- **[`config`](#config)**: Path to print the generated ESLint configuration file to.
39+
- **[`eslint`](#eslint)**: Path to an ESLint configuration file to read settings from.
40+
- **[`package`](#package)**: Path to a package.json file to read dependencies from.
41+
- **[`tslint`](#tslint)**: Path to a TSLint configuration file to read settings from.
42+
- **[`typescript`](#typescript)**: Path to a TypeScript configuration file to read TypeScript compiler options from.
43+
44+
#### `config`
3945

4046
```shell
41-
npx tslint-to-eslint-config --eslint ./path/to/seslintrc.json
47+
npx tslint-to-eslint-config --config .eslintrc.json
4248
```
4349

4450
_Default: `.eslintrc.js`_
4551

52+
Path to print the generated ESLint configuration file to.
53+
54+
The file extension of this path will be used to determine the format of the created file:
55+
56+
- `.js` file paths will be written `module.exports = ...` JavaScript
57+
- Other file paths will default to JSON
58+
59+
#### `eslint`
60+
61+
```shell
62+
npx tslint-to-eslint-config --eslint ./path/to/eslintrc.js
63+
```
64+
65+
_Default: `--config`'s value_
66+
4667
Path to an ESLint configuration file to read settings from.
4768
This isn't yet used for anything, but will eventually inform settings for the generated ESLint configuration file.
4869

@@ -76,7 +97,7 @@ npx tslint-to-eslint-config --typescript ./path/to/tsconfig.json
7697

7798
_Default: `tsconfig.json`_
7899

79-
Path to a `tsconfig.json` file to read TypeScript compiler options from.
100+
Path to a TypeScript configuration file to read TypeScript compiler options from.
80101
This will help inform the generated ESLint configuration file's [env](https://eslint.org/docs/user-guide/configuring#specifying-parser-options) settings.
81102

82103
## Development

src/cli/runCli.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,17 @@ export const runCli = async (
1919
): Promise<ResultStatus> => {
2020
const command = new Command()
2121
.usage("[options] <file ...> --language [language]")
22-
.option("--eslint [eslint]", "eslint configuration file to convert")
23-
.option("--package [package]", "package configuration file to convert")
24-
.option("--tslint [tslint]", "tslint configuration file to convert")
25-
.option("--typescript [typescript]", "typescript configuration file to convert")
22+
.option("--config [config]", "eslint configuration file to output to")
23+
.option("--eslint [eslint]", "eslint configuration file to convert using")
24+
.option("--package [package]", "package configuration file to convert using")
25+
.option("--tslint [tslint]", "tslint configuration file to convert using")
26+
.option("--typescript [typescript]", "typescript configuration file to convert using")
2627
.option("-V --version", "output the package version");
2728

28-
const parsedArgv = command.parse(rawArgv) as Partial<TSLintToESLintSettings>;
29+
const parsedArgv = {
30+
config: "./eslintrc.js",
31+
...(command.parse(rawArgv) as Partial<TSLintToESLintSettings>),
32+
};
2933

3034
if ({}.hasOwnProperty.call(parsedArgv, "version")) {
3135
dependencies.logger.stdout.write(`${version}${EOL}`);

src/conversion/convertConfig.test.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,9 @@ describe("convertConfig", () => {
2828
const dependencies = createStubDependencies({
2929
findOriginalConfigurations: async () => findError,
3030
});
31-
const settings = {};
31+
const settings = {
32+
config: "./eslintrc.js",
33+
};
3234

3335
// Act
3436
const result = await convertConfig(dependencies, settings);
@@ -46,7 +48,9 @@ describe("convertConfig", () => {
4648
const dependencies = createStubDependencies({
4749
findOriginalConfigurations: async () => findSuccess,
4850
});
49-
const settings = {};
51+
const settings = {
52+
config: "./eslintrc.js",
53+
};
5054

5155
// Act
5256
const result = await convertConfig(dependencies, settings);

src/conversion/convertConfig.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,11 @@ export const convertConfig = async (
2525
originalConfigurations.data.tslint.rules,
2626
);
2727

28-
await dependencies.writeConversionResults(ruleConversionResults, originalConfigurations.data);
28+
await dependencies.writeConversionResults(
29+
settings.config,
30+
ruleConversionResults,
31+
originalConfigurations.data,
32+
);
2933
dependencies.reportConversionResults(ruleConversionResults);
3034

3135
return {
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import { formatOutput } from "./formatOutput";
2+
import { EOL } from "os";
3+
4+
describe("formatOutput", () => {
5+
it("formats output as JavaScript for a .js file path", () => {
6+
// Arrange
7+
const outputPath = ".eslintrc.js";
8+
const configuration = { rules: {} };
9+
10+
// Act
11+
const output = formatOutput(outputPath, configuration);
12+
13+
// Assert
14+
expect(output).toBe(
15+
`module.exports = ${JSON.stringify(configuration, undefined, 4)};${EOL}`,
16+
);
17+
});
18+
19+
it("formats output as JSON for a .json file path", () => {
20+
// Arrange
21+
const outputPath = ".eslintrc.json";
22+
const configuration = { rules: {} };
23+
24+
// Act
25+
const output = formatOutput(outputPath, configuration);
26+
27+
// Assert
28+
expect(output).toBe(`${JSON.stringify(configuration, undefined, 4)}${EOL}`);
29+
});
30+
31+
it("formats output as JSON for an unknown dot file path", () => {
32+
// Arrange
33+
const outputPath = ".eslintrc";
34+
const configuration = { rules: {} };
35+
36+
// Act
37+
const output = formatOutput(outputPath, configuration);
38+
39+
// Assert
40+
expect(output).toBe(`${JSON.stringify(configuration, undefined, 4)}${EOL}`);
41+
});
42+
43+
it("formats output as JSON for an unknown raw file path", () => {
44+
// Arrange
45+
const outputPath = "eslintrc";
46+
const configuration = { rules: {} };
47+
48+
// Act
49+
const output = formatOutput(outputPath, configuration);
50+
51+
// Assert
52+
expect(output).toBe(`${JSON.stringify(configuration, undefined, 4)}${EOL}`);
53+
});
54+
});
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { formatJsonOutput } from "./formatters/formatJsonOutput";
2+
import { formatJsOutput } from "./formatters/formatJsOutput";
3+
4+
const formatters = new Map([["js", formatJsOutput]]);
5+
6+
export const formatOutput = (outputPath: string, configuration: unknown): string => {
7+
const customFormatter = formatters.get(getExtension(outputPath));
8+
const formatter = customFormatter === undefined ? formatJsonOutput : formatJsOutput;
9+
10+
return formatter(configuration);
11+
};
12+
13+
const getExtension = (outputPath: string) => {
14+
const periodIndex = outputPath.lastIndexOf(".");
15+
16+
return periodIndex === -1 ? outputPath : outputPath.slice(periodIndex + 1);
17+
};
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import { EOL } from "os";
2+
3+
export const formatJsOutput = (configuration: unknown) =>
4+
`module.exports = ${JSON.stringify(configuration, undefined, 4)};${EOL}`;
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import { EOL } from "os";
2+
3+
export const formatJsonOutput = (configuration: unknown) =>
4+
`${JSON.stringify(configuration, undefined, 4)}${EOL}`;
Lines changed: 47 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { createEmptyConversionResults } from "../conversion/conversionResults.stubs";
22
import { writeConversionResults } from "./writeConversionResults";
3+
import { formatJsonOutput } from "./formatting/formatters/formatJsonOutput";
34

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

1920
// Act
20-
await writeConversionResults({ fileSystem }, conversionResults, originalConfigurations);
21+
await writeConversionResults(
22+
{ fileSystem },
23+
".eslintrc.json",
24+
conversionResults,
25+
originalConfigurations,
26+
);
2127

2228
// Assert
2329
expect(fileSystem.writeFile).toHaveBeenLastCalledWith(
2430
".eslintrc.json",
25-
JSON.stringify(
26-
{
27-
env: {
28-
browser: true,
29-
es6: true,
30-
node: true,
31-
},
32-
parser: "@typescript-eslint/parser",
33-
parserOptions: {
34-
project: "tsconfig.json",
35-
sourceType: "module",
36-
},
37-
plugins: ["@typescript-eslint"],
38-
rules: {},
31+
formatJsonOutput({
32+
env: {
33+
browser: true,
34+
es6: true,
35+
node: true,
3936
},
40-
undefined,
41-
4,
42-
),
37+
parser: "@typescript-eslint/parser",
38+
parserOptions: {
39+
project: "tsconfig.json",
40+
sourceType: "module",
41+
},
42+
plugins: ["@typescript-eslint"],
43+
rules: {},
44+
}),
4345
);
4446
});
4547

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

6062
// Act
61-
await writeConversionResults({ fileSystem }, conversionResults, originalConfigurations);
63+
await writeConversionResults(
64+
{ fileSystem },
65+
".eslintrc.json",
66+
conversionResults,
67+
originalConfigurations,
68+
);
6269

6370
// Assert
6471
expect(fileSystem.writeFile).toHaveBeenLastCalledWith(
6572
".eslintrc.json",
66-
JSON.stringify(
67-
{
68-
env: {
69-
browser: true,
70-
es6: true,
71-
node: true,
72-
},
73-
parser: "@typescript-eslint/parser",
74-
parserOptions: {
75-
project: "tsconfig.json",
76-
sourceType: "module",
77-
},
78-
plugins: ["@typescript-eslint", "@typescript-eslint/tslint"],
79-
rules: {
80-
"@typescript-eslint/tslint/config": [
81-
"error",
82-
{
83-
rules: {
84-
"tslint-rule-one": true,
85-
},
73+
formatJsonOutput({
74+
env: {
75+
browser: true,
76+
es6: true,
77+
node: true,
78+
},
79+
parser: "@typescript-eslint/parser",
80+
parserOptions: {
81+
project: "tsconfig.json",
82+
sourceType: "module",
83+
},
84+
plugins: ["@typescript-eslint", "@typescript-eslint/tslint"],
85+
rules: {
86+
"@typescript-eslint/tslint/config": [
87+
"error",
88+
{
89+
rules: {
90+
"tslint-rule-one": true,
8691
},
87-
],
88-
},
92+
},
93+
],
8994
},
90-
undefined,
91-
4,
92-
),
95+
}),
9396
);
9497
});
9598
});

src/creation/writeConversionResults.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,15 @@ import { RuleConversionResults } from "../rules/convertRules";
33
import { formatConvertedRules } from "./formatConvertedRules";
44
import { OriginalConfigurations } from "../input/findOriginalConfigurations";
55
import { createEnv } from "./eslint/createEnv";
6+
import { formatOutput } from "./formatting/formatOutput";
67

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

1112
export const writeConversionResults = async (
1213
dependencies: WriteConversionResultsDependencies,
14+
outputPath: string,
1315
ruleConversionResults: RuleConversionResults,
1416
originalConfigurations: OriginalConfigurations,
1517
) => {
@@ -29,5 +31,5 @@ export const writeConversionResults = async (
2931
rules: formatConvertedRules(ruleConversionResults, originalConfigurations.tslint),
3032
};
3133

32-
await dependencies.fileSystem.writeFile(".eslintrc.json", JSON.stringify(output, undefined, 4));
34+
await dependencies.fileSystem.writeFile(outputPath, formatOutput(outputPath, output));
3335
};

src/input/findESLintConfiguration.test.ts

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
import { findESLintConfiguration } from "./findESLintConfiguration";
22
import { createStubExec, createStubThrowingExec } from "../adapters/exec.stubs";
3+
import { TSLintToESLintSettings } from "../types";
4+
5+
const createStubRawSettings = (overrides: Partial<TSLintToESLintSettings> = {}) => ({
6+
config: "./eslintrc.js",
7+
eslint: undefined,
8+
...overrides,
9+
});
310

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

1017
// Act
11-
const result = await findESLintConfiguration(dependencies, undefined);
18+
const result = await findESLintConfiguration(dependencies, createStubRawSettings());
1219

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

2532
// Act
26-
await findESLintConfiguration(dependencies, undefined);
33+
await findESLintConfiguration(dependencies, createStubRawSettings());
2734

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

3746
// Act
3847
await findESLintConfiguration(dependencies, config);
@@ -46,7 +55,9 @@ describe("findESLintConfiguration", () => {
4655
it("applies ESLint defaults when none are provided", async () => {
4756
// Arrange
4857
const dependencies = { exec: createStubExec({ stdout: "{}" }) };
49-
const config = "./custom/eslintrc.js";
58+
const config = createStubRawSettings({
59+
eslint: "./custom/eslintrc.js",
60+
});
5061

5162
// Act
5263
const result = await findESLintConfiguration(dependencies, config);

0 commit comments

Comments
 (0)