@hatem427/code-guard-ci 1.0.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 (107) hide show
  1. package/.husky/pre-commit +27 -0
  2. package/LICENSE +21 -0
  3. package/README.md +646 -0
  4. package/config/angular.config.ts +223 -0
  5. package/config/guidelines.config.ts +229 -0
  6. package/config/nextjs.config.ts +160 -0
  7. package/config/react.config.ts +330 -0
  8. package/dist/config/angular.config.d.ts +15 -0
  9. package/dist/config/angular.config.d.ts.map +1 -0
  10. package/dist/config/angular.config.js +187 -0
  11. package/dist/config/angular.config.js.map +1 -0
  12. package/dist/config/guidelines.config.d.ts +63 -0
  13. package/dist/config/guidelines.config.d.ts.map +1 -0
  14. package/dist/config/guidelines.config.js +167 -0
  15. package/dist/config/guidelines.config.js.map +1 -0
  16. package/dist/config/nextjs.config.d.ts +18 -0
  17. package/dist/config/nextjs.config.d.ts.map +1 -0
  18. package/dist/config/nextjs.config.js +133 -0
  19. package/dist/config/nextjs.config.js.map +1 -0
  20. package/dist/config/react.config.d.ts +15 -0
  21. package/dist/config/react.config.d.ts.map +1 -0
  22. package/dist/config/react.config.js +287 -0
  23. package/dist/config/react.config.js.map +1 -0
  24. package/dist/scripts/auto-fix.d.ts +16 -0
  25. package/dist/scripts/auto-fix.d.ts.map +1 -0
  26. package/dist/scripts/auto-fix.js +130 -0
  27. package/dist/scripts/auto-fix.js.map +1 -0
  28. package/dist/scripts/cli.d.ts +17 -0
  29. package/dist/scripts/cli.d.ts.map +1 -0
  30. package/dist/scripts/cli.js +255 -0
  31. package/dist/scripts/cli.js.map +1 -0
  32. package/dist/scripts/delete-bypass-logs.d.ts +17 -0
  33. package/dist/scripts/delete-bypass-logs.d.ts.map +1 -0
  34. package/dist/scripts/delete-bypass-logs.js +242 -0
  35. package/dist/scripts/delete-bypass-logs.js.map +1 -0
  36. package/dist/scripts/generate-doc.d.ts +18 -0
  37. package/dist/scripts/generate-doc.d.ts.map +1 -0
  38. package/dist/scripts/generate-doc.js +300 -0
  39. package/dist/scripts/generate-doc.js.map +1 -0
  40. package/dist/scripts/generate-pr-checklist.d.ts +20 -0
  41. package/dist/scripts/generate-pr-checklist.d.ts.map +1 -0
  42. package/dist/scripts/generate-pr-checklist.js +276 -0
  43. package/dist/scripts/generate-pr-checklist.js.map +1 -0
  44. package/dist/scripts/precommit-check.d.ts +23 -0
  45. package/dist/scripts/precommit-check.d.ts.map +1 -0
  46. package/dist/scripts/precommit-check.js +331 -0
  47. package/dist/scripts/precommit-check.js.map +1 -0
  48. package/dist/scripts/set-admin-password.d.ts +14 -0
  49. package/dist/scripts/set-admin-password.d.ts.map +1 -0
  50. package/dist/scripts/set-admin-password.js +116 -0
  51. package/dist/scripts/set-admin-password.js.map +1 -0
  52. package/dist/scripts/set-bypass-password.d.ts +11 -0
  53. package/dist/scripts/set-bypass-password.d.ts.map +1 -0
  54. package/dist/scripts/set-bypass-password.js +106 -0
  55. package/dist/scripts/set-bypass-password.js.map +1 -0
  56. package/dist/scripts/utils/auto-fixer.d.ts +28 -0
  57. package/dist/scripts/utils/auto-fixer.d.ts.map +1 -0
  58. package/dist/scripts/utils/auto-fixer.js +177 -0
  59. package/dist/scripts/utils/auto-fixer.js.map +1 -0
  60. package/dist/scripts/utils/bypass-manager.d.ts +101 -0
  61. package/dist/scripts/utils/bypass-manager.d.ts.map +1 -0
  62. package/dist/scripts/utils/bypass-manager.js +496 -0
  63. package/dist/scripts/utils/bypass-manager.js.map +1 -0
  64. package/dist/scripts/utils/code-analyzer.d.ts +34 -0
  65. package/dist/scripts/utils/code-analyzer.d.ts.map +1 -0
  66. package/dist/scripts/utils/code-analyzer.js +323 -0
  67. package/dist/scripts/utils/code-analyzer.js.map +1 -0
  68. package/dist/scripts/utils/file-checker.d.ts +93 -0
  69. package/dist/scripts/utils/file-checker.d.ts.map +1 -0
  70. package/dist/scripts/utils/file-checker.js +248 -0
  71. package/dist/scripts/utils/file-checker.js.map +1 -0
  72. package/dist/scripts/utils/logger.d.ts +26 -0
  73. package/dist/scripts/utils/logger.d.ts.map +1 -0
  74. package/dist/scripts/utils/logger.js +86 -0
  75. package/dist/scripts/utils/logger.js.map +1 -0
  76. package/dist/scripts/utils/project-detector.d.ts +34 -0
  77. package/dist/scripts/utils/project-detector.d.ts.map +1 -0
  78. package/dist/scripts/utils/project-detector.js +124 -0
  79. package/dist/scripts/utils/project-detector.js.map +1 -0
  80. package/dist/scripts/utils/rule-engine.d.ts +57 -0
  81. package/dist/scripts/utils/rule-engine.d.ts.map +1 -0
  82. package/dist/scripts/utils/rule-engine.js +158 -0
  83. package/dist/scripts/utils/rule-engine.js.map +1 -0
  84. package/dist/scripts/view-bypass-log.d.ts +13 -0
  85. package/dist/scripts/view-bypass-log.d.ts.map +1 -0
  86. package/dist/scripts/view-bypass-log.js +117 -0
  87. package/dist/scripts/view-bypass-log.js.map +1 -0
  88. package/package.json +74 -0
  89. package/scripts/auto-fix.ts +115 -0
  90. package/scripts/cli.ts +246 -0
  91. package/scripts/delete-bypass-logs.ts +253 -0
  92. package/scripts/generate-doc.ts +317 -0
  93. package/scripts/generate-pr-checklist.ts +285 -0
  94. package/scripts/precommit-check.ts +349 -0
  95. package/scripts/set-admin-password.ts +90 -0
  96. package/scripts/set-bypass-password.ts +80 -0
  97. package/scripts/utils/auto-fixer.ts +181 -0
  98. package/scripts/utils/bypass-manager.ts +566 -0
  99. package/scripts/utils/code-analyzer.ts +341 -0
  100. package/scripts/utils/file-checker.ts +253 -0
  101. package/scripts/utils/logger.ts +88 -0
  102. package/scripts/utils/project-detector.ts +115 -0
  103. package/scripts/utils/rule-engine.ts +186 -0
  104. package/scripts/view-bypass-log.ts +92 -0
  105. package/templates/feature-doc-api.md +101 -0
  106. package/templates/feature-doc-service.md +113 -0
  107. package/templates/feature-doc-ui.md +91 -0
