ts-reconf 0.1.0
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/LICENSE +21 -0
- package/README.md +84 -0
- package/dist/analyzer.d.ts +3 -0
- package/dist/analyzer.js +17 -0
- package/dist/analyzer.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +27 -0
- package/dist/cli.js.map +1 -0
- package/dist/loadTsConfig.d.ts +2 -0
- package/dist/loadTsConfig.js +12 -0
- package/dist/loadTsConfig.js.map +1 -0
- package/dist/reporter.d.ts +3 -0
- package/dist/reporter.js +46 -0
- package/dist/reporter.js.map +1 -0
- package/dist/rules/allowJsCheck.d.ts +2 -0
- package/dist/rules/allowJsCheck.js +19 -0
- package/dist/rules/allowJsCheck.js.map +1 -0
- package/dist/rules/defaultRedundant.d.ts +2 -0
- package/dist/rules/defaultRedundant.js +77 -0
- package/dist/rules/defaultRedundant.js.map +1 -0
- package/dist/rules/index.d.ts +10 -0
- package/dist/rules/index.js +11 -0
- package/dist/rules/index.js.map +1 -0
- package/dist/rules/legacyOption.d.ts +2 -0
- package/dist/rules/legacyOption.js +42 -0
- package/dist/rules/legacyOption.js.map +1 -0
- package/dist/rules/moduleResolutionMismatch.d.ts +2 -0
- package/dist/rules/moduleResolutionMismatch.js +52 -0
- package/dist/rules/moduleResolutionMismatch.js.map +1 -0
- package/dist/rules/moduleTypeCheck.d.ts +2 -0
- package/dist/rules/moduleTypeCheck.js +23 -0
- package/dist/rules/moduleTypeCheck.js.map +1 -0
- package/dist/rules/noEmitOutDir.d.ts +2 -0
- package/dist/rules/noEmitOutDir.js +19 -0
- package/dist/rules/noEmitOutDir.js.map +1 -0
- package/dist/rules/noIncludeOrFiles.d.ts +2 -0
- package/dist/rules/noIncludeOrFiles.js +20 -0
- package/dist/rules/noIncludeOrFiles.js.map +1 -0
- package/dist/rules/skipLibCheckExplain.d.ts +2 -0
- package/dist/rules/skipLibCheckExplain.js +17 -0
- package/dist/rules/skipLibCheckExplain.js.map +1 -0
- package/dist/rules/strictRedundant.d.ts +2 -0
- package/dist/rules/strictRedundant.js +28 -0
- package/dist/rules/strictRedundant.js.map +1 -0
- package/dist/rules/targetLibConflict.d.ts +2 -0
- package/dist/rules/targetLibConflict.js +79 -0
- package/dist/rules/targetLibConflict.js.map +1 -0
- package/dist/types.d.ts +13 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +41 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 rockcoder
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# ts-reconf
|
|
2
|
+
|
|
3
|
+
> Helps you better understand and simplify your `tsconfig.json` and tries to make it a bit less confusing
|
|
4
|
+
|
|
5
|
+
`ts-reconf` analyzes your TypeScript configuration and helps you:
|
|
6
|
+
- detect redundant, deprecated and default compiler options that could be removed
|
|
7
|
+
- understand what some setting actually does
|
|
8
|
+
- reduce complexity and confusion
|
|
9
|
+
- build a cleaner, more intentional config
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Why?
|
|
14
|
+
|
|
15
|
+
Most `tsconfig.json` files are:
|
|
16
|
+
- copied from somewhere
|
|
17
|
+
- accumulated over years
|
|
18
|
+
- full of redundant or outdated options
|
|
19
|
+
|
|
20
|
+
Developers often:
|
|
21
|
+
- don’t know what half the options do
|
|
22
|
+
- are afraid to remove anything
|
|
23
|
+
- end up with overly complex configs
|
|
24
|
+
|
|
25
|
+
**ts-reconf exists to fix that.**
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## Installation & usage
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
npm install -g ts-reconf
|
|
33
|
+
ts-reconf analyze [./tsconfig.json]
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Run without installation
|
|
37
|
+
|
|
38
|
+
You can run `ts-reconf` instantly without installing it globally:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
npx ts-reconf analyze
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Run from the source
|
|
45
|
+
|
|
46
|
+
Clone the repository and run the CLI locally:
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
npx tsx src/cli.ts analyze [./tsconfig.json]
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## Example
|
|
55
|
+
|
|
56
|
+
### Input
|
|
57
|
+
|
|
58
|
+
```json
|
|
59
|
+
{
|
|
60
|
+
"compilerOptions": {
|
|
61
|
+
"strict": true,
|
|
62
|
+
"noImplicitAny": true,
|
|
63
|
+
"skipLibCheck": true,
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Output tsconfig findings:
|
|
69
|
+
|
|
70
|
+
#### Redundant
|
|
71
|
+
- `noImplicitAny` is redundant because `strict` already enables it
|
|
72
|
+
|
|
73
|
+
#### Explanation
|
|
74
|
+
- `skipLibCheck` skips type checking of declaration files (*.d.ts)
|
|
75
|
+
→ improves build speed but may hide type issues
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## Contributing
|
|
81
|
+
|
|
82
|
+
Rules are small and easy to write. If you’ve ever thought:
|
|
83
|
+
“this tsconfig option is confusing or unnecessary”
|
|
84
|
+
— why not turn that into a rule .
|
package/dist/analyzer.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { legacyOptionRule, strictRedundantRule, skipLibCheckRule, defaultRedundantRule, targetLibConflictRule, moduleKindCheckRule, allowJsCheckRule, noEmitOutDirCheckRule, noIncludeOrFilesCheckRule, moduleResolutionMismatchRule, } from "./rules/index.js";
|
|
2
|
+
const rules = [
|
|
3
|
+
legacyOptionRule,
|
|
4
|
+
strictRedundantRule,
|
|
5
|
+
skipLibCheckRule,
|
|
6
|
+
defaultRedundantRule,
|
|
7
|
+
targetLibConflictRule,
|
|
8
|
+
moduleKindCheckRule,
|
|
9
|
+
allowJsCheckRule,
|
|
10
|
+
noEmitOutDirCheckRule,
|
|
11
|
+
noIncludeOrFilesCheckRule,
|
|
12
|
+
moduleResolutionMismatchRule,
|
|
13
|
+
];
|
|
14
|
+
export function analyze(config) {
|
|
15
|
+
return rules.flatMap(rule => rule.analyze(config));
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=analyzer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analyzer.js","sourceRoot":"","sources":["../src/analyzer.ts"],"names":[],"mappings":"AAIA,OAAO,EACH,gBAAgB,EAChB,mBAAmB,EACnB,gBAAgB,EAChB,oBAAoB,EACpB,qBAAqB,EACrB,mBAAmB,EACnB,gBAAgB,EAChB,qBAAqB,EACrB,yBAAyB,EACzB,4BAA4B,GAC/B,MAAM,kBAAkB,CAAC;AAE1B,MAAM,KAAK,GAAW;IAClB,gBAAgB;IAChB,mBAAmB;IACnB,gBAAgB;IAChB,oBAAoB;IACpB,qBAAqB;IACrB,mBAAmB;IACnB,gBAAgB;IAChB,qBAAqB;IACrB,yBAAyB;IACzB,4BAA4B;CAC/B,CAAC;AAEF,MAAM,UAAU,OAAO,CAAC,MAAuB;IAC3C,OAAO,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;AACvD,CAAC"}
|
package/dist/cli.d.ts
ADDED
package/dist/cli.js
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { loadTsConfig } from "./loadTsConfig.js";
|
|
3
|
+
import { analyze } from "./analyzer.js";
|
|
4
|
+
import { toMarkdown, toPrettyOutput } from "./reporter.js";
|
|
5
|
+
const [, , command, fileArg] = process.argv;
|
|
6
|
+
if (command !== "analyze" && fileArg) {
|
|
7
|
+
console.log("Usage: ts-reconf analyze [tsconfig.json]");
|
|
8
|
+
process.exit(1);
|
|
9
|
+
}
|
|
10
|
+
const file = fileArg ?? (command?.endsWith(".json") ? command : undefined) ?? "tsconfig.json";
|
|
11
|
+
try {
|
|
12
|
+
const config = loadTsConfig(file);
|
|
13
|
+
const findings = analyze(config);
|
|
14
|
+
const compactOuput = false;
|
|
15
|
+
const report = compactOuput ? toMarkdown(findings, file) : toPrettyOutput(findings, file);
|
|
16
|
+
console.log(report);
|
|
17
|
+
}
|
|
18
|
+
catch (err) {
|
|
19
|
+
if (err instanceof Error) {
|
|
20
|
+
console.error("Error:", err.message);
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
console.error("Error:", err);
|
|
24
|
+
}
|
|
25
|
+
process.exit(1);
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAE3D,MAAM,CAAC,EAAE,AAAD,EAAG,OAAO,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;AAE5C,IAAI,OAAO,KAAK,SAAS,IAAI,OAAO,EAAE,CAAC;IACnC,OAAO,CAAC,GAAG,CAAC,0CAA0C,CAAC,CAAC;IACxD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACpB,CAAC;AAED,MAAM,IAAI,GAAG,OAAO,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,eAAe,CAAC;AAE9F,IAAI,CAAC;IACD,MAAM,MAAM,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IAElC,MAAM,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAEjC,MAAM,YAAY,GAAG,KAAK,CAAC;IAE3B,MAAM,MAAM,GAAG,YAAY,CAAC,CAAC,CAAC,UAAU,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IAE1F,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;AAExB,CAAC;AAAC,OAAO,GAAY,EAAE,CAAC;IACpB,IAAI,GAAG,YAAY,KAAK,EAAE,CAAC;QACvB,OAAO,CAAC,KAAK,CAAC,QAAQ,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;IACzC,CAAC;SAAM,CAAC;QACJ,OAAO,CAAC,KAAK,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;IACjC,CAAC;IACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACpB,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import ts from "typescript";
|
|
2
|
+
import path from "path";
|
|
3
|
+
export function loadTsConfig(tsconfigPath) {
|
|
4
|
+
const configFile = ts.readConfigFile(tsconfigPath, ts.sys.readFile);
|
|
5
|
+
if (configFile.error) {
|
|
6
|
+
throw new Error(ts.flattenDiagnosticMessageText(configFile.error.messageText, "\n"));
|
|
7
|
+
}
|
|
8
|
+
const configDir = path.dirname(tsconfigPath);
|
|
9
|
+
const parsedTSConfig = ts.parseJsonConfigFileContent(configFile.config, ts.sys, configDir);
|
|
10
|
+
return parsedTSConfig.options;
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=loadTsConfig.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loadTsConfig.js","sourceRoot":"","sources":["../src/loadTsConfig.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,MAAM,YAAY,CAAC;AACjD,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,MAAM,UAAU,YAAY,CAAC,YAAoB;IAC7C,MAAM,UAAU,GAAG,EAAE,CAAC,cAAc,CAAC,YAAY,EAAE,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAEpE,IAAI,UAAU,CAAC,KAAK,EAAE,CAAC;QACnB,MAAM,IAAI,KAAK,CACX,EAAE,CAAC,4BAA4B,CAC3B,UAAU,CAAC,KAAK,CAAC,WAAW,EAC5B,IAAI,CACP,CACJ,CAAC;IACN,CAAC;IAED,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;IAE7C,MAAM,cAAc,GAAG,EAAE,CAAC,0BAA0B,CAChD,UAAU,CAAC,MAAM,EACjB,EAAE,CAAC,GAAG,EACN,SAAS,CACZ,CAAC;IAEF,OAAO,cAAc,CAAC,OAAO,CAAC;AAClC,CAAC"}
|
package/dist/reporter.js
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
const NO_ISSUES_FOUND_MSG = "## Looks good! 🎉 No issues found ✔\n";
|
|
2
|
+
export function toMarkdown(findings, file) {
|
|
3
|
+
const lines = [`## tsconfig findings for ${file ?? ""}:\n`];
|
|
4
|
+
if (findings.length === 0) {
|
|
5
|
+
lines.push(NO_ISSUES_FOUND_MSG);
|
|
6
|
+
return lines.join("\n");
|
|
7
|
+
}
|
|
8
|
+
for (const finding of findings) {
|
|
9
|
+
lines.push(`- ${finding.message}`);
|
|
10
|
+
}
|
|
11
|
+
return lines.join("\n");
|
|
12
|
+
}
|
|
13
|
+
function groupByCategory(findings) {
|
|
14
|
+
const groups = {};
|
|
15
|
+
for (const finding of findings) {
|
|
16
|
+
if (!groups[finding.category]) {
|
|
17
|
+
groups[finding.category] = [];
|
|
18
|
+
}
|
|
19
|
+
groups[finding.category].push(finding);
|
|
20
|
+
}
|
|
21
|
+
return groups;
|
|
22
|
+
}
|
|
23
|
+
export function toPrettyOutput(findings, file) {
|
|
24
|
+
const lines = [];
|
|
25
|
+
lines.push(`\n## ¸'ts-reconf' Analyzing ${file ?? "tsconfig.json"}...`);
|
|
26
|
+
if (findings.length === 0) {
|
|
27
|
+
lines.push(NO_ISSUES_FOUND_MSG);
|
|
28
|
+
return lines.join("\n");
|
|
29
|
+
}
|
|
30
|
+
lines.push("Findings:\n");
|
|
31
|
+
lines.push("────────────────────────────────\n");
|
|
32
|
+
const groups = groupByCategory(findings);
|
|
33
|
+
for (const [category, items] of Object.entries(groups)) {
|
|
34
|
+
const title = category.charAt(0).toUpperCase() +
|
|
35
|
+
category.slice(1);
|
|
36
|
+
lines.push(`${title} (${items.length})`);
|
|
37
|
+
for (const item of items) {
|
|
38
|
+
lines.push(` • ${item.message}`);
|
|
39
|
+
}
|
|
40
|
+
lines.push("");
|
|
41
|
+
}
|
|
42
|
+
lines.push("────────────────────────────────\n");
|
|
43
|
+
lines.push("✔ Done\n");
|
|
44
|
+
return lines.join("\n");
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=reporter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reporter.js","sourceRoot":"","sources":["../src/reporter.ts"],"names":[],"mappings":"AAEA,MAAM,mBAAmB,GAAG,uCAAuC,CAAC;AAEpE,MAAM,UAAU,UAAU,CAAC,QAAmB,EAAE,IAAa;IACzD,MAAM,KAAK,GAAG,CAAC,4BAA4B,IAAI,IAAI,EAAE,KAAK,CAAC,CAAC;IAE5D,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;QAChC,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC5B,CAAC;IAED,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC7B,KAAK,CAAC,IAAI,CAAC,KAAK,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;IACvC,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC5B,CAAC;AAED,SAAS,eAAe,CAAC,QAAmB;IACxC,MAAM,MAAM,GAA8B,EAAE,CAAC;IAE7C,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC7B,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC5B,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC;QAClC,CAAC;QACD,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC3C,CAAC;IAED,OAAO,MAAM,CAAC;AAClB,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,QAAmB,EAAE,IAAa;IAC7D,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,KAAK,CAAC,IAAI,CAAC,+BAA+B,IAAI,IAAI,eAAe,KAAK,CAAC,CAAC;IAExE,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;QAChC,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC5B,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IAC1B,KAAK,CAAC,IAAI,CAAC,oCAAoC,CAAC,CAAC;IAEjD,MAAM,MAAM,GAAG,eAAe,CAAC,QAAQ,CAAC,CAAC;IAEzC,KAAK,MAAM,CAAC,QAAQ,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QACrD,MAAM,KAAK,GACP,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE;YAChC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAEtB,KAAK,CAAC,IAAI,CAAC,GAAG,KAAK,KAAK,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC;QAEzC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACvB,KAAK,CAAC,IAAI,CAAC,OAAO,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;QACtC,CAAC;QAED,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACnB,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,oCAAoC,CAAC,CAAC;IACjD,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAEvB,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC5B,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
const ruleId = "ts.allowJs.check";
|
|
2
|
+
export const allowJsCheckRule = {
|
|
3
|
+
id: ruleId,
|
|
4
|
+
analyze(config) {
|
|
5
|
+
const allowJs = config.allowJs;
|
|
6
|
+
if (!allowJs) {
|
|
7
|
+
return [];
|
|
8
|
+
}
|
|
9
|
+
const findings = [];
|
|
10
|
+
findings.push({
|
|
11
|
+
ruleId: ruleId,
|
|
12
|
+
severity: "info",
|
|
13
|
+
message: `The "allowJs" option is enabled, TypeScript will include .js files in compilation. Ensure this is intentional. Disable it if you are not mixing JS and TS.`,
|
|
14
|
+
category: "explanation"
|
|
15
|
+
});
|
|
16
|
+
return findings;
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
//# sourceMappingURL=allowJsCheck.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"allowJsCheck.js","sourceRoot":"","sources":["../../src/rules/allowJsCheck.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,GAAG,kBAAkB,CAAC;AAElC,MAAM,CAAC,MAAM,gBAAgB,GAAS;IAClC,EAAE,EAAE,MAAM;IACV,OAAO,CAAC,MAAuB;QAE3B,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC;QAE/B,IAAI,CAAC,OAAO,EAAE,CAAC;YACX,OAAO,EAAE,CAAC;QACd,CAAC;QAED,MAAM,QAAQ,GAAc,EAAE,CAAC;QAE/B,QAAQ,CAAC,IAAI,CAAC;YACV,MAAM,EAAE,MAAM;YACd,QAAQ,EAAE,MAAM;YAChB,OAAO,EAAE,4JAA4J;YACrK,QAAQ,EAAE,aAAa;SAC1B,CAAC,CAAC;QAEH,OAAO,QAAQ,CAAC;IACpB,CAAC;CACJ,CAAC"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
const ruleId = "ts.default.redundant";
|
|
2
|
+
/**
|
|
3
|
+
* Curated subset of "stable" TypeScript defaults.
|
|
4
|
+
*/
|
|
5
|
+
const DEFAULTS = {
|
|
6
|
+
newLine: "lf",
|
|
7
|
+
chartset: "utf8",
|
|
8
|
+
importsNotUsedAsValues: "remove",
|
|
9
|
+
moduleDetection: "auto",
|
|
10
|
+
reactNamespace: "React",
|
|
11
|
+
removeComments: false,
|
|
12
|
+
sourceMap: false,
|
|
13
|
+
noEmit: false,
|
|
14
|
+
// Completeness
|
|
15
|
+
skipLibCheck: false,
|
|
16
|
+
skipDefaultLibCheck: false,
|
|
17
|
+
// Output Formatting
|
|
18
|
+
noErrorTruncation: false,
|
|
19
|
+
preserveConstEnums: false,
|
|
20
|
+
pretty: true,
|
|
21
|
+
// Modules
|
|
22
|
+
allowArbitraryExtensions: false,
|
|
23
|
+
allowImportingTsExtensions: false,
|
|
24
|
+
allowUmdGlobalAccess: false,
|
|
25
|
+
noResolve: false,
|
|
26
|
+
noUncheckedSideEffectImports: false,
|
|
27
|
+
resolveJsonModule: false,
|
|
28
|
+
rewriteRelativeImportExtensions: false,
|
|
29
|
+
// Interop Constraints
|
|
30
|
+
esModuleInterop: false,
|
|
31
|
+
forceConsistentCasingInFileNames: true,
|
|
32
|
+
isolatedDeclarations: false,
|
|
33
|
+
isolatedModules: false,
|
|
34
|
+
preserveSymlinks: false,
|
|
35
|
+
verbatimModuleSyntax: false,
|
|
36
|
+
// Type Checking
|
|
37
|
+
noFallthroughCasesInSwitch: false,
|
|
38
|
+
noImplicitOverride: false,
|
|
39
|
+
noImplicitReturns: false,
|
|
40
|
+
// Language and Environment
|
|
41
|
+
emitDecoratorMetadata: false,
|
|
42
|
+
experimentalDecorators: false,
|
|
43
|
+
noLib: false,
|
|
44
|
+
target: "es5",
|
|
45
|
+
};
|
|
46
|
+
/*
|
|
47
|
+
// defaults to consider?
|
|
48
|
+
{
|
|
49
|
+
allowJs: false,
|
|
50
|
+
declaration: false,
|
|
51
|
+
incremental: false,
|
|
52
|
+
isolatedModules: false,
|
|
53
|
+
"esModuleInterop": false,
|
|
54
|
+
"skipLibCheck": false,
|
|
55
|
+
}
|
|
56
|
+
*/
|
|
57
|
+
function isEqual(a, b) {
|
|
58
|
+
return JSON.stringify(a) === JSON.stringify(b);
|
|
59
|
+
}
|
|
60
|
+
export const defaultRedundantRule = {
|
|
61
|
+
id: ruleId,
|
|
62
|
+
analyze(config) {
|
|
63
|
+
const findings = [];
|
|
64
|
+
for (const [option, defaultValue] of Object.entries(DEFAULTS)) {
|
|
65
|
+
if (option in config && isEqual(config[option], defaultValue)) {
|
|
66
|
+
findings.push({
|
|
67
|
+
ruleId: ruleId,
|
|
68
|
+
severity: "info",
|
|
69
|
+
message: `${option} is explicitly set to its default value (${JSON.stringify(defaultValue)}). It could be potentially removed.`,
|
|
70
|
+
category: "redundant"
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return findings;
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
//# sourceMappingURL=defaultRedundant.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"defaultRedundant.js","sourceRoot":"","sources":["../../src/rules/defaultRedundant.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,GAAG,sBAAsB,CAAC;AAEtC;;GAEG;AACH,MAAM,QAAQ,GAAoD;IAC9D,OAAO,EAAE,IAAI;IACb,QAAQ,EAAE,MAAM;IAChB,sBAAsB,EAAE,QAAQ;IAChC,eAAe,EAAE,MAAM;IACvB,cAAc,EAAE,OAAO;IACvB,cAAc,EAAE,KAAK;IACrB,SAAS,EAAE,KAAK;IAChB,MAAM,EAAE,KAAK;IACb,eAAe;IACf,YAAY,EAAE,KAAK;IACnB,mBAAmB,EAAE,KAAK;IAC1B,oBAAoB;IACpB,iBAAiB,EAAE,KAAK;IACxB,kBAAkB,EAAE,KAAK;IACzB,MAAM,EAAE,IAAI;IACZ,UAAU;IACV,wBAAwB,EAAE,KAAK;IAC/B,0BAA0B,EAAE,KAAK;IACjC,oBAAoB,EAAE,KAAK;IAC3B,SAAS,EAAE,KAAK;IAChB,4BAA4B,EAAE,KAAK;IACnC,iBAAiB,EAAE,KAAK;IACxB,+BAA+B,EAAE,KAAK;IACtC,sBAAsB;IACtB,eAAe,EAAE,KAAK;IACtB,gCAAgC,EAAE,IAAI;IACtC,oBAAoB,EAAE,KAAK;IAC3B,eAAe,EAAE,KAAK;IACtB,gBAAgB,EAAE,KAAK;IACvB,oBAAoB,EAAE,KAAK;IAC3B,gBAAgB;IAChB,0BAA0B,EAAE,KAAK;IACjC,kBAAkB,EAAE,KAAK;IACzB,iBAAiB,EAAE,KAAK;IACxB,2BAA2B;IAC3B,qBAAqB,EAAE,KAAK;IAC5B,sBAAsB,EAAE,KAAK;IAC7B,KAAK,EAAE,KAAK;IACZ,MAAM,EAAE,KAAK;CAChB,CAAC;AAEF;;;;;;;;;;EAUE;AAEF,SAAS,OAAO,CAAC,CAAU,EAAE,CAAU;IACnC,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;AACnD,CAAC;AAED,MAAM,CAAC,MAAM,oBAAoB,GAAS;IACtC,EAAE,EAAE,MAAM;IAEV,OAAO,CAAC,MAAM;QACV,MAAM,QAAQ,GAAc,EAAE,CAAC;QAE/B,KAAK,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC5D,IAAI,MAAM,IAAI,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,YAAY,CAAC,EAAE,CAAC;gBAC5D,QAAQ,CAAC,IAAI,CAAC;oBACV,MAAM,EAAE,MAAM;oBACd,QAAQ,EAAE,MAAM;oBAChB,OAAO,EAAE,GAAG,MAAM,4CAA4C,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,qCAAqC;oBAC/H,QAAQ,EAAE,WAAW;iBACxB,CAAC,CAAC;YACP,CAAC;QACL,CAAC;QAED,OAAO,QAAQ,CAAC;IACpB,CAAC;CACJ,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export { legacyOptionRule } from "./legacyOption.js";
|
|
2
|
+
export { strictRedundantRule } from "./strictRedundant.js";
|
|
3
|
+
export { skipLibCheckRule } from "./skipLibCheckExplain.js";
|
|
4
|
+
export { defaultRedundantRule } from "./defaultRedundant.js";
|
|
5
|
+
export { targetLibConflictRule } from "./targetLibConflict.js";
|
|
6
|
+
export { moduleKindCheckRule } from "./moduleTypeCheck.js";
|
|
7
|
+
export { allowJsCheckRule } from "./allowJsCheck.js";
|
|
8
|
+
export { noEmitOutDirCheckRule } from "./noEmitOutDir.js";
|
|
9
|
+
export { noIncludeOrFilesCheckRule } from "./noIncludeOrFiles.js";
|
|
10
|
+
export { moduleResolutionMismatchRule } from "./moduleResolutionMismatch.js";
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export { legacyOptionRule } from "./legacyOption.js";
|
|
2
|
+
export { strictRedundantRule } from "./strictRedundant.js";
|
|
3
|
+
export { skipLibCheckRule } from "./skipLibCheckExplain.js";
|
|
4
|
+
export { defaultRedundantRule } from "./defaultRedundant.js";
|
|
5
|
+
export { targetLibConflictRule } from "./targetLibConflict.js";
|
|
6
|
+
export { moduleKindCheckRule } from "./moduleTypeCheck.js";
|
|
7
|
+
export { allowJsCheckRule } from "./allowJsCheck.js";
|
|
8
|
+
export { noEmitOutDirCheckRule } from "./noEmitOutDir.js";
|
|
9
|
+
export { noIncludeOrFilesCheckRule } from "./noIncludeOrFiles.js";
|
|
10
|
+
export { moduleResolutionMismatchRule } from "./moduleResolutionMismatch.js";
|
|
11
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/rules/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAC1D,OAAO,EAAE,yBAAyB,EAAE,MAAM,uBAAuB,CAAC;AAClE,OAAO,EAAE,4BAA4B,EAAE,MAAM,+BAA+B,CAAC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
const ruleId = "ts.legacy.option";
|
|
2
|
+
const legacyOptions = [
|
|
3
|
+
"charset",
|
|
4
|
+
"out",
|
|
5
|
+
"noUncheckedIndexedAccess",
|
|
6
|
+
"importsNotUsedAsValues",
|
|
7
|
+
"keyofStringsOnly",
|
|
8
|
+
"noStrictGenericChecks",
|
|
9
|
+
"noImplicitUseStrict",
|
|
10
|
+
"preserveSymlinks",
|
|
11
|
+
"suppressExcessPropertyErrors",
|
|
12
|
+
"suppressImplicitAnyIndexErrors",
|
|
13
|
+
"skipDefaultLibCheck",
|
|
14
|
+
];
|
|
15
|
+
export const legacyOptionRule = {
|
|
16
|
+
id: ruleId,
|
|
17
|
+
analyze(config) {
|
|
18
|
+
return legacyOptions
|
|
19
|
+
.filter(opt => opt in config)
|
|
20
|
+
.map(opt => ({
|
|
21
|
+
ruleId: ruleId,
|
|
22
|
+
severity: "warn",
|
|
23
|
+
message: `${opt} is a legacy TypeScript option and should be removed${getAdditionalInfo(opt)}`,
|
|
24
|
+
category: "legacy"
|
|
25
|
+
}));
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
function getAdditionalInfo(opt) {
|
|
29
|
+
switch (opt) {
|
|
30
|
+
case "out": return " (use 'outFile' instead)";
|
|
31
|
+
case "suppressExcessPropertyErrors":
|
|
32
|
+
case "suppressImplicitAnyIndexErrors":
|
|
33
|
+
return " (consider using @ts-ignore comment instead)";
|
|
34
|
+
case "importsNotUsedAsValues":
|
|
35
|
+
return " (Deprecated in favor of verbatimModuleSyntax)";
|
|
36
|
+
case "skipDefaultLibCheck":
|
|
37
|
+
return " (use 'skipLibCheck' instead)";
|
|
38
|
+
default:
|
|
39
|
+
return "";
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=legacyOption.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"legacyOption.js","sourceRoot":"","sources":["../../src/rules/legacyOption.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,GAAG,kBAAkB,CAAC;AAElC,MAAM,aAAa,GAA8B;IAC7C,SAAS;IACT,KAAK;IACL,0BAA0B;IAC1B,wBAAwB;IACxB,kBAAkB;IAClB,uBAAuB;IACvB,qBAAqB;IACrB,kBAAkB;IAClB,8BAA8B;IAC9B,gCAAgC;IAChC,qBAAqB;CACxB,CAAC;AAGF,MAAM,CAAC,MAAM,gBAAgB,GAAS;IAClC,EAAE,EAAE,MAAM;IAEV,OAAO,CAAC,MAAM;QACV,OAAO,aAAa;aACf,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,MAAM,CAAC;aAC5B,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YACT,MAAM,EAAE,MAAM;YACd,QAAQ,EAAE,MAAM;YAChB,OAAO,EAAE,GAAG,GAAG,uDAAuD,iBAAiB,CAAC,GAAG,CAAC,EAAE;YAC9F,QAAQ,EAAE,QAAQ;SACrB,CAAC,CAAC,CAAC;IACZ,CAAC;CACJ,CAAC;AAEF,SAAS,iBAAiB,CAAC,GAA0B;IACjD,QAAQ,GAAG,EAAE,CAAC;QACV,KAAK,KAAK,CAAC,CAAC,OAAO,0BAA0B,CAAC;QAC9C,KAAK,8BAA8B,CAAC;QACpC,KAAK,gCAAgC;YACjC,OAAO,8CAA8C,CAAC;QAC1D,KAAK,wBAAwB;YACzB,OAAO,gDAAgD,CAAC;QAC5D,KAAK,qBAAqB;YACtB,OAAO,+BAA+B,CAAC;QAC3C;YACI,OAAO,EAAE,CAAC;IAClB,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { ModuleKind, ModuleResolutionKind } from "typescript";
|
|
2
|
+
const ruleId = "ts.module-resolution.mismatch";
|
|
3
|
+
export const moduleResolutionMismatchRule = {
|
|
4
|
+
id: ruleId,
|
|
5
|
+
analyze(config) {
|
|
6
|
+
const options = config ?? {};
|
|
7
|
+
const module = options.module;
|
|
8
|
+
const moduleResolution = options.moduleResolution;
|
|
9
|
+
if (!module)
|
|
10
|
+
return [];
|
|
11
|
+
const findings = [];
|
|
12
|
+
function expect(expected) {
|
|
13
|
+
const moduleName = ModuleKind[module];
|
|
14
|
+
if (!moduleResolution) {
|
|
15
|
+
findings.push({
|
|
16
|
+
ruleId: ruleId,
|
|
17
|
+
category: "suggestion",
|
|
18
|
+
severity: "info",
|
|
19
|
+
message: `module is "${moduleName}" but moduleResolution is not set. Consider setting "moduleResolution": "${expected}" this ensures TypeScript matches runtime module resolution.`
|
|
20
|
+
});
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
if (module === 199 && moduleResolution !== 99 || module === 100 && moduleResolution !== 3) {
|
|
24
|
+
findings.push({
|
|
25
|
+
ruleId: ruleId,
|
|
26
|
+
category: "conflict",
|
|
27
|
+
severity: "warn",
|
|
28
|
+
message: `module is "${moduleName}" but moduleResolution is "${ModuleResolutionKind[moduleResolution]}". Expected moduleResolution: "${expected}". This mismatch may cause incorrect module resolution. Consider aligning them.`
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
if (module === ModuleKind.NodeNext) {
|
|
33
|
+
expect("NodeNext");
|
|
34
|
+
}
|
|
35
|
+
if (module === ModuleKind.Node16) {
|
|
36
|
+
expect("Node16");
|
|
37
|
+
}
|
|
38
|
+
if (module === ModuleKind.ESNext) {
|
|
39
|
+
// softer suggestion
|
|
40
|
+
if (!moduleResolution) {
|
|
41
|
+
findings.push({
|
|
42
|
+
ruleId: ruleId,
|
|
43
|
+
category: "suggestion",
|
|
44
|
+
severity: "info",
|
|
45
|
+
message: `module is "ESNext" but moduleResolution is not set. Consider "moduleResolution": "bundler" for modern setups, especially when using tools like Vite, Webpack, or Bun.`
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return findings;
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
//# sourceMappingURL=moduleResolutionMismatch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"moduleResolutionMismatch.js","sourceRoot":"","sources":["../../src/rules/moduleResolutionMismatch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,oBAAoB,EAAwB,MAAM,YAAY,CAAC;AAGpF,MAAM,MAAM,GAAG,+BAA+B,CAAC;AAE/C,MAAM,CAAC,MAAM,4BAA4B,GAAS;IAC9C,EAAE,EAAE,MAAM;IAEV,OAAO,CAAC,MAAuB;QAC3B,MAAM,OAAO,GAAG,MAAM,IAAI,EAAE,CAAC;QAE7B,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;QAC9B,MAAM,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,CAAC;QAElD,IAAI,CAAC,MAAM;YAAE,OAAO,EAAE,CAAC;QAEvB,MAAM,QAAQ,GAAc,EAAE,CAAC;QAE/B,SAAS,MAAM,CAAC,QAAgB;YAC5B,MAAM,UAAU,GAAG,UAAU,CAAC,MAAoB,CAAC,CAAC;YAEpD,IAAI,CAAC,gBAAgB,EAAE,CAAC;gBACpB,QAAQ,CAAC,IAAI,CAAC;oBACV,MAAM,EAAE,MAAM;oBACd,QAAQ,EAAE,YAAY;oBACtB,QAAQ,EAAE,MAAM;oBAChB,OAAO,EAAE,cAAc,UAAU,4EAA4E,QAAQ,8DAA8D;iBACtL,CAAC,CAAC;gBACH,OAAO;YACX,CAAC;YAED,IAAI,MAAM,KAAK,GAAG,IAAI,gBAAgB,KAAK,EAAE,IAAI,MAAM,KAAK,GAAG,IAAI,gBAAgB,KAAK,CAAC,EAAE,CAAC;gBACxF,QAAQ,CAAC,IAAI,CAAC;oBACV,MAAM,EAAE,MAAM;oBACd,QAAQ,EAAE,UAAU;oBACpB,QAAQ,EAAE,MAAM;oBAChB,OAAO,EAAE,cAAc,UAAU,8BAA8B,oBAAoB,CAAC,gBAAgB,CAAC,kCAAkC,QAAQ,iFAAiF;iBACnO,CAAC,CAAC;YACP,CAAC;QACL,CAAC;QAED,IAAI,MAAM,KAAK,UAAU,CAAC,QAAQ,EAAE,CAAC;YACjC,MAAM,CAAC,UAAU,CAAC,CAAC;QACvB,CAAC;QAED,IAAI,MAAM,KAAK,UAAU,CAAC,MAAM,EAAE,CAAC;YAC/B,MAAM,CAAC,QAAQ,CAAC,CAAC;QACrB,CAAC;QAED,IAAI,MAAM,KAAK,UAAU,CAAC,MAAM,EAAE,CAAC;YAC/B,oBAAoB;YACpB,IAAI,CAAC,gBAAgB,EAAE,CAAC;gBACpB,QAAQ,CAAC,IAAI,CAAC;oBACV,MAAM,EAAE,MAAM;oBACd,QAAQ,EAAE,YAAY;oBACtB,QAAQ,EAAE,MAAM;oBAChB,OAAO,EAAE,uKAAuK;iBACnL,CAAC,CAAC;YACP,CAAC;QACL,CAAC;QAED,OAAO,QAAQ,CAAC;IACpB,CAAC;CACJ,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
const ruleId = "ts.module.check";
|
|
2
|
+
export const moduleKindCheckRule = {
|
|
3
|
+
id: ruleId,
|
|
4
|
+
analyze(config) {
|
|
5
|
+
const module = config.module;
|
|
6
|
+
if (!module) {
|
|
7
|
+
return [];
|
|
8
|
+
}
|
|
9
|
+
const isCommonJS = module === 1;
|
|
10
|
+
const isESM = module > 4;
|
|
11
|
+
const findings = [];
|
|
12
|
+
if (isCommonJS) {
|
|
13
|
+
findings.push({
|
|
14
|
+
ruleId: ruleId,
|
|
15
|
+
severity: "info",
|
|
16
|
+
message: `The "module" option is explicitly set to "CommonJS", your "package.json" should not have "type": "module" to avoid potential conflicts.`,
|
|
17
|
+
category: "explanation"
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
return findings;
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
//# sourceMappingURL=moduleTypeCheck.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"moduleTypeCheck.js","sourceRoot":"","sources":["../../src/rules/moduleTypeCheck.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,GAAG,iBAAiB,CAAC;AAEjC,MAAM,CAAC,MAAM,mBAAmB,GAAS;IACrC,EAAE,EAAE,MAAM;IACV,OAAO,CAAC,MAAuB;QAE3B,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;QAE7B,IAAI,CAAC,MAAM,EAAE,CAAC;YACV,OAAO,EAAE,CAAC;QACd,CAAC;QAED,MAAM,UAAU,GAAG,MAAM,KAAK,CAAC,CAAC;QAChC,MAAM,KAAK,GAAG,MAAM,GAAG,CAAC,CAAC;QACzB,MAAM,QAAQ,GAAc,EAAE,CAAC;QAE/B,IAAI,UAAU,EAAE,CAAC;YACb,QAAQ,CAAC,IAAI,CAAC;gBACV,MAAM,EAAE,MAAM;gBACd,QAAQ,EAAE,MAAM;gBAChB,OAAO,EAAE,yIAAyI;gBAClJ,QAAQ,EAAE,aAAa;aAC1B,CAAC,CAAC;QACP,CAAC;QAED,OAAO,QAAQ,CAAC;IACpB,CAAC;CACJ,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
const ruleId = "ts.noEmitOutDir.check";
|
|
2
|
+
export const noEmitOutDirCheckRule = {
|
|
3
|
+
id: ruleId,
|
|
4
|
+
analyze(config) {
|
|
5
|
+
const noEmit = config.noEmit;
|
|
6
|
+
const outDir = config.outDir;
|
|
7
|
+
const findings = [];
|
|
8
|
+
if (noEmit && outDir) {
|
|
9
|
+
findings.push({
|
|
10
|
+
ruleId: ruleId,
|
|
11
|
+
severity: "info",
|
|
12
|
+
message: `The "noEmit" option is enabled, but "outDir" is also set. No files will be emitted, so outDir has no effect. Consider removing one of these options.`,
|
|
13
|
+
category: "explanation"
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
return findings;
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
//# sourceMappingURL=noEmitOutDir.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"noEmitOutDir.js","sourceRoot":"","sources":["../../src/rules/noEmitOutDir.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,GAAG,uBAAuB,CAAC;AAEvC,MAAM,CAAC,MAAM,qBAAqB,GAAS;IACvC,EAAE,EAAE,MAAM;IAEV,OAAO,CAAC,MAAuB;QAE3B,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;QAC7B,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;QAE7B,MAAM,QAAQ,GAAc,EAAE,CAAC;QAE/B,IAAI,MAAM,IAAI,MAAM,EAAE,CAAC;YACnB,QAAQ,CAAC,IAAI,CAAC;gBACV,MAAM,EAAE,MAAM;gBACd,QAAQ,EAAE,MAAM;gBAChB,OAAO,EAAE,sJAAsJ;gBAC/J,QAAQ,EAAE,aAAa;aAC1B,CAAC,CAAC;QACP,CAAC;QAED,OAAO,QAAQ,CAAC;IACpB,CAAC;CACJ,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
const ruleId = "ts.noIncludeOrFiles.check";
|
|
2
|
+
export const noIncludeOrFilesCheckRule = {
|
|
3
|
+
id: ruleId,
|
|
4
|
+
analyze(config) {
|
|
5
|
+
const include = config.include;
|
|
6
|
+
const files = config.files;
|
|
7
|
+
const exclude = config.exclude;
|
|
8
|
+
const findings = [];
|
|
9
|
+
if (!include && !files && !exclude) {
|
|
10
|
+
findings.push({
|
|
11
|
+
ruleId: ruleId,
|
|
12
|
+
severity: "info",
|
|
13
|
+
message: `Neither "include" nor "files" nor "exclude" options are set. TypeScript will include all files by default, consider narrowing scope for faster builds.`,
|
|
14
|
+
category: "explanation"
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
return findings;
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
//# sourceMappingURL=noIncludeOrFiles.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"noIncludeOrFiles.js","sourceRoot":"","sources":["../../src/rules/noIncludeOrFiles.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,GAAG,2BAA2B,CAAC;AAE3C,MAAM,CAAC,MAAM,yBAAyB,GAAS;IAC3C,EAAE,EAAE,MAAM;IAEV,OAAO,CAAC,MAAuB;QAC3B,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC;QAC/B,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC;QAC3B,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC;QAE/B,MAAM,QAAQ,GAAc,EAAE,CAAC;QAE/B,IAAI,CAAC,OAAO,IAAI,CAAC,KAAK,IAAI,CAAC,OAAO,EAAE,CAAC;YACjC,QAAQ,CAAC,IAAI,CAAC;gBACV,MAAM,EAAE,MAAM;gBACd,QAAQ,EAAE,MAAM;gBAChB,OAAO,EAAE,wJAAwJ;gBACjK,QAAQ,EAAE,aAAa;aAC1B,CAAC,CAAC;QACP,CAAC;QAED,OAAO,QAAQ,CAAC;IACpB,CAAC;CACJ,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
const ruleId = "ts.skipLibCheck.explain";
|
|
2
|
+
export const skipLibCheckRule = {
|
|
3
|
+
id: ruleId,
|
|
4
|
+
analyze(config) {
|
|
5
|
+
if (!("skipLibCheck" in config))
|
|
6
|
+
return [];
|
|
7
|
+
return [
|
|
8
|
+
{
|
|
9
|
+
ruleId: ruleId,
|
|
10
|
+
severity: "info",
|
|
11
|
+
message: "skipLibCheck skips type checking of declaration files (*.d.ts). This improves build speed but may hide type issues in dependencies. Generally safe for apps, more risky for libraries",
|
|
12
|
+
category: "explanation"
|
|
13
|
+
}
|
|
14
|
+
];
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
//# sourceMappingURL=skipLibCheckExplain.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skipLibCheckExplain.js","sourceRoot":"","sources":["../../src/rules/skipLibCheckExplain.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,GAAG,yBAAyB,CAAC;AAEzC,MAAM,CAAC,MAAM,gBAAgB,GAAS;IAClC,EAAE,EAAE,MAAM;IAEV,OAAO,CAAC,MAAM;QACV,IAAI,CAAC,CAAC,cAAc,IAAI,MAAM,CAAC;YAAE,OAAO,EAAE,CAAC;QAE3C,OAAO;YACH;gBACI,MAAM,EAAE,MAAM;gBACd,QAAQ,EAAE,MAAM;gBAChB,OAAO,EAAE,uLAAuL;gBAChM,QAAQ,EAAE,aAAa;aAC1B;SACJ,CAAC;IACN,CAAC;CACJ,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
const ruleId = "ts.strict.redundant";
|
|
2
|
+
export const strictRedundantRule = {
|
|
3
|
+
id: ruleId,
|
|
4
|
+
analyze(config) {
|
|
5
|
+
if (!config.strict)
|
|
6
|
+
return [];
|
|
7
|
+
const setByStrictOptions = [
|
|
8
|
+
"alwaysStrict",
|
|
9
|
+
"noImplicitAny",
|
|
10
|
+
"noImplicitThis",
|
|
11
|
+
"strictBindCallApply",
|
|
12
|
+
"strictBuiltinIteratorReturn",
|
|
13
|
+
"strictFunctionTypes",
|
|
14
|
+
"strictNullChecks",
|
|
15
|
+
"strictPropertyInitialization",
|
|
16
|
+
"useUnknownInCatchVariables"
|
|
17
|
+
];
|
|
18
|
+
return setByStrictOptions
|
|
19
|
+
.filter(opt => config[opt])
|
|
20
|
+
.map(opt => ({
|
|
21
|
+
ruleId: ruleId,
|
|
22
|
+
severity: "info",
|
|
23
|
+
message: `${opt} is redundant because strict=true enables it`,
|
|
24
|
+
category: "redundant"
|
|
25
|
+
}));
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
//# sourceMappingURL=strictRedundant.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"strictRedundant.js","sourceRoot":"","sources":["../../src/rules/strictRedundant.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,GAAG,qBAAqB,CAAC;AAErC,MAAM,CAAC,MAAM,mBAAmB,GAAS;IACrC,EAAE,EAAE,MAAM;IAEV,OAAO,CAAC,MAAM;QACV,IAAI,CAAC,MAAM,CAAC,MAAM;YAAE,OAAO,EAAE,CAAC;QAE9B,MAAM,kBAAkB,GAA8B;YAClD,cAAc;YACd,eAAe;YACf,gBAAgB;YAChB,qBAAqB;YACrB,6BAA6B;YAC7B,qBAAqB;YACrB,kBAAkB;YAClB,8BAA8B;YAC9B,4BAA4B;SAC/B,CAAC;QAEF,OAAO,kBAAkB;aACpB,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;aAC1B,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YACT,MAAM,EAAE,MAAM;YACd,QAAQ,EAAE,MAAM;YAChB,OAAO,EAAE,GAAG,GAAG,8CAA8C;YAC7D,QAAQ,EAAE,WAAW;SACxB,CAAC,CAAC,CAAC;IACZ,CAAC;CACJ,CAAC"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
const ruleId = "ts.target-lib.conflict";
|
|
2
|
+
const TARGET_ORDER = {
|
|
3
|
+
"es3": 0,
|
|
4
|
+
"es5": 1,
|
|
5
|
+
"es6": 2,
|
|
6
|
+
"es2015": 2,
|
|
7
|
+
"es2016": 3,
|
|
8
|
+
"es2017": 4,
|
|
9
|
+
"es2018": 5,
|
|
10
|
+
"es2019": 6,
|
|
11
|
+
"es2020": 7,
|
|
12
|
+
"es2021": 8,
|
|
13
|
+
"es2022": 9,
|
|
14
|
+
"es2023": 10,
|
|
15
|
+
"es2024": 11,
|
|
16
|
+
"esnext": 99,
|
|
17
|
+
"latest": 99,
|
|
18
|
+
};
|
|
19
|
+
function normalize(value) {
|
|
20
|
+
return value.toLowerCase();
|
|
21
|
+
}
|
|
22
|
+
function getTargetIndex(target) {
|
|
23
|
+
if (!target) {
|
|
24
|
+
return -1;
|
|
25
|
+
}
|
|
26
|
+
return TARGET_ORDER[normalize(target)] ?? -1;
|
|
27
|
+
}
|
|
28
|
+
function extractLibVersions(libs) {
|
|
29
|
+
if (!Array.isArray(libs) || libs.length === 0) {
|
|
30
|
+
return [];
|
|
31
|
+
}
|
|
32
|
+
return libs
|
|
33
|
+
.map(lib => lib.toLowerCase())
|
|
34
|
+
.filter(lib => lib.startsWith("es"));
|
|
35
|
+
}
|
|
36
|
+
function getHighestLib(libVersions) {
|
|
37
|
+
let maxIndex = -1;
|
|
38
|
+
let highest = null;
|
|
39
|
+
for (const lib of libVersions) {
|
|
40
|
+
const index = TARGET_ORDER[lib] ?? -1;
|
|
41
|
+
if (index > maxIndex) {
|
|
42
|
+
maxIndex = index;
|
|
43
|
+
highest = lib;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return highest;
|
|
47
|
+
}
|
|
48
|
+
export const targetLibConflictRule = {
|
|
49
|
+
id: ruleId,
|
|
50
|
+
analyze(config) {
|
|
51
|
+
const options = config ?? {};
|
|
52
|
+
const target = options.target;
|
|
53
|
+
const libs = options.lib;
|
|
54
|
+
if (!target || !libs) {
|
|
55
|
+
return [];
|
|
56
|
+
}
|
|
57
|
+
const targetOrder = Number(target);
|
|
58
|
+
const libVersions = extractLibVersions(libs);
|
|
59
|
+
const highestLib = getHighestLib(libVersions);
|
|
60
|
+
if (!highestLib) {
|
|
61
|
+
return [];
|
|
62
|
+
}
|
|
63
|
+
const libIndex = getTargetIndex(highestLib);
|
|
64
|
+
if (targetOrder === -1 || libIndex === -1)
|
|
65
|
+
return [];
|
|
66
|
+
if (libIndex > targetOrder) {
|
|
67
|
+
return [
|
|
68
|
+
{
|
|
69
|
+
ruleId: ruleId,
|
|
70
|
+
severity: "warn",
|
|
71
|
+
message: `target (${target}) is lower than lib (${highestLib})` + " this may cause runtime inconsistencies" + " consider aligning target and lib", // consider setting target to es2020 or lowering lib
|
|
72
|
+
category: "conflict"
|
|
73
|
+
}
|
|
74
|
+
];
|
|
75
|
+
}
|
|
76
|
+
return [];
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
//# sourceMappingURL=targetLibConflict.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"targetLibConflict.js","sourceRoot":"","sources":["../../src/rules/targetLibConflict.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { CompilerOptions } from "typescript";
|
|
2
|
+
export type Severity = "info" | "warn" | "error";
|
|
3
|
+
export type Category = "redundant" | "explanation" | "legacy" | "conflict" | "suggestion";
|
|
4
|
+
export interface Finding {
|
|
5
|
+
ruleId: string;
|
|
6
|
+
message: string;
|
|
7
|
+
severity: Severity;
|
|
8
|
+
category: Category;
|
|
9
|
+
}
|
|
10
|
+
export interface Rule {
|
|
11
|
+
id: string;
|
|
12
|
+
analyze(config: CompilerOptions): Finding[];
|
|
13
|
+
}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
package/package.json
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "ts-reconf",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Understand and simplify (re-conf) your tsconfig.json",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"bin": {
|
|
8
|
+
"ts-reconf": "./dist/cli.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist",
|
|
12
|
+
"README.md",
|
|
13
|
+
"LICENSE"
|
|
14
|
+
],
|
|
15
|
+
"scripts": {
|
|
16
|
+
"build": "tsc",
|
|
17
|
+
"dev": "tsx src/cli.ts",
|
|
18
|
+
"clean": "rm -rf dist",
|
|
19
|
+
"start": "node dist/cli.js",
|
|
20
|
+
"test": "echo \"Todo: write tests\" && exit 1",
|
|
21
|
+
"prepublishOnly": "npm run clean && npm run build"
|
|
22
|
+
},
|
|
23
|
+
"engines": {
|
|
24
|
+
"node": ">=18"
|
|
25
|
+
},
|
|
26
|
+
"keywords": [
|
|
27
|
+
"typescript",
|
|
28
|
+
"tsconfig",
|
|
29
|
+
"cli",
|
|
30
|
+
"developer-tools"
|
|
31
|
+
],
|
|
32
|
+
"author": "rockcoder",
|
|
33
|
+
"license": "MIT",
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"typescript": "^6.0.3"
|
|
36
|
+
},
|
|
37
|
+
"devDependencies": {
|
|
38
|
+
"@types/node": "^25.6.0",
|
|
39
|
+
"tsx": "^4.21.0"
|
|
40
|
+
}
|
|
41
|
+
}
|