codebakers 2.5.4 → 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +54 -255
- package/dist/chunk-HOWR3YTF.js +146 -0
- package/dist/index.d.ts +0 -3
- package/dist/index.js +10505 -7997
- package/dist/terminal-6ZQVP6R7.js +10 -0
- package/package.json +26 -41
- package/AUDIT_REPORT.md +0 -138
- package/dist/advisors-RWRTSJRR.js +0 -7
- package/dist/chunk-ASIJIQYC.js +0 -320
- package/dist/chunk-D44U3IEA.js +0 -565
- package/dist/chunk-LANM5XQW.js +0 -326
- package/dist/prd-RYITSL6Q.js +0 -7
- package/install.bat +0 -9
- package/installers/CodeBakers-Install.bat +0 -207
- package/installers/CodeBakers-Install.command +0 -232
- package/installers/README.md +0 -157
- package/installers/mac/assets/README.txt +0 -31
- package/installers/mac/build-mac-installer.sh +0 -240
- package/installers/windows/CodeBakers.iss +0 -256
- package/installers/windows/assets/README.txt +0 -16
- package/installers/windows/scripts/post-install.bat +0 -15
- package/src/channels/discord.ts +0 -5
- package/src/channels/slack.ts +0 -5
- package/src/channels/sms.ts +0 -4
- package/src/channels/telegram.ts +0 -5
- package/src/channels/whatsapp.ts +0 -7
- package/src/commands/advisors.ts +0 -699
- package/src/commands/build.ts +0 -1025
- package/src/commands/check.ts +0 -365
- package/src/commands/code.ts +0 -806
- package/src/commands/connect.ts +0 -12
- package/src/commands/deploy.ts +0 -448
- package/src/commands/design.ts +0 -298
- package/src/commands/fix.ts +0 -20
- package/src/commands/gateway.ts +0 -604
- package/src/commands/generate.ts +0 -178
- package/src/commands/init.ts +0 -634
- package/src/commands/integrate.ts +0 -884
- package/src/commands/learn.ts +0 -36
- package/src/commands/migrate.ts +0 -419
- package/src/commands/prd-maker.ts +0 -588
- package/src/commands/prd.ts +0 -419
- package/src/commands/security.ts +0 -102
- package/src/commands/setup.ts +0 -600
- package/src/commands/status.ts +0 -56
- package/src/commands/website.ts +0 -741
- package/src/index.ts +0 -627
- package/src/patterns/loader.ts +0 -337
- package/src/services/github.ts +0 -61
- package/src/services/supabase.ts +0 -147
- package/src/services/vercel.ts +0 -61
- package/src/utils/claude-md.ts +0 -287
- package/src/utils/config.ts +0 -375
- package/src/utils/display.ts +0 -338
- package/src/utils/files.ts +0 -418
- package/src/utils/nlp.ts +0 -312
- package/src/utils/ui.ts +0 -441
- package/src/utils/updates.ts +0 -8
- package/src/utils/voice.ts +0 -323
- package/tsconfig.json +0 -26
package/src/commands/check.ts
DELETED
|
@@ -1,365 +0,0 @@
|
|
|
1
|
-
import * as p from '@clack/prompts';
|
|
2
|
-
import chalk from 'chalk';
|
|
3
|
-
import fs from 'fs-extra';
|
|
4
|
-
import * as path from 'path';
|
|
5
|
-
import glob from 'fast-glob';
|
|
6
|
-
import { Config } from '../utils/config.js';
|
|
7
|
-
|
|
8
|
-
interface CheckOptions {
|
|
9
|
-
fix?: boolean;
|
|
10
|
-
watch?: boolean;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
interface Violation {
|
|
14
|
-
file: string;
|
|
15
|
-
line: number;
|
|
16
|
-
rule: string;
|
|
17
|
-
message: string;
|
|
18
|
-
severity: 'error' | 'warning';
|
|
19
|
-
autoFixable: boolean;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
interface CheckResult {
|
|
23
|
-
violations: Violation[];
|
|
24
|
-
filesChecked: number;
|
|
25
|
-
passed: boolean;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
// Pattern rules extracted from your CLAUDE.md
|
|
29
|
-
const RULES = [
|
|
30
|
-
{
|
|
31
|
-
id: 'no-any',
|
|
32
|
-
name: 'No any type',
|
|
33
|
-
description: 'Avoid using the "any" type',
|
|
34
|
-
severity: 'error' as const,
|
|
35
|
-
pattern: /:\s*any\b(?!\s*\=\>)/g,
|
|
36
|
-
message: 'Avoid using "any" type. Use proper TypeScript types.',
|
|
37
|
-
autoFixable: false,
|
|
38
|
-
},
|
|
39
|
-
{
|
|
40
|
-
id: 'no-ts-ignore',
|
|
41
|
-
name: 'No @ts-ignore',
|
|
42
|
-
description: 'Avoid using @ts-ignore',
|
|
43
|
-
severity: 'error' as const,
|
|
44
|
-
pattern: /@ts-ignore/g,
|
|
45
|
-
message: '@ts-ignore bypasses type checking. Fix the underlying issue.',
|
|
46
|
-
autoFixable: false,
|
|
47
|
-
},
|
|
48
|
-
{
|
|
49
|
-
id: 'no-console-log',
|
|
50
|
-
name: 'No console.log',
|
|
51
|
-
description: 'Remove debug console.log statements',
|
|
52
|
-
severity: 'warning' as const,
|
|
53
|
-
pattern: /console\.log\(/g,
|
|
54
|
-
message: 'Remove console.log before committing. Use proper logging.',
|
|
55
|
-
autoFixable: true,
|
|
56
|
-
},
|
|
57
|
-
{
|
|
58
|
-
id: 'no-todo',
|
|
59
|
-
name: 'No TODO comments',
|
|
60
|
-
description: 'Complete all TODOs before committing',
|
|
61
|
-
severity: 'warning' as const,
|
|
62
|
-
pattern: /\/\/\s*TODO:/gi,
|
|
63
|
-
message: 'Complete or remove TODO comments before committing.',
|
|
64
|
-
autoFixable: false,
|
|
65
|
-
},
|
|
66
|
-
{
|
|
67
|
-
id: 'no-fixme',
|
|
68
|
-
name: 'No FIXME comments',
|
|
69
|
-
description: 'Fix all FIXME issues before committing',
|
|
70
|
-
severity: 'error' as const,
|
|
71
|
-
pattern: /\/\/\s*FIXME:/gi,
|
|
72
|
-
message: 'Address FIXME issues before committing.',
|
|
73
|
-
autoFixable: false,
|
|
74
|
-
},
|
|
75
|
-
{
|
|
76
|
-
id: 'button-has-handler',
|
|
77
|
-
name: 'Button has onClick',
|
|
78
|
-
description: 'Buttons should have onClick handlers',
|
|
79
|
-
severity: 'error' as const,
|
|
80
|
-
pattern: /<Button[^>]*(?!onClick)[^>]*>/g,
|
|
81
|
-
message: 'Button must have an onClick handler.',
|
|
82
|
-
autoFixable: false,
|
|
83
|
-
validator: (content: string, match: RegExpExecArray) => {
|
|
84
|
-
// Check if onClick exists in the button
|
|
85
|
-
const buttonTag = match[0];
|
|
86
|
-
return !buttonTag.includes('onClick') && !buttonTag.includes('type="submit"');
|
|
87
|
-
},
|
|
88
|
-
},
|
|
89
|
-
{
|
|
90
|
-
id: 'async-has-try-catch',
|
|
91
|
-
name: 'Async has try/catch',
|
|
92
|
-
description: 'Async functions should have error handling',
|
|
93
|
-
severity: 'error' as const,
|
|
94
|
-
pattern: /async\s+(?:function\s+\w+|\([^)]*\)\s*=>|\w+\s*=\s*async\s*\([^)]*\)\s*=>)\s*\{[^}]*\}/g,
|
|
95
|
-
message: 'Async function should have try/catch error handling.',
|
|
96
|
-
autoFixable: false,
|
|
97
|
-
validator: (content: string, match: RegExpExecArray) => {
|
|
98
|
-
const funcBody = match[0];
|
|
99
|
-
return !funcBody.includes('try') && !funcBody.includes('catch');
|
|
100
|
-
},
|
|
101
|
-
},
|
|
102
|
-
{
|
|
103
|
-
id: 'no-hardcoded-secrets',
|
|
104
|
-
name: 'No hardcoded secrets',
|
|
105
|
-
description: 'Secrets should be in environment variables',
|
|
106
|
-
severity: 'error' as const,
|
|
107
|
-
pattern: /(sk_live_|sk_test_|pk_live_|pk_test_|api_key\s*=\s*['"][^'"]+['"])/gi,
|
|
108
|
-
message: 'Possible hardcoded secret. Use environment variables.',
|
|
109
|
-
autoFixable: false,
|
|
110
|
-
},
|
|
111
|
-
{
|
|
112
|
-
id: 'no-eval',
|
|
113
|
-
name: 'No eval()',
|
|
114
|
-
description: 'Never use eval() - security risk',
|
|
115
|
-
severity: 'error' as const,
|
|
116
|
-
pattern: /\beval\s*\(/g,
|
|
117
|
-
message: 'Never use eval(). It is a security vulnerability.',
|
|
118
|
-
autoFixable: false,
|
|
119
|
-
},
|
|
120
|
-
{
|
|
121
|
-
id: 'no-innerhtml',
|
|
122
|
-
name: 'No innerHTML',
|
|
123
|
-
description: 'Avoid direct innerHTML assignment',
|
|
124
|
-
severity: 'error' as const,
|
|
125
|
-
pattern: /\.innerHTML\s*=/g,
|
|
126
|
-
message: 'Avoid innerHTML. Use proper React rendering or DOMPurify.',
|
|
127
|
-
autoFixable: false,
|
|
128
|
-
},
|
|
129
|
-
{
|
|
130
|
-
id: 'loading-state',
|
|
131
|
-
name: 'Loading state in components',
|
|
132
|
-
description: 'Components with fetch should have loading states',
|
|
133
|
-
severity: 'warning' as const,
|
|
134
|
-
pattern: /useEffect\s*\([^)]*fetch\([^)]*\)/g,
|
|
135
|
-
message: 'Components fetching data should have loading states.',
|
|
136
|
-
autoFixable: false,
|
|
137
|
-
validator: (content: string) => {
|
|
138
|
-
return content.includes('fetch(') &&
|
|
139
|
-
!content.includes('isLoading') &&
|
|
140
|
-
!content.includes('loading') &&
|
|
141
|
-
!content.includes('isPending');
|
|
142
|
-
},
|
|
143
|
-
},
|
|
144
|
-
{
|
|
145
|
-
id: 'form-validation',
|
|
146
|
-
name: 'Form has validation',
|
|
147
|
-
description: 'Forms should use Zod validation',
|
|
148
|
-
severity: 'warning' as const,
|
|
149
|
-
pattern: /<form[^>]*onSubmit/gi,
|
|
150
|
-
message: 'Forms should use Zod schema validation.',
|
|
151
|
-
autoFixable: false,
|
|
152
|
-
validator: (content: string) => {
|
|
153
|
-
return content.includes('<form') &&
|
|
154
|
-
!content.includes('zodResolver') &&
|
|
155
|
-
!content.includes('z.object');
|
|
156
|
-
},
|
|
157
|
-
},
|
|
158
|
-
{
|
|
159
|
-
id: 'use-client-directive',
|
|
160
|
-
name: 'use client directive',
|
|
161
|
-
description: 'Client components should have "use client" directive',
|
|
162
|
-
severity: 'error' as const,
|
|
163
|
-
pattern: /(useState|useEffect|useReducer|useContext|useRef|useCallback|useMemo)\s*\(/g,
|
|
164
|
-
message: 'Components using hooks must have "use client" directive.',
|
|
165
|
-
autoFixable: true,
|
|
166
|
-
validator: (content: string) => {
|
|
167
|
-
const hasHooks = /(useState|useEffect|useReducer|useContext|useRef|useCallback|useMemo)\s*\(/.test(content);
|
|
168
|
-
const hasDirective = content.trim().startsWith("'use client'") || content.trim().startsWith('"use client"');
|
|
169
|
-
return hasHooks && !hasDirective;
|
|
170
|
-
},
|
|
171
|
-
},
|
|
172
|
-
{
|
|
173
|
-
id: 'key-prop-in-map',
|
|
174
|
-
name: 'Key prop in map',
|
|
175
|
-
description: 'Elements in .map() should have key prop',
|
|
176
|
-
severity: 'error' as const,
|
|
177
|
-
pattern: /\.map\s*\([^)]*\)\s*=>\s*(?:\(?\s*<[A-Z][^>]*(?!key=)[^>]*>)/g,
|
|
178
|
-
message: 'Elements in .map() must have a unique key prop.',
|
|
179
|
-
autoFixable: false,
|
|
180
|
-
},
|
|
181
|
-
];
|
|
182
|
-
|
|
183
|
-
export async function checkCommand(options: CheckOptions = {}): Promise<void> {
|
|
184
|
-
const config = new Config();
|
|
185
|
-
|
|
186
|
-
if (!config.isInProject()) {
|
|
187
|
-
p.log.error('Not in a CodeBakers project.');
|
|
188
|
-
return;
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
p.intro(chalk.bgCyan.black(' CodeBakers Pattern Check '));
|
|
192
|
-
|
|
193
|
-
const spinner = p.spinner();
|
|
194
|
-
spinner.start('Analyzing code...');
|
|
195
|
-
|
|
196
|
-
const result = await runPatternCheck(options.fix || false);
|
|
197
|
-
|
|
198
|
-
spinner.stop('Analysis complete');
|
|
199
|
-
|
|
200
|
-
// Display results
|
|
201
|
-
displayResults(result);
|
|
202
|
-
|
|
203
|
-
if (result.violations.length > 0 && options.fix) {
|
|
204
|
-
const fixable = result.violations.filter(v => v.autoFixable);
|
|
205
|
-
if (fixable.length > 0) {
|
|
206
|
-
spinner.start(`Auto-fixing ${fixable.length} violations...`);
|
|
207
|
-
await autoFix(fixable);
|
|
208
|
-
spinner.stop('Auto-fix complete');
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
// Exit with error code if there are errors
|
|
213
|
-
const errors = result.violations.filter(v => v.severity === 'error');
|
|
214
|
-
if (errors.length > 0) {
|
|
215
|
-
p.outro(chalk.red(`❌ ${errors.length} errors found. Fix before committing.`));
|
|
216
|
-
process.exit(1);
|
|
217
|
-
} else if (result.violations.length > 0) {
|
|
218
|
-
p.outro(chalk.yellow(`⚠️ ${result.violations.length} warnings. Consider fixing.`));
|
|
219
|
-
} else {
|
|
220
|
-
p.outro(chalk.green('✓ All patterns satisfied!'));
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
export async function runPatternCheck(autoFix: boolean): Promise<CheckResult> {
|
|
225
|
-
const cwd = process.cwd();
|
|
226
|
-
const violations: Violation[] = [];
|
|
227
|
-
|
|
228
|
-
// Find all TypeScript/JavaScript files
|
|
229
|
-
const files = await glob(['src/**/*.{ts,tsx,js,jsx}'], {
|
|
230
|
-
cwd,
|
|
231
|
-
ignore: ['**/node_modules/**', '**/.next/**', '**/dist/**'],
|
|
232
|
-
});
|
|
233
|
-
|
|
234
|
-
for (const file of files) {
|
|
235
|
-
const filePath = path.join(cwd, file);
|
|
236
|
-
const content = await fs.readFile(filePath, 'utf-8');
|
|
237
|
-
const lines = content.split('\n');
|
|
238
|
-
|
|
239
|
-
for (const rule of RULES) {
|
|
240
|
-
// If rule has custom validator, use it
|
|
241
|
-
if (rule.validator) {
|
|
242
|
-
// Create a fresh regex for each file
|
|
243
|
-
const regex = new RegExp(rule.pattern.source, rule.pattern.flags);
|
|
244
|
-
let match;
|
|
245
|
-
while ((match = regex.exec(content)) !== null) {
|
|
246
|
-
if (rule.validator(content, match)) {
|
|
247
|
-
const line = content.substring(0, match.index).split('\n').length;
|
|
248
|
-
violations.push({
|
|
249
|
-
file,
|
|
250
|
-
line,
|
|
251
|
-
rule: rule.id,
|
|
252
|
-
message: rule.message,
|
|
253
|
-
severity: rule.severity,
|
|
254
|
-
autoFixable: rule.autoFixable,
|
|
255
|
-
});
|
|
256
|
-
break; // One violation per rule per file
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
} else {
|
|
260
|
-
// Standard pattern matching
|
|
261
|
-
const regex = new RegExp(rule.pattern.source, rule.pattern.flags);
|
|
262
|
-
let match;
|
|
263
|
-
while ((match = regex.exec(content)) !== null) {
|
|
264
|
-
const line = content.substring(0, match.index).split('\n').length;
|
|
265
|
-
violations.push({
|
|
266
|
-
file,
|
|
267
|
-
line,
|
|
268
|
-
rule: rule.id,
|
|
269
|
-
message: rule.message,
|
|
270
|
-
severity: rule.severity,
|
|
271
|
-
autoFixable: rule.autoFixable,
|
|
272
|
-
});
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
return {
|
|
279
|
-
violations,
|
|
280
|
-
filesChecked: files.length,
|
|
281
|
-
passed: violations.length === 0,
|
|
282
|
-
};
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
function displayResults(result: CheckResult): void {
|
|
286
|
-
console.log(chalk.dim(`\nChecked ${result.filesChecked} files\n`));
|
|
287
|
-
|
|
288
|
-
if (result.violations.length === 0) {
|
|
289
|
-
console.log(chalk.green(' ✓ No violations found\n'));
|
|
290
|
-
return;
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
// Group by file
|
|
294
|
-
const byFile = new Map<string, Violation[]>();
|
|
295
|
-
for (const v of result.violations) {
|
|
296
|
-
if (!byFile.has(v.file)) {
|
|
297
|
-
byFile.set(v.file, []);
|
|
298
|
-
}
|
|
299
|
-
byFile.get(v.file)!.push(v);
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
for (const [file, fileViolations] of byFile) {
|
|
303
|
-
console.log(chalk.bold(file));
|
|
304
|
-
|
|
305
|
-
for (const v of fileViolations) {
|
|
306
|
-
const icon = v.severity === 'error' ? chalk.red('✗') : chalk.yellow('⚠');
|
|
307
|
-
const fixable = v.autoFixable ? chalk.dim(' (auto-fixable)') : '';
|
|
308
|
-
console.log(` ${icon} Line ${v.line}: ${v.message}${fixable}`);
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
console.log('');
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
// Summary
|
|
315
|
-
const errors = result.violations.filter(v => v.severity === 'error').length;
|
|
316
|
-
const warnings = result.violations.filter(v => v.severity === 'warning').length;
|
|
317
|
-
|
|
318
|
-
console.log(chalk.bold('Summary:'));
|
|
319
|
-
if (errors > 0) {
|
|
320
|
-
console.log(chalk.red(` ${errors} error(s)`));
|
|
321
|
-
}
|
|
322
|
-
if (warnings > 0) {
|
|
323
|
-
console.log(chalk.yellow(` ${warnings} warning(s)`));
|
|
324
|
-
}
|
|
325
|
-
console.log('');
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
async function autoFix(violations: Violation[]): Promise<void> {
|
|
329
|
-
const cwd = process.cwd();
|
|
330
|
-
|
|
331
|
-
// Group by file
|
|
332
|
-
const byFile = new Map<string, Violation[]>();
|
|
333
|
-
for (const v of violations) {
|
|
334
|
-
if (!byFile.has(v.file)) {
|
|
335
|
-
byFile.set(v.file, []);
|
|
336
|
-
}
|
|
337
|
-
byFile.get(v.file)!.push(v);
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
for (const [file, fileViolations] of byFile) {
|
|
341
|
-
const filePath = path.join(cwd, file);
|
|
342
|
-
let content = await fs.readFile(filePath, 'utf-8');
|
|
343
|
-
|
|
344
|
-
for (const v of fileViolations) {
|
|
345
|
-
switch (v.rule) {
|
|
346
|
-
case 'no-console-log':
|
|
347
|
-
// Remove console.log statements
|
|
348
|
-
content = content.replace(/console\.log\([^)]*\);?\n?/g, '');
|
|
349
|
-
break;
|
|
350
|
-
|
|
351
|
-
case 'use-client-directive':
|
|
352
|
-
// Add "use client" directive at the top
|
|
353
|
-
if (!content.startsWith("'use client'") && !content.startsWith('"use client"')) {
|
|
354
|
-
content = "'use client';\n\n" + content;
|
|
355
|
-
}
|
|
356
|
-
break;
|
|
357
|
-
}
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
await fs.writeFile(filePath, content);
|
|
361
|
-
}
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
// Export for use in other commands
|
|
365
|
-
export { Violation, CheckResult };
|