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.
Files changed (51) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +84 -0
  3. package/dist/analyzer.d.ts +3 -0
  4. package/dist/analyzer.js +17 -0
  5. package/dist/analyzer.js.map +1 -0
  6. package/dist/cli.d.ts +2 -0
  7. package/dist/cli.js +27 -0
  8. package/dist/cli.js.map +1 -0
  9. package/dist/loadTsConfig.d.ts +2 -0
  10. package/dist/loadTsConfig.js +12 -0
  11. package/dist/loadTsConfig.js.map +1 -0
  12. package/dist/reporter.d.ts +3 -0
  13. package/dist/reporter.js +46 -0
  14. package/dist/reporter.js.map +1 -0
  15. package/dist/rules/allowJsCheck.d.ts +2 -0
  16. package/dist/rules/allowJsCheck.js +19 -0
  17. package/dist/rules/allowJsCheck.js.map +1 -0
  18. package/dist/rules/defaultRedundant.d.ts +2 -0
  19. package/dist/rules/defaultRedundant.js +77 -0
  20. package/dist/rules/defaultRedundant.js.map +1 -0
  21. package/dist/rules/index.d.ts +10 -0
  22. package/dist/rules/index.js +11 -0
  23. package/dist/rules/index.js.map +1 -0
  24. package/dist/rules/legacyOption.d.ts +2 -0
  25. package/dist/rules/legacyOption.js +42 -0
  26. package/dist/rules/legacyOption.js.map +1 -0
  27. package/dist/rules/moduleResolutionMismatch.d.ts +2 -0
  28. package/dist/rules/moduleResolutionMismatch.js +52 -0
  29. package/dist/rules/moduleResolutionMismatch.js.map +1 -0
  30. package/dist/rules/moduleTypeCheck.d.ts +2 -0
  31. package/dist/rules/moduleTypeCheck.js +23 -0
  32. package/dist/rules/moduleTypeCheck.js.map +1 -0
  33. package/dist/rules/noEmitOutDir.d.ts +2 -0
  34. package/dist/rules/noEmitOutDir.js +19 -0
  35. package/dist/rules/noEmitOutDir.js.map +1 -0
  36. package/dist/rules/noIncludeOrFiles.d.ts +2 -0
  37. package/dist/rules/noIncludeOrFiles.js +20 -0
  38. package/dist/rules/noIncludeOrFiles.js.map +1 -0
  39. package/dist/rules/skipLibCheckExplain.d.ts +2 -0
  40. package/dist/rules/skipLibCheckExplain.js +17 -0
  41. package/dist/rules/skipLibCheckExplain.js.map +1 -0
  42. package/dist/rules/strictRedundant.d.ts +2 -0
  43. package/dist/rules/strictRedundant.js +28 -0
  44. package/dist/rules/strictRedundant.js.map +1 -0
  45. package/dist/rules/targetLibConflict.d.ts +2 -0
  46. package/dist/rules/targetLibConflict.js +79 -0
  47. package/dist/rules/targetLibConflict.js.map +1 -0
  48. package/dist/types.d.ts +13 -0
  49. package/dist/types.js +2 -0
  50. package/dist/types.js.map +1 -0
  51. 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 .
@@ -0,0 +1,3 @@
1
+ import type { CompilerOptions } from "typescript";
2
+ import type { Finding } from "./types.js";
3
+ export declare function analyze(config: CompilerOptions): Finding[];
@@ -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
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
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
@@ -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,2 @@
1
+ import { CompilerOptions } from "typescript";
2
+ export declare function loadTsConfig(tsconfigPath: string): CompilerOptions;
@@ -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"}
@@ -0,0 +1,3 @@
1
+ import { Finding } from "./types.js";
2
+ export declare function toMarkdown(findings: Finding[], file?: string): string;
3
+ export declare function toPrettyOutput(findings: Finding[], file?: string): string;
@@ -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,2 @@
1
+ import type { Rule } from "../types.js";
2
+ export declare const allowJsCheckRule: Rule;
@@ -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,2 @@
1
+ import type { Rule } from "../types.js";
2
+ export declare const defaultRedundantRule: Rule;
@@ -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,2 @@
1
+ import type { Rule } from "../types.js";
2
+ export declare const legacyOptionRule: Rule;
@@ -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,2 @@
1
+ import type { Rule } from "../types.js";
2
+ export declare const moduleResolutionMismatchRule: Rule;
@@ -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,2 @@
1
+ import type { Rule } from "../types.js";
2
+ export declare const moduleKindCheckRule: Rule;
@@ -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,2 @@
1
+ import type { Rule } from "../types.js";
2
+ export declare const noEmitOutDirCheckRule: Rule;
@@ -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,2 @@
1
+ import type { Rule } from "../types.js";
2
+ export declare const noIncludeOrFilesCheckRule: Rule;
@@ -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,2 @@
1
+ import { Rule } from "../types.js";
2
+ export declare const skipLibCheckRule: Rule;
@@ -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,2 @@
1
+ import { Rule } from "../types.js";
2
+ export declare const strictRedundantRule: Rule;
@@ -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,2 @@
1
+ import type { Rule } from "../types.js";
2
+ export declare const targetLibConflictRule: Rule;
@@ -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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"}
@@ -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,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -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
+ }