codebakers 1.0.45 โ†’ 2.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 (81) hide show
  1. package/README.md +275 -60
  2. package/dist/index.d.ts +1 -0
  3. package/dist/index.js +3999 -0
  4. package/install.bat +9 -0
  5. package/package.json +71 -115
  6. package/src/channels/discord.ts +5 -0
  7. package/src/channels/slack.ts +5 -0
  8. package/src/channels/sms.ts +4 -0
  9. package/src/channels/telegram.ts +5 -0
  10. package/src/channels/whatsapp.ts +7 -0
  11. package/src/commands/check.ts +365 -0
  12. package/src/commands/code.ts +684 -0
  13. package/src/commands/connect.ts +12 -0
  14. package/src/commands/deploy.ts +414 -0
  15. package/src/commands/fix.ts +20 -0
  16. package/src/commands/gateway.ts +604 -0
  17. package/src/commands/generate.ts +178 -0
  18. package/src/commands/init.ts +574 -0
  19. package/src/commands/learn.ts +36 -0
  20. package/src/commands/security.ts +102 -0
  21. package/src/commands/setup.ts +448 -0
  22. package/src/commands/status.ts +56 -0
  23. package/src/index.ts +268 -0
  24. package/src/patterns/loader.ts +337 -0
  25. package/src/services/github.ts +61 -0
  26. package/src/services/supabase.ts +147 -0
  27. package/src/services/vercel.ts +61 -0
  28. package/src/utils/claude-md.ts +287 -0
  29. package/src/utils/config.ts +282 -0
  30. package/src/utils/updates.ts +27 -0
  31. package/tsconfig.json +17 -10
  32. package/.vscodeignore +0 -18
  33. package/LICENSE +0 -21
  34. package/codebakers-1.0.0.vsix +0 -0
  35. package/codebakers-1.0.10.vsix +0 -0
  36. package/codebakers-1.0.11.vsix +0 -0
  37. package/codebakers-1.0.12.vsix +0 -0
  38. package/codebakers-1.0.13.vsix +0 -0
  39. package/codebakers-1.0.14.vsix +0 -0
  40. package/codebakers-1.0.15.vsix +0 -0
  41. package/codebakers-1.0.16.vsix +0 -0
  42. package/codebakers-1.0.17.vsix +0 -0
  43. package/codebakers-1.0.18.vsix +0 -0
  44. package/codebakers-1.0.19.vsix +0 -0
  45. package/codebakers-1.0.20.vsix +0 -0
  46. package/codebakers-1.0.21.vsix +0 -0
  47. package/codebakers-1.0.22.vsix +0 -0
  48. package/codebakers-1.0.23.vsix +0 -0
  49. package/codebakers-1.0.24.vsix +0 -0
  50. package/codebakers-1.0.25.vsix +0 -0
  51. package/codebakers-1.0.26.vsix +0 -0
  52. package/codebakers-1.0.27.vsix +0 -0
  53. package/codebakers-1.0.28.vsix +0 -0
  54. package/codebakers-1.0.29.vsix +0 -0
  55. package/codebakers-1.0.30.vsix +0 -0
  56. package/codebakers-1.0.31.vsix +0 -0
  57. package/codebakers-1.0.32.vsix +0 -0
  58. package/codebakers-1.0.35.vsix +0 -0
  59. package/codebakers-1.0.36.vsix +0 -0
  60. package/codebakers-1.0.37.vsix +0 -0
  61. package/codebakers-1.0.38.vsix +0 -0
  62. package/codebakers-1.0.39.vsix +0 -0
  63. package/codebakers-1.0.40.vsix +0 -0
  64. package/codebakers-1.0.41.vsix +0 -0
  65. package/codebakers-1.0.42.vsix +0 -0
  66. package/codebakers-1.0.43.vsix +0 -0
  67. package/codebakers-1.0.44.vsix +0 -0
  68. package/codebakers-1.0.45.vsix +0 -0
  69. package/dist/extension.js +0 -1394
  70. package/esbuild.js +0 -63
  71. package/media/icon.png +0 -0
  72. package/media/icon.svg +0 -7
  73. package/nul +0 -1
  74. package/preview.html +0 -547
  75. package/src/ChatPanelProvider.ts +0 -1815
  76. package/src/ChatViewProvider.ts +0 -749
  77. package/src/CodeBakersClient.ts +0 -1146
  78. package/src/CodeValidator.ts +0 -645
  79. package/src/FileOperations.ts +0 -410
  80. package/src/ProjectContext.ts +0 -526
  81. package/src/extension.ts +0 -332