@@ -0,0 +1,90 @@
1
+ #!/usr/bin/env ts-node
2
+ /**
3
+ * ============================================================================
4
+ * set-admin-password.ts — CLI tool to set admin password
5
+ * ============================================================================
6
+ *
7
+ * Admin password is required to delete bypass log entries.
8
+ * This provides a higher level of security for log management.
9
+ *
10
+ * Usage:
11
+ * npm run set-admin-password
12
+ */
13
+
14
+ import { setAdminPassword } from './utils/bypass-manager';
15
+ import * as readline from 'readline';
16
+
17
+ function promptPassword(question: string): Promise<string> {
18
+ return new Promise((resolve) => {
19
+ const rl = readline.createInterface({
20
+ input: process.stdin,
21
+ output: process.stdout,
22
+ });
23
+
24
+ const stdin = process.stdin as any;
25
+ stdin.setRawMode(true);
26
+
27
+ let password = '';
28
+ process.stdout.write(question);
29
+
30
+ stdin.on('data', (char: Buffer) => {
31
+ const str = char.toString('utf-8');
32
+
33
+ if (str === '\n' || str === '\r' || str === '\u0004') {
34
+ stdin.setRawMode(false);
35
+ process.stdout.write('\n');
36
+ rl.close();
37
+ resolve(password);
38
+ } else if (str === '\u0003') {
39
+ // Ctrl+C
40
+ process.exit(1);
41
+ } else if (str === '\u007f' || str === '\b') {
42
+ // Backspace
43
+ if (password.length > 0) {
44
+ password = password.slice(0, -1);
45
+ process.stdout.write('\b \b');
46
+ }
47
+ } else {
48
+ password += str;
49
+ process.stdout.write('*');
50
+ }
51
+ });
52
+ });
53
+ }
54
+
55
+ async function main() {
56
+ console.log('🔐 Code Guardian — Set Admin Password\n');
57
+ console.log('⚠️ ADMIN PRIVILEGES:');
58
+ console.log(' • View all bypass logs');
59
+ console.log(' • Delete bypass log entries');
60
+ console.log(' • Access archived logs\n');
61
+ console.log('🔒 This password should be highly restricted and secure.\n');
62
+
63
+ const password = await promptPassword('Enter new admin password: ');
64
+
65
+ if (!password || password.length < 8) {
66
+ console.error('\n❌ Admin password must be at least 8 characters long.');
67
+ process.exit(1);
68
+ }
69
+
70
+ const confirm = await promptPassword('Confirm password: ');
71
+
72
+ if (password !== confirm) {
73
+ console.error('\n❌ Passwords do not match.');
74
+ process.exit(1);
75
+ }
76
+
77
+ setAdminPassword(password);
78
+ console.log('\n✅ Admin password set successfully!');
79
+ console.log('📁 Stored in: .code-guardian/admin-credentials.hash');
80
+ console.log('\n⚠️ IMPORTANT SECURITY NOTES:');
81
+ console.log(' 1. Add .code-guardian/ to .gitignore (if not already done)');
82
+ console.log(' 2. Share this password only with authorized administrators');
83
+ console.log(' 3. Change default password immediately in production');
84
+ console.log(' 4. Store password securely (password manager recommended)');
85
+ }
86
+
87
+ main().catch((err) => {
88
+ console.error(`Error: ${err.message}`);
89
+ process.exit(1);
90
+ });
@@ -0,0 +1,80 @@
1
+ #!/usr/bin/env ts-node
2
+ /**
3
+ * ============================================================================
4
+ * set-bypass-password.ts — CLI tool to set bypass password
5
+ * ============================================================================
6
+ *
7
+ * Usage:
8
+ * npm run set-bypass-password
9
+ */
10
+
11
+ import { setBypassPassword } from './utils/bypass-manager';
12
+ import * as readline from 'readline';
13
+
14
+ function promptPassword(question: string): Promise<string> {
15
+ return new Promise((resolve) => {
16
+ const rl = readline.createInterface({
17
+ input: process.stdin,
18
+ output: process.stdout,
19
+ });
20
+
21
+ const stdin = process.stdin as any;
22
+ stdin.setRawMode(true);
23
+
24
+ let password = '';
25
+ process.stdout.write(question);
26
+
27
+ stdin.on('data', (char: Buffer) => {
28
+ const str = char.toString('utf-8');
29
+
30
+ if (str === '\n' || str === '\r' || str === '\u0004') {
31
+ stdin.setRawMode(false);
32
+ process.stdout.write('\n');
33
+ rl.close();
34
+ resolve(password);
35
+ } else if (str === '\u0003') {
36
+ // Ctrl+C
37
+ process.exit(1);
38
+ } else if (str === '\u007f' || str === '\b') {
39
+ // Backspace
40
+ if (password.length > 0) {
41
+ password = password.slice(0, -1);
42
+ process.stdout.write('\b \b');
43
+ }
44
+ } else {
45
+ password += str;
46
+ process.stdout.write('*');
47
+ }
48
+ });
49
+ });
50
+ }
51
+
52
+ async function main() {
53
+ console.log('🔐 Code Guardian — Set Bypass Password\n');
54
+ console.log('This password will be required to bypass pre-commit checks.');
55
+ console.log('Share it only with authorized team members.\n');
56
+
57
+ const password = await promptPassword('Enter new bypass password: ');
58
+
59
+ if (!password || password.length < 6) {
60
+ console.error('\n❌ Password must be at least 6 characters long.');
61
+ process.exit(1);
62
+ }
63
+
64
+ const confirm = await promptPassword('Confirm password: ');
65
+
66
+ if (password !== confirm) {
67
+ console.error('\n❌ Passwords do not match.');
68
+ process.exit(1);
69
+ }
70
+
71
+ setBypassPassword(password);
72
+ console.log('\n✅ Password set successfully!');
73
+ console.log('📁 Stored in: .code-guardian/bypass-password.hash');
74
+ console.log('\n⚠️ Remember to add .code-guardian/ to .gitignore if not already done.');
75
+ }
76
+
77
+ main().catch((err) => {
78
+ console.error(`Error: ${err.message}`);
79
+ process.exit(1);
80
+ });
@@ -0,0 +1,181 @@
1
+ /**
2
+ * ============================================================================
3
+ * auto-fixer.ts — Automatic code fixes for common violations
4
+ * ============================================================================
5
+ *
6
+ * Provides auto-fix capabilities for rules that can be safely automated.
7
+ */
8
+
9
+ import * as fs from 'fs';
10
+ import { Violation } from './rule-engine';
11
+
12
+ export interface FixResult {
13
+ fixed: boolean;
14
+ message: string;
15
+ }
16
+
17
+ /**
18
+ * Attempt to auto-fix a violation
19
+ */
20
+ export function autoFixViolation(violation: Violation, filePath: string): FixResult {
21
+ const content = fs.readFileSync(filePath, 'utf-8');
22
+ const lines = content.split('\n');
23
+
24
+ switch (violation.ruleId) {
25
+ case 'no-console-log':
26
+ return fixConsoleLog(lines, violation, filePath);
27
+
28
+ case 'no-any-type':
29
+ return fixAnyType(lines, violation, filePath);
30
+
31
+ case 'react-no-inline-styles':
32
+ return { fixed: false, message: 'Manual fix required - convert to Tailwind classes' };
33
+
34
+ case 'require-alt-text':
35
+ return fixMissingAlt(lines, violation, filePath);
36
+
37
+ case 'require-button-type':
38
+ return fixButtonType(lines, violation, filePath);
39
+
40
+ default:
41
+ return { fixed: false, message: 'No auto-fix available for this rule' };
42
+ }
43
+ }
44
+
45
+ /**
46
+ * Remove console.log statements
47
+ */
48
+ function fixConsoleLog(lines: string[], violation: Violation, filePath: string): FixResult {
49
+ if (!violation.line) {
50
+ return { fixed: false, message: 'Cannot determine line number' };
51
+ }
52
+
53
+ const lineIndex = violation.line - 1;
54
+ const line = lines[lineIndex];
55
+
56
+ // Remove entire line if it only contains console.log
57
+ if (line.trim().match(/^console\.log\(.+\);?\s*$/)) {
58
+ lines.splice(lineIndex, 1);
59
+ fs.writeFileSync(filePath, lines.join('\n'), 'utf-8');
60
+ return { fixed: true, message: 'Removed console.log statement' };
61
+ }
62
+
63
+ return { fixed: false, message: 'Console.log is part of larger expression - manual fix required' };
64
+ }
65
+
66
+ /**
67
+ * Convert 'any' to 'unknown' (safer)
68
+ */
69
+ function fixAnyType(lines: string[], violation: Violation, filePath: string): FixResult {
70
+ if (!violation.line) {
71
+ return { fixed: false, message: 'Cannot determine line number' };
72
+ }
73
+
74
+ const lineIndex = violation.line - 1;
75
+ let line = lines[lineIndex];
76
+
77
+ // Replace : any with : unknown
78
+ if (line.includes(': any')) {
79
+ line = line.replace(/:\s*any\b/g, ': unknown');
80
+ lines[lineIndex] = line;
81
+ fs.writeFileSync(filePath, lines.join('\n'), 'utf-8');
82
+ return { fixed: true, message: 'Changed any → unknown' };
83
+ }
84
+
85
+ // Replace any[] with unknown[]
86
+ if (line.includes('any[]')) {
87
+ line = line.replace(/\bany\[\]/g, 'unknown[]');
88
+ lines[lineIndex] = line;
89
+ fs.writeFileSync(filePath, lines.join('\n'), 'utf-8');
90
+ return { fixed: true, message: 'Changed any[] → unknown[]' };
91
+ }
92
+
93
+ return { fixed: false, message: 'Complex any usage - manual fix required' };
94
+ }
95
+
96
+ /**
97
+ * Add alt="" to images
98
+ */
99
+ function fixMissingAlt(lines: string[], violation: Violation, filePath: string): FixResult {
100
+ if (!violation.line) {
101
+ return { fixed: false, message: 'Cannot determine line number' };
102
+ }
103
+
104
+ const lineIndex = violation.line - 1;
105
+ let line = lines[lineIndex];
106
+
107
+ // Add alt="" before the closing />
108
+ if (/<img\b/.test(line) && !/alt\s*=/.test(line)) {
109
+ // Add alt before />
110
+ line = line.replace(/\/>/, ' alt="" />');
111
+ // Or before >
112
+ line = line.replace(/([^/])>/, '$1 alt="">');
113
+
114
+ lines[lineIndex] = line;
115
+ fs.writeFileSync(filePath, lines.join('\n'), 'utf-8');
116
+ return { fixed: true, message: 'Added alt="" attribute' };
117
+ }
118
+
119
+ return { fixed: false, message: 'Could not add alt attribute' };
120
+ }
121
+
122
+ /**
123
+ * Add type="button" to buttons
124
+ */
125
+ function fixButtonType(lines: string[], violation: Violation, filePath: string): FixResult {
126
+ if (!violation.line) {
127
+ return { fixed: false, message: 'Cannot determine line number' };
128
+ }
129
+
130
+ const lineIndex = violation.line - 1;
131
+ let line = lines[lineIndex];
132
+
133
+ // Add type="button" to <button>
134
+ if (/<button\b/.test(line) && !/type\s*=/.test(line)) {
135
+ line = line.replace(/<button/, '<button type="button"');
136
+
137
+ lines[lineIndex] = line;
138
+ fs.writeFileSync(filePath, lines.join('\n'), 'utf-8');
139
+ return { fixed: true, message: 'Added type="button" attribute' };
140
+ }
141
+
142
+ return { fixed: false, message: 'Could not add type attribute' };
143
+ }
144
+
145
+ /**
146
+ * Auto-fix all fixable violations in a list
147
+ */
148
+ export function autoFixAll(violations: Violation[], rootDir: string): {
149
+ fixed: number;
150
+ failed: number;
151
+ results: Array<{ violation: Violation; result: FixResult }>;
152
+ } {
153
+ const results: Array<{ violation: Violation; result: FixResult }> = [];
154
+ let fixed = 0;
155
+ let failed = 0;
156
+
157
+ // Group by file to avoid multiple reads/writes
158
+ const byFile = new Map<string, Violation[]>();
159
+ for (const v of violations) {
160
+ const existing = byFile.get(v.file) || [];
161
+ existing.push(v);
162
+ byFile.set(v.file, existing);
163
+ }
164
+
165
+ for (const [file, fileViolations] of byFile) {
166
+ const fullPath = `${rootDir}/${file}`;
167
+
168
+ for (const violation of fileViolations) {
169
+ const result = autoFixViolation(violation, fullPath);
170
+ results.push({ violation, result });
171
+
172
+ if (result.fixed) {
173
+ fixed++;
174
+ } else {
175
+ failed++;
176
+ }
177
+ }
178
+ }
179
+
180
+ return { fixed, failed, results };
181
+ }