@goldensheepai/toknxr-cli 0.2.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.
@@ -0,0 +1,319 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ import chalk from 'chalk';
4
+ // Comprehensive code review rules for AI-generated code
5
+ export const DEFAULT_CODE_REVIEW_RULES = [
6
+ // Security Issues
7
+ {
8
+ id: 'SEC001',
9
+ name: 'Hardcoded Secrets',
10
+ description: 'Detects hardcoded API keys, passwords, or tokens',
11
+ severity: 'error',
12
+ category: 'security',
13
+ pattern: /(api[_-]?key|password|secret|token)\s*[=:]?\s*["'][^"']{8,}["']/gi,
14
+ message: 'Potential hardcoded secret detected',
15
+ suggestion: 'Use environment variables or secure secret management'
16
+ },
17
+ {
18
+ id: 'SEC002',
19
+ name: 'SQL Injection Risk',
20
+ description: 'Detects unsafe string concatenation in SQL queries',
21
+ severity: 'error',
22
+ category: 'security',
23
+ pattern: /(SELECT|INSERT|UPDATE|DELETE).*\+.*["'][^"']*["']/gi,
24
+ message: 'Potential SQL injection vulnerability',
25
+ suggestion: 'Use parameterized queries or prepared statements'
26
+ },
27
+ {
28
+ id: 'SEC003',
29
+ name: 'Insecure Random',
30
+ description: 'Detects use of Math.random() for security-sensitive operations',
31
+ severity: 'warning',
32
+ category: 'security',
33
+ pattern: /Math\.random\(\)/g,
34
+ message: 'Math.random() is not cryptographically secure',
35
+ suggestion: 'Use crypto.randomBytes() or crypto.getRandomValues() for security-sensitive operations'
36
+ },
37
+ // Performance Issues
38
+ {
39
+ id: 'PERF001',
40
+ name: 'Inefficient Loop',
41
+ description: 'Detects potential infinite or inefficient loops',
42
+ severity: 'warning',
43
+ category: 'performance',
44
+ pattern: /for\s*\(\s*let\s+\w+\s*=\s*0\s*;\s*\w+\s*<\s*\w+\.length\s*;\s*\w+\+\+\s*\)\s*{[^}]*\w+\[\w+\]/g,
45
+ message: 'Potential inefficient array iteration',
46
+ suggestion: 'Consider using modern array methods like forEach, map, or for...of'
47
+ },
48
+ {
49
+ id: 'PERF002',
50
+ name: 'Large DOM Manipulation',
51
+ description: 'Detects multiple DOM manipulations that could be batched',
52
+ severity: 'info',
53
+ category: 'performance',
54
+ pattern: /(document\.createElement|appendChild|innerHTML\s*=)[^;]+;[^;]*\1/gi,
55
+ message: 'Multiple DOM manipulations detected',
56
+ suggestion: 'Consider batching DOM operations or using DocumentFragment'
57
+ },
58
+ // Maintainability Issues
59
+ {
60
+ id: 'MAINT001',
61
+ name: 'Long Function',
62
+ description: 'Detects functions that are too long and should be broken up',
63
+ severity: 'warning',
64
+ category: 'maintainability',
65
+ pattern: /^(?:function|\w+\s*=>|\w+\s*\([^)]*\)\s*{[^}]*{[^}]*}[^}]*})/gm,
66
+ message: 'Function appears to be too long',
67
+ suggestion: 'Consider breaking this function into smaller, more focused functions'
68
+ },
69
+ {
70
+ id: 'MAINT002',
71
+ name: 'Missing Error Handling',
72
+ description: 'Detects operations that might throw errors without proper handling',
73
+ severity: 'warning',
74
+ category: 'maintainability',
75
+ pattern: /(fetch|axios|XMLHttpRequest)\s*\([^)]+\)\s*(?![^}]*catch|\.catch)/gi,
76
+ message: 'Async operation without error handling',
77
+ suggestion: 'Add try-catch blocks or .catch() handlers for async operations'
78
+ },
79
+ {
80
+ id: 'MAINT003',
81
+ name: 'Magic Numbers',
82
+ description: 'Detects hardcoded numeric values that should be constants',
83
+ severity: 'info',
84
+ category: 'maintainability',
85
+ pattern: /\b\d{2,}\b/g,
86
+ message: 'Magic number detected',
87
+ suggestion: 'Consider defining this as a named constant for better readability'
88
+ },
89
+ // Reliability Issues
90
+ {
91
+ id: 'REL001',
92
+ name: 'Unsafe Type Coercion',
93
+ description: 'Detects potentially unsafe type conversions',
94
+ severity: 'warning',
95
+ category: 'reliability',
96
+ pattern: /(==|!=)\s*null/gi,
97
+ message: 'Loose equality comparison with null',
98
+ suggestion: 'Use strict equality (===) or explicitly check for null/undefined'
99
+ },
100
+ {
101
+ id: 'REL002',
102
+ name: 'Resource Leaks',
103
+ description: 'Detects potential resource leaks',
104
+ severity: 'warning',
105
+ category: 'reliability',
106
+ pattern: /(addEventListener|setTimeout|setInterval)\s*\([^)]+\)\s*(?![^}]*removeEventListener|\.clear)/gi,
107
+ message: 'Event listener or timer without cleanup',
108
+ suggestion: 'Ensure proper cleanup of event listeners and timers'
109
+ }
110
+ ];
111
+ export class CodeReviewer {
112
+ rules;
113
+ constructor(customRules = []) {
114
+ this.rules = [...DEFAULT_CODE_REVIEW_RULES, ...customRules];
115
+ }
116
+ async reviewFile(filePath) {
117
+ try {
118
+ const content = fs.readFileSync(filePath, 'utf8');
119
+ const lines = content.split('\n');
120
+ const results = [];
121
+ let errors = 0;
122
+ let warnings = 0;
123
+ let info = 0;
124
+ lines.forEach((line, index) => {
125
+ this.rules.forEach(rule => {
126
+ const matches = line.match(rule.pattern);
127
+ if (matches) {
128
+ matches.forEach(match => {
129
+ const result = {
130
+ rule,
131
+ line: index + 1,
132
+ context: line.trim(),
133
+ severity: rule.severity,
134
+ message: rule.message,
135
+ suggestion: rule.suggestion
136
+ };
137
+ results.push(result);
138
+ switch (rule.severity) {
139
+ case 'error':
140
+ errors++;
141
+ break;
142
+ case 'warning':
143
+ warnings++;
144
+ break;
145
+ case 'info':
146
+ info++;
147
+ break;
148
+ }
149
+ });
150
+ }
151
+ });
152
+ });
153
+ const totalIssues = results.length;
154
+ const summary = this.generateSummary(totalIssues, errors, warnings, info);
155
+ const recommendations = this.generateRecommendations(results);
156
+ return {
157
+ filePath,
158
+ totalIssues,
159
+ errors,
160
+ warnings,
161
+ info,
162
+ results,
163
+ summary,
164
+ recommendations
165
+ };
166
+ }
167
+ catch (error) {
168
+ throw new Error(`Failed to review file ${filePath}: ${error}`);
169
+ }
170
+ }
171
+ async reviewDirectory(dirPath) {
172
+ const reports = [];
173
+ const files = this.getCodeFiles(dirPath);
174
+ for (const file of files) {
175
+ try {
176
+ const report = await this.reviewFile(file);
177
+ reports.push(report);
178
+ }
179
+ catch (error) {
180
+ console.warn(chalk.yellow(`Warning: Could not review file ${file}: ${error}`));
181
+ }
182
+ }
183
+ return reports;
184
+ }
185
+ getCodeFiles(dirPath) {
186
+ const files = [];
187
+ const extensions = ['.js', '.ts', '.jsx', '.tsx', '.py', '.java', '.cpp', '.c', '.cs'];
188
+ const scan = (currentPath) => {
189
+ const items = fs.readdirSync(currentPath);
190
+ for (const item of items) {
191
+ const fullPath = path.join(currentPath, item);
192
+ const stat = fs.statSync(fullPath);
193
+ if (stat.isDirectory() && !item.startsWith('.') && item !== 'node_modules') {
194
+ scan(fullPath);
195
+ }
196
+ else if (stat.isFile() && extensions.some(ext => item.endsWith(ext))) {
197
+ files.push(fullPath);
198
+ }
199
+ }
200
+ };
201
+ scan(dirPath);
202
+ return files;
203
+ }
204
+ generateSummary(totalIssues, errors, warnings, info) {
205
+ if (totalIssues === 0) {
206
+ return 'โœ… No issues found! The code looks good.';
207
+ }
208
+ let summary = `Found ${totalIssues} issue${totalIssues > 1 ? 's' : ''}: `;
209
+ const parts = [];
210
+ if (errors > 0)
211
+ parts.push(`${errors} error${errors > 1 ? 's' : ''}`);
212
+ if (warnings > 0)
213
+ parts.push(`${warnings} warning${warnings > 1 ? 's' : ''}`);
214
+ if (info > 0)
215
+ parts.push(`${info} info item${info > 1 ? 's' : ''}`);
216
+ summary += parts.join(', ');
217
+ if (errors > 0) {
218
+ summary += ' ๐Ÿ”ด Critical issues need immediate attention.';
219
+ }
220
+ else if (warnings > 0) {
221
+ summary += ' ๐ŸŸก Some issues should be addressed.';
222
+ }
223
+ else {
224
+ summary += ' โ„น๏ธ Minor improvements suggested.';
225
+ }
226
+ return summary;
227
+ }
228
+ generateRecommendations(results) {
229
+ const recommendations = [];
230
+ const categories = new Set(results.map(r => r.rule.category));
231
+ if (categories.has('security')) {
232
+ recommendations.push('๐Ÿ”’ Review security issues first - they pose the highest risk');
233
+ }
234
+ if (categories.has('reliability')) {
235
+ recommendations.push('๐Ÿ›ก๏ธ Address reliability issues to prevent runtime errors');
236
+ }
237
+ if (categories.has('performance')) {
238
+ recommendations.push('โšก Consider performance optimizations for better user experience');
239
+ }
240
+ if (categories.has('maintainability')) {
241
+ recommendations.push('๐Ÿงน Refactor maintainability issues for long-term code health');
242
+ }
243
+ if (recommendations.length === 0) {
244
+ recommendations.push('โœจ Code quality looks good! Consider regular reviews to maintain standards');
245
+ }
246
+ return recommendations;
247
+ }
248
+ addCustomRule(rule) {
249
+ this.rules.push(rule);
250
+ }
251
+ getRules() {
252
+ return [...this.rules];
253
+ }
254
+ }
255
+ export function printReviewReport(report) {
256
+ console.log(chalk.bold.blue(`\n๐Ÿ“‹ Code Review Report for: ${path.basename(report.filePath)}`));
257
+ console.log(chalk.gray(`File: ${report.filePath}`));
258
+ console.log(chalk.cyan(report.summary));
259
+ console.log('');
260
+ if (report.results.length > 0) {
261
+ // Group by severity
262
+ const errors = report.results.filter(r => r.severity === 'error');
263
+ const warnings = report.results.filter(r => r.severity === 'warning');
264
+ const info = report.results.filter(r => r.severity === 'info');
265
+ if (errors.length > 0) {
266
+ console.log(chalk.red.bold('๐Ÿ”ด ERRORS:'));
267
+ errors.forEach(result => {
268
+ console.log(` ${chalk.red(`[${result.rule.id}]`)} Line ${result.line}: ${result.message}`);
269
+ if (result.suggestion) {
270
+ console.log(` ๐Ÿ’ก ${chalk.gray(result.suggestion)}`);
271
+ }
272
+ });
273
+ console.log('');
274
+ }
275
+ if (warnings.length > 0) {
276
+ console.log(chalk.yellow.bold('๐ŸŸก WARNINGS:'));
277
+ warnings.forEach(result => {
278
+ console.log(` ${chalk.yellow(`[${result.rule.id}]`)} Line ${result.line}: ${result.message}`);
279
+ if (result.suggestion) {
280
+ console.log(` ๐Ÿ’ก ${chalk.gray(result.suggestion)}`);
281
+ }
282
+ });
283
+ console.log('');
284
+ }
285
+ if (info.length > 0) {
286
+ console.log(chalk.blue.bold('โ„น๏ธ INFO:'));
287
+ info.forEach(result => {
288
+ console.log(` ${chalk.blue(`[${result.rule.id}]`)} Line ${result.line}: ${result.message}`);
289
+ if (result.suggestion) {
290
+ console.log(` ๐Ÿ’ก ${chalk.gray(result.suggestion)}`);
291
+ }
292
+ });
293
+ console.log('');
294
+ }
295
+ }
296
+ if (report.recommendations.length > 0) {
297
+ console.log(chalk.green.bold('๐Ÿ’ก RECOMMENDATIONS:'));
298
+ report.recommendations.forEach(rec => {
299
+ console.log(` ${rec}`);
300
+ });
301
+ console.log('');
302
+ }
303
+ console.log(chalk.gray(`Total: ${report.totalIssues} issues (${report.errors} errors, ${report.warnings} warnings, ${report.info} info)`));
304
+ }
305
+ export function printMultipleReports(reports) {
306
+ const totalIssues = reports.reduce((sum, r) => sum + r.totalIssues, 0);
307
+ const totalErrors = reports.reduce((sum, r) => sum + r.errors, 0);
308
+ const totalWarnings = reports.reduce((sum, r) => sum + r.warnings, 0);
309
+ const totalInfo = reports.reduce((sum, r) => sum + r.info, 0);
310
+ console.log(chalk.bold.blue(`\n๐Ÿ“Š Code Review Summary`));
311
+ console.log(chalk.cyan(`Reviewed ${reports.length} files`));
312
+ console.log(chalk.gray(`Total Issues: ${totalIssues} (${totalErrors} errors, ${totalWarnings} warnings, ${totalInfo} info)`));
313
+ console.log('');
314
+ reports.forEach(report => {
315
+ if (report.totalIssues > 0) {
316
+ printReviewReport(report);
317
+ }
318
+ });
319
+ }
package/lib/config.js ADDED
@@ -0,0 +1,7 @@
1
+ import { createClient } from '@supabase/supabase-js';
2
+ export const supabaseUrl = process.env.SUPABASE_URL || 'https://pkdytotoptkknghtsomn.supabase.co';
3
+ export const supabaseAnonKey = process.env.SUPABASE_ANON_KEY || 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InBrZHl0b3RvcHRra25naHRzb21uIiwicm9sZSI6ImFub24iLCJpYXQiOjE3NTk3MjI1OTgsImV4cCI6MjA3NTI5ODU5OH0.Y3RVJvx7w-eGD4Nv2aVv8jnkUKhmA2vpkBs7_rFzEoQ';
4
+ export const supabase = createClient(supabaseUrl, supabaseAnonKey);
5
+ export const setAuthToken = (token) => {
6
+ supabase.auth.setSession({ access_token: token, refresh_token: '' });
7
+ };