@@ -0,0 +1,147 @@
1
+ import { Config } from '../utils/config.js';
2
+
3
+ export class SupabaseService {
4
+ private config: Config;
5
+ private accessToken: string;
6
+
7
+ constructor(config: Config) {
8
+ this.config = config;
9
+ const creds = config.getCredentials('supabase');
10
+
11
+ if (!creds?.accessToken) {
12
+ throw new Error('Supabase not configured. Run `codebakers setup`.');
13
+ }
14
+
15
+ this.accessToken = creds.accessToken;
16
+ }
17
+
18
+ async createProject(name: string): Promise<{
19
+ id: string;
20
+ name: string;
21
+ api_url: string;
22
+ anon_key: string;
23
+ }> {
24
+ // Generate a random password for the database
25
+ const dbPassword = this.generatePassword();
26
+
27
+ const response = await fetch('https://api.supabase.com/v1/projects', {
28
+ method: 'POST',
29
+ headers: {
30
+ Authorization: `Bearer ${this.accessToken}`,
31
+ 'Content-Type': 'application/json',
32
+ },
33
+ body: JSON.stringify({
34
+ name,
35
+ organization_id: await this.getDefaultOrgId(),
36
+ region: 'us-west-1',
37
+ plan: 'free',
38
+ db_pass: dbPassword,
39
+ }),
40
+ });
41
+
42
+ if (!response.ok) {
43
+ const error = await response.json();
44
+ throw new Error(error.message || 'Failed to create Supabase project');
45
+ }
46
+
47
+ const data = await response.json();
48
+
49
+ // Wait for project to be ready
50
+ await this.waitForProject(data.id);
51
+
52
+ // Get API keys
53
+ const keys = await this.getApiKeys(data.id);
54
+
55
+ return {
56
+ id: data.id,
57
+ name: data.name,
58
+ api_url: `https://${data.id}.supabase.co`,
59
+ anon_key: keys.anon_key,
60
+ };
61
+ }
62
+
63
+ private async getDefaultOrgId(): Promise<string> {
64
+ const response = await fetch('https://api.supabase.com/v1/organizations', {
65
+ headers: { Authorization: `Bearer ${this.accessToken}` },
66
+ });
67
+
68
+ if (!response.ok) {
69
+ throw new Error('Failed to get organizations');
70
+ }
71
+
72
+ const orgs = await response.json();
73
+ if (orgs.length === 0) {
74
+ throw new Error('No Supabase organization found');
75
+ }
76
+
77
+ return orgs[0].id;
78
+ }
79
+
80
+ private async waitForProject(projectId: string, maxWait = 120000): Promise<void> {
81
+ const startTime = Date.now();
82
+
83
+ while (Date.now() - startTime < maxWait) {
84
+ const response = await fetch(
85
+ `https://api.supabase.com/v1/projects/${projectId}`,
86
+ { headers: { Authorization: `Bearer ${this.accessToken}` } }
87
+ );
88
+
89
+ if (response.ok) {
90
+ const project = await response.json();
91
+ if (project.status === 'ACTIVE_HEALTHY') {
92
+ return;
93
+ }
94
+ }
95
+
96
+ await new Promise(resolve => setTimeout(resolve, 5000));
97
+ }
98
+
99
+ throw new Error('Timeout waiting for Supabase project');
100
+ }
101
+
102
+ private async getApiKeys(projectId: string): Promise<{ anon_key: string; service_role_key: string }> {
103
+ const response = await fetch(
104
+ `https://api.supabase.com/v1/projects/${projectId}/api-keys`,
105
+ { headers: { Authorization: `Bearer ${this.accessToken}` } }
106
+ );
107
+
108
+ if (!response.ok) {
109
+ throw new Error('Failed to get API keys');
110
+ }
111
+
112
+ const keys = await response.json();
113
+ const anonKey = keys.find((k: any) => k.name === 'anon');
114
+ const serviceKey = keys.find((k: any) => k.name === 'service_role');
115
+
116
+ return {
117
+ anon_key: anonKey?.api_key || '',
118
+ service_role_key: serviceKey?.api_key || '',
119
+ };
120
+ }
121
+
122
+ private generatePassword(): string {
123
+ const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%';
124
+ let password = '';
125
+ for (let i = 0; i < 24; i++) {
126
+ password += chars.charAt(Math.floor(Math.random() * chars.length));
127
+ }
128
+ return password;
129
+ }
130
+
131
+ async listProjects(): Promise<Array<{ id: string; name: string; region: string }>> {
132
+ const response = await fetch('https://api.supabase.com/v1/projects', {
133
+ headers: { Authorization: `Bearer ${this.accessToken}` },
134
+ });
135
+
136
+ if (!response.ok) {
137
+ throw new Error('Failed to list projects');
138
+ }
139
+
140
+ const projects = await response.json();
141
+ return projects.map((p: any) => ({
142
+ id: p.id,
143
+ name: p.name,
144
+ region: p.region,
145
+ }));
146
+ }
147
+ }
@@ -0,0 +1,61 @@
1
+ import { execa } from 'execa';
2
+ import { Config } from '../utils/config.js';
3
+
4
+ export class VercelService {
5
+ private config: Config;
6
+ private token: string;
7
+
8
+ constructor(config: Config) {
9
+ this.config = config;
10
+ const creds = config.getCredentials('vercel');
11
+
12
+ if (!creds?.token) {
13
+ throw new Error('Vercel not configured. Run `codebakers setup`.');
14
+ }
15
+
16
+ this.token = creds.token;
17
+ }
18
+
19
+ async createProject(name: string): Promise<{ id: string; name: string }> {
20
+ const response = await fetch('https://api.vercel.com/v9/projects', {
21
+ method: 'POST',
22
+ headers: {
23
+ Authorization: `Bearer ${this.token}`,
24
+ 'Content-Type': 'application/json',
25
+ },
26
+ body: JSON.stringify({ name, framework: 'nextjs' }),
27
+ });
28
+
29
+ if (!response.ok) {
30
+ const error = await response.json();
31
+ throw new Error(error.error?.message || 'Failed to create project');
32
+ }
33
+
34
+ const data = await response.json();
35
+ return { id: data.id, name: data.name };
36
+ }
37
+
38
+ async deploy(projectPath: string, production = false): Promise<{ url: string }> {
39
+ const args = ['vercel', '--yes'];
40
+ if (production) args.push('--prod');
41
+
42
+ const result = await execa('npx', args, {
43
+ cwd: projectPath,
44
+ env: { ...process.env, VERCEL_TOKEN: this.token },
45
+ });
46
+
47
+ const urlMatch = result.stdout.match(/https:\/\/[^\s]+\.vercel\.app/);
48
+ return { url: urlMatch ? urlMatch[0] : 'https://vercel.app' };
49
+ }
50
+
51
+ async addDomain(projectName: string, domain: string): Promise<void> {
52
+ await fetch(`https://api.vercel.com/v10/projects/${projectName}/domains`, {
53
+ method: 'POST',
54
+ headers: {
55
+ Authorization: `Bearer ${this.token}`,
56
+ 'Content-Type': 'application/json',
57
+ },
58
+ body: JSON.stringify({ name: domain }),
59
+ });
60
+ }
61
+ }
@@ -0,0 +1,287 @@
1
+ interface ProjectConfig {
2
+ name: string;
3
+ type: unknown;
4
+ framework: string;
5
+ ui: unknown;
6
+ packages: unknown;
7
+ services: unknown;
8
+ domain?: string;
9
+ }
10
+
11
+ export function generateClaudeMd(config: ProjectConfig): string {
12
+ return `# ${config.name.toUpperCase()} - CLAUDE.md
13
+
14
+ Generated by CodeBakers CLI
15
+
16
+ ---
17
+
18
+ # CORE DEVELOPMENT STANDARDS
19
+
20
+ ## ๐Ÿง  MANDATORY THINKING PROTOCOL
21
+
22
+ **BEFORE WRITING ANY CODE**, complete this mental checklist:
23
+
24
+ \`\`\`
25
+ โ–ข What is the user actually asking for?
26
+ โ–ข What are ALL the components needed (UI, API, DB, types)?
27
+ โ–ข What are the edge cases?
28
+ โ–ข What error handling is required?
29
+ โ–ข What loading/empty states are needed?
30
+ โ–ข How does this integrate with existing code?
31
+ โ–ข What security implications exist?
32
+ โ–ข What could break in production?
33
+ \`\`\`
34
+
35
+ **NEVER skip this step.**
36
+
37
+ ---
38
+
39
+ ## ๐Ÿšซ ABSOLUTE PROHIBITIONS
40
+
41
+ These will NEVER appear in your code under ANY circumstances:
42
+
43
+ \`\`\`typescript
44
+ // โŒ BANNED FOREVER - NON-FUNCTIONAL CODE
45
+ onClick={handleClick} // where handleClick doesn't exist
46
+ onSubmit={handleSubmit} // where handleSubmit doesn't exist
47
+ href="/some-page" // where the page doesn't exist
48
+
49
+ // โŒ BANNED FOREVER - INCOMPLETE CODE
50
+ TODO: // No TODOs ever
51
+ FIXME: // No FIXMEs ever
52
+ // ... // No placeholder comments
53
+ throw new Error('Not implemented')
54
+
55
+ // โŒ BANNED FOREVER - DEBUG CODE
56
+ console.log('test') // No debug logs in final code
57
+ debugger; // No debugger statements
58
+
59
+ // โŒ BANNED FOREVER - TYPE SAFETY VIOLATIONS
60
+ any // No 'any' types
61
+ @ts-ignore // No ignoring TypeScript
62
+ as any // No casting to any
63
+
64
+ // โŒ BANNED FOREVER - SECURITY VIOLATIONS
65
+ eval() // No eval ever
66
+ innerHTML = // No direct innerHTML
67
+ dangerouslySetInnerHTML // Without DOMPurify
68
+ \`\`\`
69
+
70
+ ---
71
+
72
+ ## โœ… MANDATORY PATTERNS
73
+
74
+ ### Every Button MUST Have:
75
+
76
+ \`\`\`typescript
77
+ // โœ… CORRECT - Fully functional button
78
+ <Button
79
+ onClick={handleAction}
80
+ disabled={isLoading || isDisabled}
81
+ aria-label="Descriptive action name"
82
+ aria-busy={isLoading}
83
+ >
84
+ {isLoading ? (
85
+ <>
86
+ <Loader2 className="mr-2 h-4 w-4 animate-spin" />
87
+ Processing...
88
+ </>
89
+ ) : (
90
+ 'Action Name'
91
+ )}
92
+ </Button>
93
+
94
+ // The handler MUST exist and be complete:
95
+ const handleAction = async () => {
96
+ setIsLoading(true);
97
+ try {
98
+ await performAction();
99
+ toast.success('Action completed successfully');
100
+ } catch (error) {
101
+ const message = error instanceof Error ? error.message : 'Action failed';
102
+ toast.error(message);
103
+ } finally {
104
+ setIsLoading(false);
105
+ }
106
+ };
107
+ \`\`\`
108
+
109
+ ### Every Form MUST Have:
110
+
111
+ \`\`\`typescript
112
+ 'use client';
113
+
114
+ import { useState } from 'react';
115
+ import { z } from 'zod';
116
+ import { useForm } from 'react-hook-form';
117
+ import { zodResolver } from '@hookform/resolvers/zod';
118
+ import { toast } from 'sonner';
119
+
120
+ const formSchema = z.object({
121
+ email: z.string().email('Please enter a valid email'),
122
+ name: z.string().min(1, 'Name is required').max(100),
123
+ });
124
+
125
+ type FormData = z.infer<typeof formSchema>;
126
+
127
+ export function ContactForm({ onSuccess }: { onSuccess?: () => void }) {
128
+ const [isSubmitting, setIsSubmitting] = useState(false);
129
+
130
+ const form = useForm<FormData>({
131
+ resolver: zodResolver(formSchema),
132
+ defaultValues: { email: '', name: '' },
133
+ });
134
+
135
+ const onSubmit = async (data: FormData) => {
136
+ setIsSubmitting(true);
137
+ try {
138
+ const response = await fetch('/api/contact', {
139
+ method: 'POST',
140
+ headers: { 'Content-Type': 'application/json' },
141
+ body: JSON.stringify(data),
142
+ });
143
+
144
+ if (!response.ok) {
145
+ const error = await response.json();
146
+ throw new Error(error.message || 'Failed to send');
147
+ }
148
+
149
+ toast.success('Message sent!');
150
+ form.reset();
151
+ onSuccess?.();
152
+ } catch (error) {
153
+ const message = error instanceof Error ? error.message : 'Something went wrong';
154
+ toast.error(message);
155
+ } finally {
156
+ setIsSubmitting(false);
157
+ }
158
+ };
159
+
160
+ return (
161
+ <Form {...form}>
162
+ <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4">
163
+ {/* Form fields with FormField, FormLabel, FormControl, FormMessage */}
164
+ <Button type="submit" disabled={isSubmitting}>
165
+ {isSubmitting ? 'Sending...' : 'Send Message'}
166
+ </Button>
167
+ </form>
168
+ </Form>
169
+ );
170
+ }
171
+ \`\`\`
172
+
173
+ ### Every List MUST Have:
174
+
175
+ \`\`\`typescript
176
+ interface ItemListProps {
177
+ items: Item[];
178
+ isLoading: boolean;
179
+ error: string | null;
180
+ onRetry?: () => void;
181
+ }
182
+
183
+ export function ItemList({ items, isLoading, error, onRetry }: ItemListProps) {
184
+ // Loading state
185
+ if (isLoading) {
186
+ return (
187
+ <div className="flex items-center justify-center p-8">
188
+ <Loader2 className="h-8 w-8 animate-spin text-muted-foreground" />
189
+ </div>
190
+ );
191
+ }
192
+
193
+ // Error state
194
+ if (error) {
195
+ return (
196
+ <div className="flex flex-col items-center gap-4 p-8 text-center">
197
+ <AlertCircle className="h-12 w-12 text-destructive" />
198
+ <p className="text-destructive">{error}</p>
199
+ {onRetry && <Button variant="outline" onClick={onRetry}>Try Again</Button>}
200
+ </div>
201
+ );
202
+ }
203
+
204
+ // Empty state
205
+ if (items.length === 0) {
206
+ return (
207
+ <div className="flex flex-col items-center gap-4 p-8 text-center">
208
+ <Package className="h-12 w-12 text-muted-foreground" />
209
+ <div>
210
+ <h3 className="font-medium">No items found</h3>
211
+ <p className="text-sm text-muted-foreground">Get started by creating your first item.</p>
212
+ </div>
213
+ </div>
214
+ );
215
+ }
216
+
217
+ // Success state with data
218
+ return (
219
+ <ul className="divide-y divide-border">
220
+ {items.map((item) => (
221
+ <li key={item.id} className="p-4">
222
+ {item.name}
223
+ </li>
224
+ ))}
225
+ </ul>
226
+ );
227
+ }
228
+ \`\`\`
229
+
230
+ ---
231
+
232
+ ## ๐Ÿ“ PROJECT STRUCTURE
233
+
234
+ \`\`\`
235
+ ${config.name}/
236
+ โ”œโ”€โ”€ src/
237
+ โ”‚ โ”œโ”€โ”€ app/ # Next.js App Router
238
+ โ”‚ โ”‚ โ”œโ”€โ”€ (auth)/ # Routes requiring authentication
239
+ โ”‚ โ”‚ โ”œโ”€โ”€ (public)/ # Public routes
240
+ โ”‚ โ”‚ โ”œโ”€โ”€ api/ # API routes
241
+ โ”‚ โ”‚ โ””โ”€โ”€ layout.tsx # Root layout
242
+ โ”‚ โ”œโ”€โ”€ components/
243
+ โ”‚ โ”‚ โ”œโ”€โ”€ ui/ # shadcn/ui components
244
+ โ”‚ โ”‚ โ”œโ”€โ”€ forms/ # Form components
245
+ โ”‚ โ”‚ โ””โ”€โ”€ [feature]/ # Feature-specific
246
+ โ”‚ โ”œโ”€โ”€ lib/
247
+ โ”‚ โ”‚ โ”œโ”€โ”€ supabase/ # Supabase clients
248
+ โ”‚ โ”‚ โ”œโ”€โ”€ utils.ts # Utilities
249
+ โ”‚ โ”‚ โ””โ”€โ”€ validations.ts # Zod schemas
250
+ โ”‚ โ”œโ”€โ”€ hooks/ # Custom hooks
251
+ โ”‚ โ”œโ”€โ”€ types/ # TypeScript types
252
+ โ”‚ โ”œโ”€โ”€ stores/ # Zustand stores
253
+ โ”‚ โ””โ”€โ”€ services/ # Business logic
254
+ โ”œโ”€โ”€ tests/ # Playwright tests
255
+ โ”œโ”€โ”€ .codebakers/ # CodeBakers config
256
+ โ””โ”€โ”€ CLAUDE.md # This file
257
+ \`\`\`
258
+
259
+ ---
260
+
261
+ ## ๐Ÿ” SECURITY REQUIREMENTS
262
+
263
+ 1. **Never expose secrets** - Use environment variables
264
+ 2. **Validate all inputs** - Use Zod on both client and server
265
+ 3. **Enable RLS** - Every Supabase table must have Row Level Security
266
+ 4. **Sanitize user content** - Use DOMPurify for any user HTML
267
+ 5. **Use HTTPS** - Never use HTTP in production
268
+ 6. **Rate limit APIs** - Protect public endpoints
269
+
270
+ ---
271
+
272
+ ## ๐Ÿงช TESTING REQUIREMENTS
273
+
274
+ After building ANY feature, automatically test it:
275
+
276
+ 1. Run \`codebakers check\` to verify patterns
277
+ 2. Check TypeScript: \`npx tsc --noEmit\`
278
+ 3. Run tests: \`npm test\`
279
+ 4. Fix any failures before saying "done"
280
+
281
+ ---
282
+
283
+ **END OF CLAUDE.md**
284
+
285
+ Generated by CodeBakers CLI v1.0.0
286
+ `;
287
+ }