ts-reconf 0.3.0 → 0.4.1

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 (36) hide show
  1. package/dist/__tests__/analyzer.test.d.ts +1 -0
  2. package/dist/__tests__/analyzer.test.js +76 -0
  3. package/dist/__tests__/analyzer.test.js.map +1 -0
  4. package/dist/__tests__/integration.test.d.ts +1 -0
  5. package/dist/__tests__/integration.test.js +111 -0
  6. package/dist/__tests__/integration.test.js.map +1 -0
  7. package/dist/__tests__/loadTsConfig.test.d.ts +1 -0
  8. package/dist/__tests__/loadTsConfig.test.js +79 -0
  9. package/dist/__tests__/loadTsConfig.test.js.map +1 -0
  10. package/dist/__tests__/reporter.test.d.ts +1 -0
  11. package/dist/__tests__/reporter.test.js +95 -0
  12. package/dist/__tests__/reporter.test.js.map +1 -0
  13. package/dist/__tests__/types.test.d.ts +1 -0
  14. package/dist/__tests__/types.test.js +74 -0
  15. package/dist/__tests__/types.test.js.map +1 -0
  16. package/dist/analyzer.js +6 -2
  17. package/dist/analyzer.js.map +1 -1
  18. package/dist/reporter.js +6 -1
  19. package/dist/reporter.js.map +1 -1
  20. package/dist/rules/declarationMapCheck.d.ts +2 -0
  21. package/dist/rules/declarationMapCheck.js +18 -0
  22. package/dist/rules/declarationMapCheck.js.map +1 -0
  23. package/dist/rules/emitDeclarationOnly.d.ts +2 -0
  24. package/dist/rules/emitDeclarationOnly.js +19 -0
  25. package/dist/rules/emitDeclarationOnly.js.map +1 -0
  26. package/dist/rules/index.d.ts +4 -0
  27. package/dist/rules/index.js +4 -0
  28. package/dist/rules/index.js.map +1 -1
  29. package/dist/rules/legacyJsxTransformCheck.d.ts +2 -0
  30. package/dist/rules/legacyJsxTransformCheck.js +19 -0
  31. package/dist/rules/legacyJsxTransformCheck.js.map +1 -0
  32. package/dist/rules/moduleResolutionOutdated.d.ts +2 -0
  33. package/dist/rules/moduleResolutionOutdated.js +29 -0
  34. package/dist/rules/moduleResolutionOutdated.js.map +1 -0
  35. package/dist/types.d.ts +1 -0
  36. package/package.json +49 -45
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,76 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { analyze } from '../analyzer.js';
3
+ describe('Analyzer', () => {
4
+ it('should return empty findings for clean config', () => {
5
+ const config = {
6
+ compilerOptions: {
7
+ target: 99,
8
+ module: 99,
9
+ },
10
+ rawConfig: {},
11
+ };
12
+ const findings = analyze(config);
13
+ expect(Array.isArray(findings)).toBe(true);
14
+ });
15
+ it('should detect redundant options when strict is enabled', () => {
16
+ const config = {
17
+ compilerOptions: {
18
+ strict: true,
19
+ noImplicitAny: true,
20
+ strictNullChecks: true,
21
+ },
22
+ rawConfig: {},
23
+ };
24
+ const findings = analyze(config);
25
+ const redundantFindings = findings.filter(f => f.category === 'redundant');
26
+ expect(redundantFindings.length).toBeGreaterThan(0);
27
+ expect(redundantFindings.some(f => f.message.includes('noImplicitAny'))).toBe(true);
28
+ });
29
+ it('should provide explanations for skipLibCheck', () => {
30
+ const config = {
31
+ compilerOptions: {
32
+ skipLibCheck: true,
33
+ },
34
+ rawConfig: {},
35
+ };
36
+ const findings = analyze(config);
37
+ const explanations = findings.filter(f => f.category === 'explanation' && f.message.includes('skipLibCheck'));
38
+ expect(explanations.length).toBeGreaterThan(0);
39
+ });
40
+ it('should handle empty compiler options', () => {
41
+ const config = {
42
+ compilerOptions: {},
43
+ rawConfig: {},
44
+ };
45
+ const findings = analyze(config);
46
+ expect(Array.isArray(findings)).toBe(true);
47
+ });
48
+ it('should categorize findings with correct severity levels', () => {
49
+ const config = {
50
+ compilerOptions: {
51
+ strict: true,
52
+ noImplicitAny: true,
53
+ },
54
+ rawConfig: {},
55
+ };
56
+ const findings = analyze(config);
57
+ const severities = findings.map(f => f.severity);
58
+ severities.forEach(severity => {
59
+ expect(['info', 'warn', 'error']).toContain(severity);
60
+ });
61
+ });
62
+ it('should detect module resolution mismatches', () => {
63
+ const config = {
64
+ compilerOptions: {
65
+ module: 7, // ESNext
66
+ moduleResolution: 1, // Classic
67
+ },
68
+ rawConfig: {},
69
+ };
70
+ const findings = analyze(config);
71
+ const mismatches = findings.filter(f => f.message.includes('moduleResolution'));
72
+ // May or may not have mismatches depending on rules, but should not error
73
+ expect(Array.isArray(findings)).toBe(true);
74
+ });
75
+ });
76
+ //# sourceMappingURL=analyzer.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analyzer.test.js","sourceRoot":"","sources":["../../src/__tests__/analyzer.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,111 @@
1
+ import { describe, it, expect, beforeEach, afterEach } from 'vitest';
2
+ import { loadTsConfig } from '../loadTsConfig.js';
3
+ import { analyze } from '../analyzer.js';
4
+ import { toMarkdown, toPrettyOutput } from '../reporter.js';
5
+ import { writeFileSync, mkdirSync, rmSync } from 'fs';
6
+ import { join } from 'path';
7
+ describe('Integration Tests', () => {
8
+ const testDir = join(process.cwd(), '.test-integration');
9
+ beforeEach(() => {
10
+ mkdirSync(testDir, { recursive: true });
11
+ });
12
+ afterEach(() => {
13
+ rmSync(testDir, { recursive: true, force: true });
14
+ });
15
+ it('should complete full analysis pipeline', () => {
16
+ const configPath = join(testDir, 'tsconfig.json');
17
+ writeFileSync(configPath, JSON.stringify({
18
+ compilerOptions: {
19
+ target: 'ES2020',
20
+ module: 'commonjs',
21
+ strict: true,
22
+ noImplicitAny: true,
23
+ skipLibCheck: true,
24
+ },
25
+ include: ['src'],
26
+ }));
27
+ // Load config
28
+ const config = loadTsConfig(configPath);
29
+ expect(config).toBeDefined();
30
+ // Analyze
31
+ const findings = analyze(config);
32
+ expect(Array.isArray(findings)).toBe(true);
33
+ // Report - markdown
34
+ const markdown = toMarkdown(findings, 'tsconfig.json');
35
+ expect(markdown).toContain('tsconfig findings');
36
+ // Report - pretty
37
+ const pretty = toPrettyOutput(findings, 'tsconfig.json');
38
+ expect(pretty).toContain('Analyzing');
39
+ });
40
+ it('should analyze realistic tsconfig with multiple issues', () => {
41
+ const configPath = join(testDir, 'tsconfig.json');
42
+ writeFileSync(configPath, JSON.stringify({
43
+ compilerOptions: {
44
+ target: 'ES2020',
45
+ module: 'ES2020',
46
+ moduleResolution: 'node',
47
+ strict: true,
48
+ noImplicitAny: true,
49
+ noImplicitThis: true,
50
+ strictNullChecks: true,
51
+ skipLibCheck: true,
52
+ esModuleInterop: true,
53
+ declaration: true,
54
+ declarationMap: true,
55
+ sourceMap: true,
56
+ outDir: 'dist',
57
+ },
58
+ include: ['src'],
59
+ exclude: ['node_modules', 'dist'],
60
+ }));
61
+ const config = loadTsConfig(configPath);
62
+ const findings = analyze(config);
63
+ const report = toPrettyOutput(findings, 'tsconfig.json');
64
+ // Should find redundant strict options
65
+ const redundantFindings = findings.filter(f => f.category === 'redundant');
66
+ expect(redundantFindings.length).toBeGreaterThan(0);
67
+ // Report should be generated successfully
68
+ expect(report).toContain('Done');
69
+ });
70
+ it('should handle clean config gracefully', () => {
71
+ const configPath = join(testDir, 'tsconfig.json');
72
+ writeFileSync(configPath, JSON.stringify({
73
+ compilerOptions: {
74
+ target: 'ES2020',
75
+ module: 'commonjs',
76
+ },
77
+ include: ['src'],
78
+ }));
79
+ const config = loadTsConfig(configPath);
80
+ const findings = analyze(config);
81
+ // Even if there are no issues, the pipeline should work
82
+ expect(Array.isArray(findings)).toBe(true);
83
+ const report = toPrettyOutput(findings);
84
+ expect(report).toBeDefined();
85
+ });
86
+ it('should preserve all information through pipeline', () => {
87
+ const configPath = join(testDir, 'tsconfig.json');
88
+ const testConfig = {
89
+ compilerOptions: {
90
+ strict: true,
91
+ noImplicitAny: true,
92
+ target: 'ES2020',
93
+ },
94
+ include: ['src', 'tests'],
95
+ exclude: ['node_modules'],
96
+ files: ['index.ts'],
97
+ };
98
+ writeFileSync(configPath, JSON.stringify(testConfig));
99
+ const config = loadTsConfig(configPath);
100
+ // Raw config should be preserved
101
+ expect(config.rawConfig.include).toEqual(['src', 'tests']);
102
+ expect(config.rawConfig.exclude).toEqual(['node_modules']);
103
+ expect(config.rawConfig.files).toEqual(['index.ts']);
104
+ // Compiler options should be set
105
+ expect(config.compilerOptions.strict).toBe(true);
106
+ // Analysis should work on preserved data
107
+ const findings = analyze(config);
108
+ expect(findings).toBeDefined();
109
+ });
110
+ });
111
+ //# sourceMappingURL=integration.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"integration.test.js","sourceRoot":"","sources":["../../src/__tests__/integration.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,79 @@
1
+ import { describe, it, expect, beforeEach, afterEach } from 'vitest';
2
+ import { loadTsConfig } from '../loadTsConfig.js';
3
+ import { writeFileSync, mkdirSync, rmSync } from 'fs';
4
+ import { join } from 'path';
5
+ describe('loadTsConfig', () => {
6
+ const testDir = join(process.cwd(), '.test-tsconfig');
7
+ beforeEach(() => {
8
+ mkdirSync(testDir, { recursive: true });
9
+ });
10
+ afterEach(() => {
11
+ rmSync(testDir, { recursive: true, force: true });
12
+ });
13
+ it('should load valid tsconfig.json', () => {
14
+ const configPath = join(testDir, 'tsconfig.json');
15
+ writeFileSync(configPath, JSON.stringify({
16
+ compilerOptions: {
17
+ target: 'ES2020',
18
+ module: 'commonjs',
19
+ },
20
+ include: ['src'],
21
+ }));
22
+ const config = loadTsConfig(configPath);
23
+ expect(config).toHaveProperty('compilerOptions');
24
+ expect(config).toHaveProperty('rawConfig');
25
+ expect(config.compilerOptions).toBeDefined();
26
+ });
27
+ it('should parse compiler options correctly', () => {
28
+ const configPath = join(testDir, 'tsconfig.json');
29
+ writeFileSync(configPath, JSON.stringify({
30
+ compilerOptions: {
31
+ target: 'ES2022',
32
+ strict: true,
33
+ declaration: true,
34
+ },
35
+ }));
36
+ const config = loadTsConfig(configPath);
37
+ expect(config.compilerOptions.strict).toBe(true);
38
+ expect(config.compilerOptions.declaration).toBe(true);
39
+ });
40
+ it('should preserve raw config include/exclude/files', () => {
41
+ const configPath = join(testDir, 'tsconfig.json');
42
+ writeFileSync(configPath, JSON.stringify({
43
+ compilerOptions: { target: 'ES2020' },
44
+ include: ['src'],
45
+ exclude: ['node_modules', 'dist'],
46
+ files: ['index.ts'],
47
+ }));
48
+ const config = loadTsConfig(configPath);
49
+ expect(config.rawConfig.include).toEqual(['src']);
50
+ expect(config.rawConfig.exclude).toEqual(['node_modules', 'dist']);
51
+ expect(config.rawConfig.files).toEqual(['index.ts']);
52
+ });
53
+ it('should throw error for invalid JSON', () => {
54
+ const configPath = join(testDir, 'tsconfig.json');
55
+ writeFileSync(configPath, '{invalid json}');
56
+ expect(() => loadTsConfig(configPath)).toThrow();
57
+ });
58
+ it('should throw error for missing file', () => {
59
+ const configPath = join(testDir, 'nonexistent.json');
60
+ expect(() => loadTsConfig(configPath)).toThrow();
61
+ });
62
+ it('should handle extends property in raw config', () => {
63
+ const configPath = join(testDir, 'tsconfig.json');
64
+ writeFileSync(configPath, JSON.stringify({
65
+ extends: './tsconfig.base.json',
66
+ compilerOptions: { strict: true },
67
+ }));
68
+ const config = loadTsConfig(configPath);
69
+ expect(config.rawConfig.extends).toBe('./tsconfig.base.json');
70
+ });
71
+ it('should handle empty config file', () => {
72
+ const configPath = join(testDir, 'tsconfig.json');
73
+ writeFileSync(configPath, JSON.stringify({}));
74
+ const config = loadTsConfig(configPath);
75
+ expect(config.compilerOptions).toBeDefined();
76
+ expect(config.rawConfig).toBeDefined();
77
+ });
78
+ });
79
+ //# sourceMappingURL=loadTsConfig.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loadTsConfig.test.js","sourceRoot":"","sources":["../../src/__tests__/loadTsConfig.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,95 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { toMarkdown, toPrettyOutput } from '../reporter.js';
3
+ describe('Reporter', () => {
4
+ const mockFindings = [
5
+ {
6
+ ruleId: 'test.redundant',
7
+ message: 'noImplicitAny is redundant',
8
+ severity: 'info',
9
+ category: 'redundant',
10
+ },
11
+ {
12
+ ruleId: 'test.explanation',
13
+ message: 'skipLibCheck improves build speed',
14
+ severity: 'info',
15
+ category: 'explanation',
16
+ },
17
+ {
18
+ ruleId: 'test.conflict',
19
+ message: 'Module and moduleResolution conflict',
20
+ severity: 'warn',
21
+ category: 'conflict',
22
+ },
23
+ ];
24
+ describe('toMarkdown', () => {
25
+ it('should return success message for empty findings', () => {
26
+ const output = toMarkdown([], 'tsconfig.json');
27
+ expect(output).toContain('Looks good!');
28
+ expect(output).toContain('No issues found');
29
+ });
30
+ it('should list findings in markdown format', () => {
31
+ const output = toMarkdown(mockFindings, 'tsconfig.json');
32
+ expect(output).toContain('tsconfig findings');
33
+ expect(output).toContain('noImplicitAny is redundant');
34
+ expect(output).toContain('skipLibCheck improves build speed');
35
+ expect(output).toContain('Module and moduleResolution conflict');
36
+ });
37
+ it('should format findings as markdown list items', () => {
38
+ const output = toMarkdown(mockFindings);
39
+ expect(output).toMatch(/- .+/); // Should have list items
40
+ });
41
+ it('should handle undefined file parameter', () => {
42
+ const output = toMarkdown(mockFindings);
43
+ expect(output).toContain('tsconfig findings');
44
+ });
45
+ });
46
+ describe('toPrettyOutput', () => {
47
+ it('should return success message for empty findings', () => {
48
+ const output = toPrettyOutput([], 'tsconfig.json');
49
+ expect(output).toContain('Looks good!');
50
+ expect(output).toContain('No issues found');
51
+ //expect(output).toContain('Done');
52
+ });
53
+ it('should group findings by category', () => {
54
+ const output = toPrettyOutput(mockFindings);
55
+ expect(output).toContain('Conflict');
56
+ expect(output).toContain('Redundant');
57
+ expect(output).toContain('Explanation');
58
+ });
59
+ it('should display category counts', () => {
60
+ const output = toPrettyOutput(mockFindings);
61
+ expect(output).toMatch(/Redundant \(\d+\)/);
62
+ expect(output).toMatch(/Explanation \(\d+\)/);
63
+ expect(output).toMatch(/Conflict \(\d+\)/);
64
+ });
65
+ it('should format findings with bullet points', () => {
66
+ const output = toPrettyOutput(mockFindings);
67
+ expect(output).toContain('•');
68
+ });
69
+ it('should include file name in output', () => {
70
+ const output = toPrettyOutput(mockFindings, 'my-tsconfig.json');
71
+ expect(output).toContain('my-tsconfig.json');
72
+ });
73
+ it('should have visual separators', () => {
74
+ const output = toPrettyOutput(mockFindings);
75
+ expect(output).toContain('────────────');
76
+ });
77
+ });
78
+ describe('Output consistency', () => {
79
+ it('markdown output should be compact', () => {
80
+ const markdown = toMarkdown(mockFindings);
81
+ const pretty = toPrettyOutput(mockFindings);
82
+ // Markdown should generally be shorter (no formatting)
83
+ expect(markdown.length).toBeLessThanOrEqual(pretty.length);
84
+ });
85
+ it('both formats should include all findings', () => {
86
+ const markdown = toMarkdown(mockFindings);
87
+ const pretty = toPrettyOutput(mockFindings);
88
+ mockFindings.forEach(finding => {
89
+ expect(markdown).toContain(finding.message);
90
+ expect(pretty).toContain(finding.message);
91
+ });
92
+ });
93
+ });
94
+ });
95
+ //# sourceMappingURL=reporter.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reporter.test.js","sourceRoot":"","sources":["../../src/__tests__/reporter.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,74 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ describe('Type Definitions', () => {
3
+ it('should create valid Finding objects', () => {
4
+ const finding = {
5
+ ruleId: 'test.rule',
6
+ message: 'Test message',
7
+ severity: 'info',
8
+ category: 'redundant',
9
+ };
10
+ expect(finding.ruleId).toBe('test.rule');
11
+ expect(finding.message).toBe('Test message');
12
+ expect(['info', 'warn', 'error']).toContain(finding.severity);
13
+ });
14
+ it('should accept all valid severity levels', () => {
15
+ const severities = ['info', 'warn', 'error'];
16
+ severities.forEach(severity => {
17
+ const finding = {
18
+ ruleId: 'test',
19
+ message: 'test',
20
+ severity,
21
+ category: 'redundant',
22
+ };
23
+ expect(finding.severity).toBe(severity);
24
+ });
25
+ });
26
+ it('should accept all valid categories', () => {
27
+ const categories = [
28
+ 'conflict',
29
+ 'legacy',
30
+ 'redundant',
31
+ 'suggestion',
32
+ 'explanation',
33
+ ];
34
+ categories.forEach(category => {
35
+ const finding = {
36
+ ruleId: 'test',
37
+ message: 'test',
38
+ severity: 'info',
39
+ category,
40
+ };
41
+ expect(finding.category).toBe(category);
42
+ });
43
+ });
44
+ it('should create valid AnalysisContext objects', () => {
45
+ const context = {
46
+ compilerOptions: {
47
+ strict: true,
48
+ target: 99,
49
+ },
50
+ rawConfig: {
51
+ include: ['src'],
52
+ exclude: ['node_modules'],
53
+ },
54
+ };
55
+ expect(context.compilerOptions).toBeDefined();
56
+ expect(context.rawConfig).toBeDefined();
57
+ });
58
+ it('should enforce Rule interface contract', () => {
59
+ const rule = {
60
+ id: 'test.rule',
61
+ analyze: (config) => {
62
+ return [];
63
+ },
64
+ };
65
+ expect(rule.id).toBe('test.rule');
66
+ expect(typeof rule.analyze).toBe('function');
67
+ const findings = rule.analyze({
68
+ compilerOptions: {},
69
+ rawConfig: {},
70
+ });
71
+ expect(Array.isArray(findings)).toBe(true);
72
+ });
73
+ });
74
+ //# sourceMappingURL=types.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.test.js","sourceRoot":"","sources":["../../src/__tests__/types.test.ts"],"names":[],"mappings":"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"}
package/dist/analyzer.js CHANGED
@@ -1,4 +1,4 @@
1
- import { legacyOptionRule, strictRedundantRule, skipLibCheckRule, defaultRedundantRule, targetLibConflictRule, moduleKindCheckRule, allowJsCheckRule, noEmitOutDirCheckRule, noIncludeOrFilesCheckRule, moduleResolutionMismatchRule, declarationNoEmitCheckRule, verbatimModuleIsolatedModulesRule, verbatimModuleSyntaxCheckRule, allowSyntheticDefaultImportsRule, noUncheckedIndexedAccessRule, forceConsistentCasingInFileNamesRule, } from "./rules/index.js";
1
+ import { legacyOptionRule, strictRedundantRule, skipLibCheckRule, defaultRedundantRule, targetLibConflictRule, moduleKindCheckRule, allowJsCheckRule, noEmitOutDirCheckRule, noIncludeOrFilesCheckRule, moduleResolutionMismatchRule, declarationNoEmitCheckRule, verbatimModuleIsolatedModulesRule, verbatimModuleSyntaxCheckRule, allowSyntheticDefaultImportsRule, noUncheckedIndexedAccessRule, forceConsistentCasingInFileNamesRule, moduleResolutionOutdatedRule, emitDeclarationOnlyRule, legacyJsxTransformCheckRule, declarationMapCheckRule, } from "./rules/index.js";
2
2
  const rules = [
3
3
  legacyOptionRule,
4
4
  strictRedundantRule,
@@ -15,7 +15,11 @@ const rules = [
15
15
  verbatimModuleSyntaxCheckRule,
16
16
  allowSyntheticDefaultImportsRule,
17
17
  noUncheckedIndexedAccessRule,
18
- forceConsistentCasingInFileNamesRule
18
+ forceConsistentCasingInFileNamesRule,
19
+ moduleResolutionOutdatedRule,
20
+ emitDeclarationOnlyRule,
21
+ legacyJsxTransformCheckRule,
22
+ declarationMapCheckRule,
19
23
  ];
20
24
  export function analyze(config) {
21
25
  return rules.flatMap(rule => rule.analyze(config));
@@ -1 +1 @@
1
- {"version":3,"file":"analyzer.js","sourceRoot":"","sources":["../src/analyzer.ts"],"names":[],"mappings":"AAEA,OAAO,EACH,gBAAgB,EAChB,mBAAmB,EACnB,gBAAgB,EAChB,oBAAoB,EACpB,qBAAqB,EACrB,mBAAmB,EACnB,gBAAgB,EAChB,qBAAqB,EACrB,yBAAyB,EACzB,4BAA4B,EAC5B,0BAA0B,EAC1B,iCAAiC,EACjC,6BAA6B,EAC7B,gCAAgC,EAChC,4BAA4B,EAC5B,oCAAoC,GACvC,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;IAC5B,0BAA0B;IAC1B,iCAAiC;IACjC,6BAA6B;IAC7B,gCAAgC;IAChC,4BAA4B;IAC5B,oCAAoC;CACvC,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"}
1
+ {"version":3,"file":"analyzer.js","sourceRoot":"","sources":["../src/analyzer.ts"],"names":[],"mappings":"AAEA,OAAO,EACH,gBAAgB,EAChB,mBAAmB,EACnB,gBAAgB,EAChB,oBAAoB,EACpB,qBAAqB,EACrB,mBAAmB,EACnB,gBAAgB,EAChB,qBAAqB,EACrB,yBAAyB,EACzB,4BAA4B,EAC5B,0BAA0B,EAC1B,iCAAiC,EACjC,6BAA6B,EAC7B,gCAAgC,EAChC,4BAA4B,EAC5B,oCAAoC,EACpC,4BAA4B,EAC5B,uBAAuB,EACvB,2BAA2B,EAC3B,uBAAuB,GAC1B,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;IAC5B,0BAA0B;IAC1B,iCAAiC;IACjC,6BAA6B;IAC7B,gCAAgC;IAChC,4BAA4B;IAC5B,oCAAoC;IACpC,4BAA4B;IAC5B,uBAAuB;IACvB,2BAA2B;IAC3B,uBAAuB;CAC1B,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/reporter.js CHANGED
@@ -1,4 +1,9 @@
1
1
  const NO_ISSUES_FOUND_MSG = "## Looks good! 🎉 No issues found ✔\n";
2
+ const SeverityIcons = new Map([
3
+ ["info", "ℹ"],
4
+ ["warn", "⚠"],
5
+ ["error", "✖"]
6
+ ]);
2
7
  export function toMarkdown(findings, file) {
3
8
  const lines = [`## tsconfig findings for ${file ?? ""}:\n`];
4
9
  if (findings.length === 0) {
@@ -35,7 +40,7 @@ export function toPrettyOutput(findings, file) {
35
40
  category.slice(1);
36
41
  lines.push(`${title} (${items.length})`);
37
42
  for (const item of items) {
38
- lines.push(` • ${item.message}`);
43
+ lines.push(` • ${SeverityIcons.get(item.severity)} ${item.message}`);
39
44
  }
40
45
  lines.push("");
41
46
  }
@@ -1 +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,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC;QAClF,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,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;IAC5C,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"}
1
+ {"version":3,"file":"reporter.js","sourceRoot":"","sources":["../src/reporter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import type { Rule } from "../types.js";
2
+ export declare const declarationMapCheckRule: Rule;
@@ -0,0 +1,18 @@
1
+ const ruleId = "ts.declarationMap.noDeclaration";
2
+ export const declarationMapCheckRule = {
3
+ id: ruleId,
4
+ analyze(config) {
5
+ const compilerOptions = config.compilerOptions ?? {};
6
+ const findings = [];
7
+ if (compilerOptions.declarationMap && !compilerOptions.declaration) {
8
+ findings.push({
9
+ ruleId: ruleId,
10
+ category: "redundant",
11
+ severity: "warn",
12
+ message: `"declarationMap" emits ".d.ts.map" files but has no effect if "declaration" is not set to "true"`
13
+ });
14
+ }
15
+ return findings;
16
+ }
17
+ };
18
+ //# sourceMappingURL=declarationMapCheck.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"declarationMapCheck.js","sourceRoot":"","sources":["../../src/rules/declarationMapCheck.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,GAAG,iCAAiC,CAAC;AAEjD,MAAM,CAAC,MAAM,uBAAuB,GAAS;IACzC,EAAE,EAAE,MAAM;IACV,OAAO,CAAC,MAAuB;QAC3B,MAAM,eAAe,GAAG,MAAM,CAAC,eAAe,IAAI,EAAE,CAAC;QACrD,MAAM,QAAQ,GAAc,EAAE,CAAC;QAE/B,IAAI,eAAe,CAAC,cAAc,IAAI,CAAC,eAAe,CAAC,WAAW,EAAE,CAAC;YACjE,QAAQ,CAAC,IAAI,CAAC;gBACV,MAAM,EAAE,MAAM;gBACd,QAAQ,EAAE,WAAW;gBACrB,QAAQ,EAAE,MAAM;gBAChB,OAAO,EAAE,kGAAkG;aAC9G,CAAC,CAAC;QACP,CAAC;QAED,OAAO,QAAQ,CAAC;IACpB,CAAC;CAEJ,CAAA"}
@@ -0,0 +1,2 @@
1
+ import type { Rule } from "../types.js";
2
+ export declare const emitDeclarationOnlyRule: Rule;
@@ -0,0 +1,19 @@
1
+ const ruleId = "ts.emitDeclarationOnly.noDeclaration";
2
+ export const emitDeclarationOnlyRule = {
3
+ id: ruleId,
4
+ analyze(config) {
5
+ const options = config.compilerOptions ?? {};
6
+ const emitDeclarationOnly = options.emitDeclarationOnly;
7
+ const findings = [];
8
+ if (emitDeclarationOnly && !options.declaration && !options.composite) {
9
+ findings.push({
10
+ ruleId: ruleId,
11
+ category: "conflict",
12
+ severity: "warn",
13
+ message: `"emitDeclarationOnly" is enabled but "declaration" (or "composite") is not. TypeScript requires declaration generation to be enabled for emitDeclarationOnly to work. Either enable "declaration": true or remove "emitDeclarationOnly".`
14
+ });
15
+ }
16
+ return findings;
17
+ }
18
+ };
19
+ //# sourceMappingURL=emitDeclarationOnly.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emitDeclarationOnly.js","sourceRoot":"","sources":["../../src/rules/emitDeclarationOnly.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,GAAG,sCAAsC,CAAC;AAEtD,MAAM,CAAC,MAAM,uBAAuB,GAAS;IACzC,EAAE,EAAE,MAAM;IAEV,OAAO,CAAC,MAAuB;QAC3B,MAAM,OAAO,GAAG,MAAM,CAAC,eAAe,IAAI,EAAE,CAAC;QAC7C,MAAM,mBAAmB,GAAG,OAAO,CAAC,mBAAmB,CAAC;QACxD,MAAM,QAAQ,GAAc,EAAE,CAAC;QAE/B,IAAI,mBAAmB,IAAI,CAAC,OAAO,CAAC,WAAW,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC;YACpE,QAAQ,CAAC,IAAI,CAAC;gBACV,MAAM,EAAE,MAAM;gBACd,QAAQ,EAAE,UAAU;gBACpB,QAAQ,EAAE,MAAM;gBAChB,OAAO,EAAE,0OAA0O;aACtP,CAAC,CAAC;QACP,CAAC;QAED,OAAO,QAAQ,CAAC;IACpB,CAAC;CACJ,CAAC"}
@@ -14,3 +14,7 @@ export { verbatimModuleSyntaxCheckRule } from "./moduleVerbatimModuleSyntaxCheck
14
14
  export { allowSyntheticDefaultImportsRule } from "./allowSyntheticDefaultImportsCheck.js";
15
15
  export { noUncheckedIndexedAccessRule } from "./noUncheckedIndexedAccessCheck.js";
16
16
  export { forceConsistentCasingInFileNamesRule } from "./forceConsistentCasing.js";
17
+ export { moduleResolutionOutdatedRule } from "./moduleResolutionOutdated.js";
18
+ export { emitDeclarationOnlyRule } from "./emitDeclarationOnly.js";
19
+ export { legacyJsxTransformCheckRule } from "./legacyJsxTransformCheck.js";
20
+ export { declarationMapCheckRule } from "./declarationMapCheck.js";
@@ -14,4 +14,8 @@ export { verbatimModuleSyntaxCheckRule } from "./moduleVerbatimModuleSyntaxCheck
14
14
  export { allowSyntheticDefaultImportsRule } from "./allowSyntheticDefaultImportsCheck.js";
15
15
  export { noUncheckedIndexedAccessRule } from "./noUncheckedIndexedAccessCheck.js";
16
16
  export { forceConsistentCasingInFileNamesRule } from "./forceConsistentCasing.js";
17
+ export { moduleResolutionOutdatedRule } from "./moduleResolutionOutdated.js";
18
+ export { emitDeclarationOnlyRule } from "./emitDeclarationOnly.js";
19
+ export { legacyJsxTransformCheckRule } from "./legacyJsxTransformCheck.js";
20
+ export { declarationMapCheckRule } from "./declarationMapCheck.js";
17
21
  //# sourceMappingURL=index.js.map
@@ -1 +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;AAC7E,OAAO,EAAE,0BAA0B,EAAE,MAAM,wBAAwB,CAAC;AACpE,OAAO,EAAE,iCAAiC,EAAE,MAAM,oCAAoC,CAAC;AACvF,OAAO,EAAE,6BAA6B,EAAE,MAAM,sCAAsC,CAAC;AACrF,OAAO,EAAE,gCAAgC,EAAE,MAAM,wCAAwC,CAAC;AAC1F,OAAO,EAAE,4BAA4B,EAAE,MAAM,oCAAoC,CAAC;AAClF,OAAO,EAAE,oCAAoC,EAAE,MAAM,4BAA4B,CAAC"}
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;AAC7E,OAAO,EAAE,0BAA0B,EAAE,MAAM,wBAAwB,CAAC;AACpE,OAAO,EAAE,iCAAiC,EAAE,MAAM,oCAAoC,CAAC;AACvF,OAAO,EAAE,6BAA6B,EAAE,MAAM,sCAAsC,CAAC;AACrF,OAAO,EAAE,gCAAgC,EAAE,MAAM,wCAAwC,CAAC;AAC1F,OAAO,EAAE,4BAA4B,EAAE,MAAM,oCAAoC,CAAC;AAClF,OAAO,EAAE,oCAAoC,EAAE,MAAM,4BAA4B,CAAC;AAClF,OAAO,EAAE,4BAA4B,EAAE,MAAM,+BAA+B,CAAC;AAC7E,OAAO,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AACnE,OAAO,EAAE,2BAA2B,EAAE,MAAM,8BAA8B,CAAC;AAC3E,OAAO,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAA"}
@@ -0,0 +1,2 @@
1
+ import type { Rule } from "../types.js";
2
+ export declare const legacyJsxTransformCheckRule: Rule;
@@ -0,0 +1,19 @@
1
+ import { JsxEmit } from "typescript";
2
+ const ruleId = "ts.jsx.legacyTransform";
3
+ export const legacyJsxTransformCheckRule = {
4
+ id: ruleId,
5
+ analyze(config) {
6
+ const options = config.compilerOptions ?? {};
7
+ const findings = [];
8
+ if (options.jsx === JsxEmit.React) {
9
+ findings.push({
10
+ ruleId: ruleId,
11
+ category: "suggestion",
12
+ severity: "info",
13
+ message: `"jsx" is set to "react" (legacy transform), which requires \`import React from 'react'\` in every JSX file. Consider switching to "react-jsx" (available since TS 4.1 / React 17). Set "jsx": "react-jsx" for production and "react-jsxdev" for development.`
14
+ });
15
+ }
16
+ return findings;
17
+ }
18
+ };
19
+ //# sourceMappingURL=legacyJsxTransformCheck.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"legacyJsxTransformCheck.js","sourceRoot":"","sources":["../../src/rules/legacyJsxTransformCheck.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAGrC,MAAM,MAAM,GAAG,wBAAwB,CAAC;AAExC,MAAM,CAAC,MAAM,2BAA2B,GAAS;IAC7C,EAAE,EAAE,MAAM;IAEV,OAAO,CAAC,MAAuB;QAC3B,MAAM,OAAO,GAAG,MAAM,CAAC,eAAe,IAAI,EAAE,CAAC;QAC7C,MAAM,QAAQ,GAAc,EAAE,CAAC;QAE/B,IAAI,OAAO,CAAC,GAAG,KAAK,OAAO,CAAC,KAAK,EAAE,CAAC;YAChC,QAAQ,CAAC,IAAI,CAAC;gBACV,MAAM,EAAE,MAAM;gBACd,QAAQ,EAAE,YAAY;gBACtB,QAAQ,EAAE,MAAM;gBAChB,OAAO,EAAE,8PAA8P;aAC1Q,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 moduleResolutionOutdatedRule: Rule;
@@ -0,0 +1,29 @@
1
+ import { ModuleResolutionKind, ScriptTarget } from "typescript";
2
+ const ruleId = "ts.moduleResolution.outdated";
3
+ export const moduleResolutionOutdatedRule = {
4
+ id: ruleId,
5
+ analyze(config) {
6
+ const options = config.compilerOptions ?? {};
7
+ const moduleResolution = options.moduleResolution;
8
+ const findings = [];
9
+ if (moduleResolution === ModuleResolutionKind.Node10) {
10
+ findings.push({
11
+ ruleId: ruleId,
12
+ category: "legacy",
13
+ severity: "warn",
14
+ message: `"moduleResolution" is set to "node" (Node10), which is the legacy CommonJS resolution algorithm. It does not support package.json "exports", self-references via "imports", or ESM resolution rules. Consider upgrading to "node16", "nodenext" (for Node.js), or "bundler" (for Vite/Webpack/esbuild).`
15
+ });
16
+ }
17
+ const target = options.target;
18
+ if (target !== undefined && target < ScriptTarget.ES2017) {
19
+ findings.push({
20
+ ruleId: ruleId,
21
+ category: "suggestion",
22
+ severity: "warn",
23
+ message: `"target" is outdated. Consider upgrading to at least "ES2017" or "ES2020". See "https://github.com/tsconfig/bases#centralized-recommendations-for-tsconfig-bases" for more details`
24
+ });
25
+ }
26
+ return findings;
27
+ }
28
+ };
29
+ //# sourceMappingURL=moduleResolutionOutdated.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"moduleResolutionOutdated.js","sourceRoot":"","sources":["../../src/rules/moduleResolutionOutdated.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAGhE,MAAM,MAAM,GAAG,8BAA8B,CAAC;AAE9C,MAAM,CAAC,MAAM,4BAA4B,GAAS;IAC9C,EAAE,EAAE,MAAM;IAEV,OAAO,CAAC,MAAuB;QAC3B,MAAM,OAAO,GAAG,MAAM,CAAC,eAAe,IAAI,EAAE,CAAC;QAE7C,MAAM,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,CAAC;QAElD,MAAM,QAAQ,GAAc,EAAE,CAAC;QAE/B,IAAI,gBAAgB,KAAK,oBAAoB,CAAC,MAAM,EAAE,CAAC;YACnD,QAAQ,CAAC,IAAI,CAAC;gBACV,MAAM,EAAE,MAAM;gBACd,QAAQ,EAAE,QAAQ;gBAClB,QAAQ,EAAE,MAAM;gBAChB,OAAO,EAAE,ySAAyS;aACrT,CAAC,CAAC;QACP,CAAC;QAED,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAA;QAC7B,IAAI,MAAM,KAAK,SAAS,IAAI,MAAM,GAAG,YAAY,CAAC,MAAM,EAAE,CAAC;YACvD,QAAQ,CAAC,IAAI,CAAC;gBACV,MAAM,EAAE,MAAM;gBACd,QAAQ,EAAE,YAAY;gBACtB,QAAQ,EAAE,MAAM;gBAChB,OAAO,EAAE,oLAAoL;aAChM,CAAC,CAAC;QACP,CAAC;QAED,OAAO,QAAQ,CAAC;IACpB,CAAC;CACJ,CAAC"}
package/dist/types.d.ts CHANGED
@@ -14,6 +14,7 @@ export interface AnalysisContext {
14
14
  exclude?: string[];
15
15
  files?: string[];
16
16
  extends?: string;
17
+ compileOnSave?: boolean;
17
18
  };
18
19
  }
19
20
  export interface Rule {
package/package.json CHANGED
@@ -1,45 +1,49 @@
1
- {
2
- "name": "ts-reconf",
3
- "version": "0.3.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
- "repository": {
16
- "type": "git",
17
- "url": "https://github.com/rockcoder/ts-reconf.git"
18
- },
19
- "scripts": {
20
- "build": "tsc",
21
- "dev": "tsx src/cli.ts",
22
- "clean": "rm -rf dist",
23
- "start": "node dist/cli.js",
24
- "test": "echo \"Todo: write tests\" && exit 1",
25
- "prepublishOnly": "npm run clean && npm run build"
26
- },
27
- "engines": {
28
- "node": ">=18"
29
- },
30
- "keywords": [
31
- "typescript",
32
- "tsconfig",
33
- "cli",
34
- "developer-tools"
35
- ],
36
- "author": "rockcoder",
37
- "license": "MIT",
38
- "dependencies": {
39
- "typescript": "6.0.3"
40
- },
41
- "devDependencies": {
42
- "@types/node": "25.6.0",
43
- "tsx": "4.21.0"
44
- }
45
- }
1
+ {
2
+ "name": "ts-reconf",
3
+ "version": "0.4.1",
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
+ "repository": {
16
+ "type": "git",
17
+ "url": "https://github.com/rockcoder/ts-reconf.git"
18
+ },
19
+ "scripts": {
20
+ "build": "tsc",
21
+ "dev": "tsx src/cli.ts",
22
+ "clean": "rm -rf dist",
23
+ "start": "node dist/cli.js",
24
+ "test": "vitest",
25
+ "test:run": "vitest run",
26
+ "test:coverage": "vitest run --coverage",
27
+ "prepublishOnly": "npm run clean && npm run build"
28
+ },
29
+ "engines": {
30
+ "node": ">=20"
31
+ },
32
+ "keywords": [
33
+ "typescript",
34
+ "tsconfig",
35
+ "cli",
36
+ "developer-tools"
37
+ ],
38
+ "author": "rockcoder",
39
+ "license": "MIT",
40
+ "dependencies": {
41
+ "typescript": "6.0.3"
42
+ },
43
+ "devDependencies": {
44
+ "@types/node": "25.9.1",
45
+ "@vitest/coverage-v8": "4.1.8",
46
+ "tsx": "4.22.4",
47
+ "vitest": "4.1.8"
48
+ }
49
+ }