codebakers 2.5.3 → 3.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 (60) hide show
  1. package/README.md +54 -255
  2. package/dist/chunk-HOWR3YTF.js +146 -0
  3. package/dist/index.d.ts +0 -3
  4. package/dist/index.js +10489 -7994
  5. package/dist/terminal-6ZQVP6R7.js +10 -0
  6. package/package.json +26 -41
  7. package/AUDIT_REPORT.md +0 -138
  8. package/dist/advisors-RWRTSJRR.js +0 -7
  9. package/dist/chunk-ASIJIQYC.js +0 -320
  10. package/dist/chunk-D44U3IEA.js +0 -565
  11. package/dist/chunk-LANM5XQW.js +0 -326
  12. package/dist/prd-RYITSL6Q.js +0 -7
  13. package/install.bat +0 -9
  14. package/installers/CodeBakers-Install.bat +0 -207
  15. package/installers/CodeBakers-Install.command +0 -232
  16. package/installers/README.md +0 -157
  17. package/installers/mac/assets/README.txt +0 -31
  18. package/installers/mac/build-mac-installer.sh +0 -240
  19. package/installers/windows/CodeBakers.iss +0 -256
  20. package/installers/windows/assets/README.txt +0 -16
  21. package/installers/windows/scripts/post-install.bat +0 -15
  22. package/src/channels/discord.ts +0 -5
  23. package/src/channels/slack.ts +0 -5
  24. package/src/channels/sms.ts +0 -4
  25. package/src/channels/telegram.ts +0 -5
  26. package/src/channels/whatsapp.ts +0 -7
  27. package/src/commands/advisors.ts +0 -699
  28. package/src/commands/build.ts +0 -1025
  29. package/src/commands/check.ts +0 -365
  30. package/src/commands/code.ts +0 -806
  31. package/src/commands/connect.ts +0 -12
  32. package/src/commands/deploy.ts +0 -448
  33. package/src/commands/design.ts +0 -298
  34. package/src/commands/fix.ts +0 -20
  35. package/src/commands/gateway.ts +0 -604
  36. package/src/commands/generate.ts +0 -178
  37. package/src/commands/init.ts +0 -634
  38. package/src/commands/integrate.ts +0 -884
  39. package/src/commands/learn.ts +0 -36
  40. package/src/commands/migrate.ts +0 -419
  41. package/src/commands/prd-maker.ts +0 -588
  42. package/src/commands/prd.ts +0 -419
  43. package/src/commands/security.ts +0 -102
  44. package/src/commands/setup.ts +0 -600
  45. package/src/commands/status.ts +0 -56
  46. package/src/commands/website.ts +0 -741
  47. package/src/index.ts +0 -627
  48. package/src/patterns/loader.ts +0 -337
  49. package/src/services/github.ts +0 -61
  50. package/src/services/supabase.ts +0 -147
  51. package/src/services/vercel.ts +0 -61
  52. package/src/utils/claude-md.ts +0 -287
  53. package/src/utils/config.ts +0 -375
  54. package/src/utils/display.ts +0 -338
  55. package/src/utils/files.ts +0 -418
  56. package/src/utils/nlp.ts +0 -312
  57. package/src/utils/ui.ts +0 -441
  58. package/src/utils/updates.ts +0 -8
  59. package/src/utils/voice.ts +0 -323
  60. package/tsconfig.json +0 -26
@@ -1,884 +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 open from 'open';
6
- import { Config } from '../utils/config.js';
7
- import { execa } from 'execa';
8
-
9
- // ============================================================================
10
- // INTEGRATION LIBRARY - 50+ One-Click Integrations
11
- // ============================================================================
12
-
13
- interface Integration {
14
- id: string;
15
- name: string;
16
- description: string;
17
- category: string;
18
- icon: string;
19
- dashboardUrl: string;
20
- envVars: string[];
21
- envVarHints?: Record<string, string>;
22
- packages?: string[];
23
- docs: string;
24
- steps: string[];
25
- }
26
-
27
- const INTEGRATIONS: Integration[] = [
28
- // ═══════════════════════════════════════════════════════════════════════════
29
- // AUTH
30
- // ═══════════════════════════════════════════════════════════════════════════
31
- {
32
- id: 'clerk',
33
- name: 'Clerk',
34
- description: 'User management & authentication',
35
- category: 'auth',
36
- icon: '🔐',
37
- dashboardUrl: 'https://dashboard.clerk.com',
38
- envVars: ['NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY', 'CLERK_SECRET_KEY'],
39
- envVarHints: {
40
- 'NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY': 'pk_test_... or pk_live_...',
41
- 'CLERK_SECRET_KEY': 'sk_test_... or sk_live_...',
42
- },
43
- packages: ['@clerk/nextjs'],
44
- docs: 'https://clerk.com/docs',
45
- steps: [
46
- 'Sign up or log in at dashboard.clerk.com',
47
- 'Create a new application',
48
- 'Go to API Keys in the sidebar',
49
- 'Copy Publishable Key and Secret Key',
50
- ],
51
- },
52
- {
53
- id: 'supabase-auth',
54
- name: 'Supabase Auth',
55
- description: 'Auth with email, social, magic links',
56
- category: 'auth',
57
- icon: '⚡',
58
- dashboardUrl: 'https://supabase.com/dashboard',
59
- envVars: ['NEXT_PUBLIC_SUPABASE_URL', 'NEXT_PUBLIC_SUPABASE_ANON_KEY'],
60
- envVarHints: {
61
- 'NEXT_PUBLIC_SUPABASE_URL': 'https://xxx.supabase.co',
62
- 'NEXT_PUBLIC_SUPABASE_ANON_KEY': 'eyJ... (anon public key)',
63
- },
64
- packages: ['@supabase/supabase-js', '@supabase/auth-helpers-nextjs'],
65
- docs: 'https://supabase.com/docs/guides/auth',
66
- steps: [
67
- 'Sign in at supabase.com/dashboard',
68
- 'Create or select a project',
69
- 'Go to Settings > API',
70
- 'Copy Project URL and anon/public key',
71
- ],
72
- },
73
- {
74
- id: 'nextauth',
75
- name: 'NextAuth.js',
76
- description: 'Open source auth for Next.js',
77
- category: 'auth',
78
- icon: '🔑',
79
- dashboardUrl: 'https://next-auth.js.org',
80
- envVars: ['NEXTAUTH_SECRET', 'NEXTAUTH_URL'],
81
- envVarHints: {
82
- 'NEXTAUTH_SECRET': 'Run: openssl rand -base64 32',
83
- 'NEXTAUTH_URL': 'http://localhost:3000',
84
- },
85
- packages: ['next-auth'],
86
- docs: 'https://next-auth.js.org',
87
- steps: [
88
- 'No signup needed - open source!',
89
- 'Generate secret: openssl rand -base64 32',
90
- 'Set URL to your app (localhost for dev)',
91
- ],
92
- },
93
-
94
- // ═══════════════════════════════════════════════════════════════════════════
95
- // DATABASE
96
- // ═══════════════════════════════════════════════════════════════════════════
97
- {
98
- id: 'supabase',
99
- name: 'Supabase',
100
- description: 'Postgres + Realtime + Auth + Storage',
101
- category: 'database',
102
- icon: '⚡',
103
- dashboardUrl: 'https://supabase.com/dashboard',
104
- envVars: ['NEXT_PUBLIC_SUPABASE_URL', 'NEXT_PUBLIC_SUPABASE_ANON_KEY', 'SUPABASE_SERVICE_ROLE_KEY'],
105
- envVarHints: {
106
- 'NEXT_PUBLIC_SUPABASE_URL': 'https://xxx.supabase.co',
107
- 'NEXT_PUBLIC_SUPABASE_ANON_KEY': 'eyJ... (anon key)',
108
- 'SUPABASE_SERVICE_ROLE_KEY': 'eyJ... (service_role key - keep secret!)',
109
- },
110
- packages: ['@supabase/supabase-js'],
111
- docs: 'https://supabase.com/docs',
112
- steps: [
113
- 'Sign in at supabase.com/dashboard',
114
- 'Create a new project',
115
- 'Go to Settings > API',
116
- 'Copy URL, anon key, and service_role key',
117
- ],
118
- },
119
- {
120
- id: 'neon',
121
- name: 'Neon',
122
- description: 'Serverless Postgres',
123
- category: 'database',
124
- icon: '🐘',
125
- dashboardUrl: 'https://console.neon.tech',
126
- envVars: ['DATABASE_URL'],
127
- envVarHints: {
128
- 'DATABASE_URL': 'postgres://user:pass@xxx.neon.tech/db?sslmode=require',
129
- },
130
- packages: ['@neondatabase/serverless'],
131
- docs: 'https://neon.tech/docs',
132
- steps: [
133
- 'Sign in at console.neon.tech',
134
- 'Create a project',
135
- 'Go to Dashboard > Connection Details',
136
- 'Copy the connection string',
137
- ],
138
- },
139
- {
140
- id: 'planetscale',
141
- name: 'PlanetScale',
142
- description: 'Serverless MySQL',
143
- category: 'database',
144
- icon: '🪐',
145
- dashboardUrl: 'https://app.planetscale.com',
146
- envVars: ['DATABASE_URL'],
147
- envVarHints: {
148
- 'DATABASE_URL': 'mysql://user:pass@xxx.psdb.cloud/db?sslaccept=strict',
149
- },
150
- packages: ['@planetscale/database'],
151
- docs: 'https://planetscale.com/docs',
152
- steps: [
153
- 'Sign in at app.planetscale.com',
154
- 'Create a database',
155
- 'Go to Connect > Create password',
156
- 'Copy the connection string',
157
- ],
158
- },
159
- {
160
- id: 'prisma',
161
- name: 'Prisma',
162
- description: 'Type-safe ORM',
163
- category: 'database',
164
- icon: '🔷',
165
- dashboardUrl: 'https://prisma.io',
166
- envVars: ['DATABASE_URL'],
167
- envVarHints: {
168
- 'DATABASE_URL': 'Your database connection string',
169
- },
170
- packages: ['prisma', '@prisma/client'],
171
- docs: 'https://prisma.io/docs',
172
- steps: [
173
- 'No account needed - Prisma is open source!',
174
- 'Use your existing database URL',
175
- 'Run: npx prisma init',
176
- ],
177
- },
178
-
179
- // ═══════════════════════════════════════════════════════════════════════════
180
- // PAYMENTS
181
- // ═══════════════════════════════════════════════════════════════════════════
182
- {
183
- id: 'stripe',
184
- name: 'Stripe',
185
- description: 'Payments & subscriptions',
186
- category: 'payments',
187
- icon: '💳',
188
- dashboardUrl: 'https://dashboard.stripe.com/apikeys',
189
- envVars: ['STRIPE_SECRET_KEY', 'NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY', 'STRIPE_WEBHOOK_SECRET'],
190
- envVarHints: {
191
- 'STRIPE_SECRET_KEY': 'sk_test_... or sk_live_...',
192
- 'NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY': 'pk_test_... or pk_live_...',
193
- 'STRIPE_WEBHOOK_SECRET': 'whsec_... (from Webhooks page)',
194
- },
195
- packages: ['stripe', '@stripe/stripe-js'],
196
- docs: 'https://stripe.com/docs',
197
- steps: [
198
- 'Sign in at dashboard.stripe.com',
199
- 'Go to Developers > API keys',
200
- 'Copy Publishable and Secret keys',
201
- 'For webhooks: Developers > Webhooks > Add endpoint',
202
- ],
203
- },
204
- {
205
- id: 'lemonsqueezy',
206
- name: 'Lemon Squeezy',
207
- description: 'Payments with tax handling (MoR)',
208
- category: 'payments',
209
- icon: '🍋',
210
- dashboardUrl: 'https://app.lemonsqueezy.com/settings/api',
211
- envVars: ['LEMONSQUEEZY_API_KEY', 'LEMONSQUEEZY_STORE_ID', 'LEMONSQUEEZY_WEBHOOK_SECRET'],
212
- envVarHints: {
213
- 'LEMONSQUEEZY_API_KEY': 'From Settings > API',
214
- 'LEMONSQUEEZY_STORE_ID': 'Your store ID number',
215
- 'LEMONSQUEEZY_WEBHOOK_SECRET': 'From Settings > Webhooks',
216
- },
217
- packages: ['@lemonsqueezy/lemonsqueezy.js'],
218
- docs: 'https://docs.lemonsqueezy.com',
219
- steps: [
220
- 'Sign in at app.lemonsqueezy.com',
221
- 'Go to Settings > API',
222
- 'Create an API key',
223
- 'Note your Store ID from the URL',
224
- ],
225
- },
226
-
227
- // ═══════════════════════════════════════════════════════════════════════════
228
- // EMAIL
229
- // ═══════════════════════════════════════════════════════════════════════════
230
- {
231
- id: 'resend',
232
- name: 'Resend',
233
- description: 'Modern email API',
234
- category: 'email',
235
- icon: '📧',
236
- dashboardUrl: 'https://resend.com/api-keys',
237
- envVars: ['RESEND_API_KEY'],
238
- envVarHints: {
239
- 'RESEND_API_KEY': 're_...',
240
- },
241
- packages: ['resend'],
242
- docs: 'https://resend.com/docs',
243
- steps: [
244
- 'Sign up at resend.com',
245
- 'Go to API Keys',
246
- 'Create a new API key',
247
- 'Copy the key (only shown once!)',
248
- ],
249
- },
250
- {
251
- id: 'sendgrid',
252
- name: 'SendGrid',
253
- description: 'Email delivery service',
254
- category: 'email',
255
- icon: '📨',
256
- dashboardUrl: 'https://app.sendgrid.com/settings/api_keys',
257
- envVars: ['SENDGRID_API_KEY'],
258
- envVarHints: {
259
- 'SENDGRID_API_KEY': 'SG.xxx...',
260
- },
261
- packages: ['@sendgrid/mail'],
262
- docs: 'https://docs.sendgrid.com',
263
- steps: [
264
- 'Sign in at app.sendgrid.com',
265
- 'Go to Settings > API Keys',
266
- 'Create an API key with Mail Send permission',
267
- 'Copy the key (only shown once!)',
268
- ],
269
- },
270
-
271
- // ═══════════════════════════════════════════════════════════════════════════
272
- // STORAGE
273
- // ═══════════════════════════════════════════════════════════════════════════
274
- {
275
- id: 'uploadthing',
276
- name: 'UploadThing',
277
- description: 'File uploads for Next.js',
278
- category: 'storage',
279
- icon: '📤',
280
- dashboardUrl: 'https://uploadthing.com/dashboard',
281
- envVars: ['UPLOADTHING_SECRET', 'UPLOADTHING_APP_ID'],
282
- envVarHints: {
283
- 'UPLOADTHING_SECRET': 'sk_live_...',
284
- 'UPLOADTHING_APP_ID': 'Your app ID',
285
- },
286
- packages: ['uploadthing', '@uploadthing/react'],
287
- docs: 'https://docs.uploadthing.com',
288
- steps: [
289
- 'Sign in at uploadthing.com',
290
- 'Create or select an app',
291
- 'Go to API Keys',
292
- 'Copy Secret and App ID',
293
- ],
294
- },
295
- {
296
- id: 'cloudinary',
297
- name: 'Cloudinary',
298
- description: 'Image & video management',
299
- category: 'storage',
300
- icon: '☁️',
301
- dashboardUrl: 'https://console.cloudinary.com/settings/api-keys',
302
- envVars: ['CLOUDINARY_CLOUD_NAME', 'CLOUDINARY_API_KEY', 'CLOUDINARY_API_SECRET'],
303
- envVarHints: {
304
- 'CLOUDINARY_CLOUD_NAME': 'Your cloud name',
305
- 'CLOUDINARY_API_KEY': 'Numeric API key',
306
- 'CLOUDINARY_API_SECRET': 'API Secret',
307
- },
308
- packages: ['cloudinary'],
309
- docs: 'https://cloudinary.com/documentation',
310
- steps: [
311
- 'Sign in at cloudinary.com',
312
- 'Go to Settings > API Keys',
313
- 'Copy Cloud Name, API Key, API Secret',
314
- ],
315
- },
316
-
317
- // ═══════════════════════════════════════════════════════════════════════════
318
- // AI
319
- // ═══════════════════════════════════════════════════════════════════════════
320
- {
321
- id: 'openai',
322
- name: 'OpenAI',
323
- description: 'GPT-4, DALL-E, Whisper',
324
- category: 'ai',
325
- icon: '🤖',
326
- dashboardUrl: 'https://platform.openai.com/api-keys',
327
- envVars: ['OPENAI_API_KEY'],
328
- envVarHints: {
329
- 'OPENAI_API_KEY': 'sk-...',
330
- },
331
- packages: ['openai'],
332
- docs: 'https://platform.openai.com/docs',
333
- steps: [
334
- 'Sign in at platform.openai.com',
335
- 'Go to API Keys',
336
- 'Create new secret key',
337
- 'Copy it (only shown once!)',
338
- ],
339
- },
340
- {
341
- id: 'anthropic',
342
- name: 'Anthropic',
343
- description: 'Claude AI models',
344
- category: 'ai',
345
- icon: '🧠',
346
- dashboardUrl: 'https://console.anthropic.com/settings/keys',
347
- envVars: ['ANTHROPIC_API_KEY'],
348
- envVarHints: {
349
- 'ANTHROPIC_API_KEY': 'sk-ant-...',
350
- },
351
- packages: ['@anthropic-ai/sdk'],
352
- docs: 'https://docs.anthropic.com',
353
- steps: [
354
- 'Sign in at console.anthropic.com',
355
- 'Go to API Keys',
356
- 'Create a new key',
357
- 'Copy it (only shown once!)',
358
- ],
359
- },
360
- {
361
- id: 'replicate',
362
- name: 'Replicate',
363
- description: 'Run ML models in the cloud',
364
- category: 'ai',
365
- icon: '🔄',
366
- dashboardUrl: 'https://replicate.com/account/api-tokens',
367
- envVars: ['REPLICATE_API_TOKEN'],
368
- envVarHints: {
369
- 'REPLICATE_API_TOKEN': 'r8_...',
370
- },
371
- packages: ['replicate'],
372
- docs: 'https://replicate.com/docs',
373
- steps: [
374
- 'Sign in at replicate.com',
375
- 'Go to Account > API Tokens',
376
- 'Create a token',
377
- ],
378
- },
379
-
380
- // ═══════════════════════════════════════════════════════════════════════════
381
- // ANALYTICS
382
- // ═══════════════════════════════════════════════════════════════════════════
383
- {
384
- id: 'posthog',
385
- name: 'PostHog',
386
- description: 'Product analytics & feature flags',
387
- category: 'analytics',
388
- icon: '🦔',
389
- dashboardUrl: 'https://app.posthog.com/project/settings',
390
- envVars: ['NEXT_PUBLIC_POSTHOG_KEY', 'NEXT_PUBLIC_POSTHOG_HOST'],
391
- envVarHints: {
392
- 'NEXT_PUBLIC_POSTHOG_KEY': 'phc_...',
393
- 'NEXT_PUBLIC_POSTHOG_HOST': 'https://app.posthog.com (or your self-hosted URL)',
394
- },
395
- packages: ['posthog-js'],
396
- docs: 'https://posthog.com/docs',
397
- steps: [
398
- 'Sign up at posthog.com',
399
- 'Create or select a project',
400
- 'Go to Project Settings',
401
- 'Copy Project API Key',
402
- ],
403
- },
404
- {
405
- id: 'vercel-analytics',
406
- name: 'Vercel Analytics',
407
- description: 'Web analytics by Vercel',
408
- category: 'analytics',
409
- icon: '▲',
410
- dashboardUrl: 'https://vercel.com/dashboard',
411
- envVars: [],
412
- packages: ['@vercel/analytics'],
413
- docs: 'https://vercel.com/docs/analytics',
414
- steps: [
415
- 'No API key needed!',
416
- 'Just install the package',
417
- 'Add <Analytics /> to your layout',
418
- 'Deploy to Vercel to see data',
419
- ],
420
- },
421
-
422
- // ═══════════════════════════════════════════════════════════════════════════
423
- // MONITORING
424
- // ═══════════════════════════════════════════════════════════════════════════
425
- {
426
- id: 'sentry',
427
- name: 'Sentry',
428
- description: 'Error tracking & performance',
429
- category: 'monitoring',
430
- icon: '🐛',
431
- dashboardUrl: 'https://sentry.io/settings/account/api/auth-tokens/',
432
- envVars: ['SENTRY_DSN', 'SENTRY_AUTH_TOKEN'],
433
- envVarHints: {
434
- 'SENTRY_DSN': 'https://xxx@xxx.ingest.sentry.io/xxx',
435
- 'SENTRY_AUTH_TOKEN': 'From Organization Auth Tokens',
436
- },
437
- packages: ['@sentry/nextjs'],
438
- docs: 'https://docs.sentry.io',
439
- steps: [
440
- 'Sign up at sentry.io',
441
- 'Create a project (Next.js)',
442
- 'Copy DSN from Project Settings > Client Keys',
443
- 'Create auth token in Settings > Auth Tokens',
444
- ],
445
- },
446
-
447
- // ═══════════════════════════════════════════════════════════════════════════
448
- // MESSAGING
449
- // ═══════════════════════════════════════════════════════════════════════════
450
- {
451
- id: 'twilio',
452
- name: 'Twilio',
453
- description: 'SMS, voice & WhatsApp',
454
- category: 'messaging',
455
- icon: '📱',
456
- dashboardUrl: 'https://console.twilio.com',
457
- envVars: ['TWILIO_ACCOUNT_SID', 'TWILIO_AUTH_TOKEN', 'TWILIO_PHONE_NUMBER'],
458
- envVarHints: {
459
- 'TWILIO_ACCOUNT_SID': 'AC... (from Console Dashboard)',
460
- 'TWILIO_AUTH_TOKEN': 'From Console Dashboard (click to reveal)',
461
- 'TWILIO_PHONE_NUMBER': '+1234567890 (buy in Phone Numbers)',
462
- },
463
- packages: ['twilio'],
464
- docs: 'https://www.twilio.com/docs',
465
- steps: [
466
- 'Sign up at twilio.com',
467
- 'Go to Console Dashboard',
468
- 'Copy Account SID and Auth Token',
469
- 'Buy a phone number in Phone Numbers > Manage',
470
- ],
471
- },
472
- {
473
- id: 'pusher',
474
- name: 'Pusher',
475
- description: 'Realtime websockets',
476
- category: 'messaging',
477
- icon: '🔔',
478
- dashboardUrl: 'https://dashboard.pusher.com',
479
- envVars: ['PUSHER_APP_ID', 'PUSHER_KEY', 'PUSHER_SECRET', 'NEXT_PUBLIC_PUSHER_KEY', 'PUSHER_CLUSTER'],
480
- envVarHints: {
481
- 'PUSHER_APP_ID': 'App ID from App Keys',
482
- 'PUSHER_KEY': 'Key from App Keys',
483
- 'PUSHER_SECRET': 'Secret from App Keys',
484
- 'NEXT_PUBLIC_PUSHER_KEY': 'Same as PUSHER_KEY',
485
- 'PUSHER_CLUSTER': 'e.g., us2, eu, ap1',
486
- },
487
- packages: ['pusher', 'pusher-js'],
488
- docs: 'https://pusher.com/docs',
489
- steps: [
490
- 'Sign up at pusher.com',
491
- 'Create a Channels app',
492
- 'Go to App Keys',
493
- 'Copy all credentials',
494
- ],
495
- },
496
-
497
- // ═══════════════════════════════════════════════════════════════════════════
498
- // DEPLOYMENT
499
- // ═══════════════════════════════════════════════════════════════════════════
500
- {
501
- id: 'vercel',
502
- name: 'Vercel',
503
- description: 'Deploy Next.js apps',
504
- category: 'deployment',
505
- icon: '▲',
506
- dashboardUrl: 'https://vercel.com/account/tokens',
507
- envVars: ['VERCEL_TOKEN'],
508
- envVarHints: {
509
- 'VERCEL_TOKEN': 'From Account Settings > Tokens',
510
- },
511
- packages: ['vercel'],
512
- docs: 'https://vercel.com/docs',
513
- steps: [
514
- 'Sign in at vercel.com',
515
- 'Go to Account Settings > Tokens',
516
- 'Create a new token',
517
- 'Copy it',
518
- ],
519
- },
520
- {
521
- id: 'github',
522
- name: 'GitHub',
523
- description: 'Code hosting & CI/CD',
524
- category: 'deployment',
525
- icon: '🐙',
526
- dashboardUrl: 'https://github.com/settings/tokens',
527
- envVars: ['GITHUB_TOKEN'],
528
- envVarHints: {
529
- 'GITHUB_TOKEN': 'ghp_... or github_pat_...',
530
- },
531
- packages: ['octokit'],
532
- docs: 'https://docs.github.com',
533
- steps: [
534
- 'Sign in at github.com',
535
- 'Go to Settings > Developer settings > Personal access tokens',
536
- 'Generate new token (classic)',
537
- 'Select scopes: repo, user',
538
- 'Copy the token',
539
- ],
540
- },
541
-
542
- // ═══════════════════════════════════════════════════════════════════════════
543
- // CMS
544
- // ═══════════════════════════════════════════════════════════════════════════
545
- {
546
- id: 'sanity',
547
- name: 'Sanity',
548
- description: 'Headless CMS',
549
- category: 'cms',
550
- icon: '📝',
551
- dashboardUrl: 'https://www.sanity.io/manage',
552
- envVars: ['NEXT_PUBLIC_SANITY_PROJECT_ID', 'NEXT_PUBLIC_SANITY_DATASET', 'SANITY_API_TOKEN'],
553
- envVarHints: {
554
- 'NEXT_PUBLIC_SANITY_PROJECT_ID': 'From project settings',
555
- 'NEXT_PUBLIC_SANITY_DATASET': 'Usually "production"',
556
- 'SANITY_API_TOKEN': 'From API > Tokens',
557
- },
558
- packages: ['@sanity/client', 'next-sanity'],
559
- docs: 'https://www.sanity.io/docs',
560
- steps: [
561
- 'Sign in at sanity.io/manage',
562
- 'Create or select a project',
563
- 'Copy Project ID from settings',
564
- 'Create API token in API > Tokens',
565
- ],
566
- },
567
- ];
568
-
569
- // ============================================================================
570
- // MAIN COMMAND
571
- // ============================================================================
572
-
573
- export async function integrateCommand(integrationId?: string): Promise<void> {
574
- console.log(chalk.cyan(`
575
- ╔═══════════════════════════════════════════════════════════════╗
576
- ║ 🔌 ONE-CLICK INTEGRATIONS ║
577
- ║ ║
578
- ║ ${INTEGRATIONS.length} services • Step-by-step guidance • Auto-setup ║
579
- ╚═══════════════════════════════════════════════════════════════╝
580
- `));
581
-
582
- // Direct install if ID provided
583
- if (integrationId) {
584
- const integration = INTEGRATIONS.find(i => i.id === integrationId);
585
- if (!integration) {
586
- p.log.error(`Unknown integration: ${integrationId}`);
587
- console.log(chalk.dim(`\nAvailable: ${INTEGRATIONS.map(i => i.id).join(', ')}`));
588
- return;
589
- }
590
- await installIntegration(integration);
591
- return;
592
- }
593
-
594
- // Category selection
595
- const categories = [...new Set(INTEGRATIONS.map(i => i.category))];
596
-
597
- const categoryLabels: Record<string, string> = {
598
- auth: '🔐 Authentication',
599
- database: '🗄️ Database',
600
- payments: '💳 Payments',
601
- email: '📧 Email',
602
- storage: '📦 Storage',
603
- ai: '🤖 AI & ML',
604
- analytics: '📊 Analytics',
605
- monitoring: '🐛 Monitoring',
606
- messaging: '💬 Messaging',
607
- deployment: '🚀 Deployment',
608
- cms: '📝 CMS',
609
- };
610
-
611
- const category = await p.select({
612
- message: 'Choose a category:',
613
- options: [
614
- { value: 'all', label: '📋 Show all integrations' },
615
- { value: 'search', label: '🔍 Search by name' },
616
- ...categories.map(c => ({
617
- value: c,
618
- label: categoryLabels[c] || c,
619
- hint: `${INTEGRATIONS.filter(i => i.category === c).length} services`,
620
- })),
621
- ],
622
- });
623
-
624
- if (p.isCancel(category)) return;
625
-
626
- let filtered = INTEGRATIONS;
627
-
628
- if (category === 'search') {
629
- const query = await p.text({
630
- message: 'Search:',
631
- placeholder: 'stripe, supabase, openai...',
632
- });
633
- if (p.isCancel(query)) return;
634
-
635
- const q = (query as string).toLowerCase();
636
- filtered = INTEGRATIONS.filter(i =>
637
- i.name.toLowerCase().includes(q) ||
638
- i.description.toLowerCase().includes(q) ||
639
- i.id.includes(q)
640
- );
641
-
642
- if (filtered.length === 0) {
643
- p.log.warn('No integrations found');
644
- return;
645
- }
646
- } else if (category !== 'all') {
647
- filtered = INTEGRATIONS.filter(i => i.category === category);
648
- }
649
-
650
- // Select integration
651
- const selected = await p.select({
652
- message: 'Select integration:',
653
- options: filtered.map(i => ({
654
- value: i.id,
655
- label: `${i.icon} ${i.name}`,
656
- hint: i.description,
657
- })),
658
- });
659
-
660
- if (p.isCancel(selected)) return;
661
-
662
- const integration = INTEGRATIONS.find(i => i.id === selected)!;
663
- await installIntegration(integration);
664
- }
665
-
666
- // ============================================================================
667
- // INSTALL INTEGRATION
668
- // ============================================================================
669
-
670
- async function installIntegration(integration: Integration): Promise<void> {
671
- console.log(chalk.cyan(`
672
- ┌─────────────────────────────────────────────────────────────
673
- │ ${integration.icon} Installing ${integration.name}
674
- └─────────────────────────────────────────────────────────────
675
- `));
676
-
677
- // STEP 1: Install packages
678
- if (integration.packages && integration.packages.length > 0) {
679
- const spinner = p.spinner();
680
- spinner.start(`Installing ${integration.packages.join(', ')}...`);
681
-
682
- try {
683
- await execa('npm', ['install', ...integration.packages], {
684
- cwd: process.cwd(),
685
- reject: false,
686
- });
687
- spinner.stop(chalk.green('✓ Packages installed'));
688
- } catch {
689
- spinner.stop(chalk.yellow('⚠ Package install had issues (may already be installed)'));
690
- }
691
- }
692
-
693
- // STEP 2: Get credentials
694
- if (integration.envVars.length > 0) {
695
- // Show step-by-step instructions
696
- console.log(chalk.cyan(`
697
- ┌─────────────────────────────────────────────────────────────
698
- │ 📋 HOW TO GET YOUR API KEYS
699
- └─────────────────────────────────────────────────────────────
700
- `));
701
-
702
- integration.steps.forEach((step, i) => {
703
- console.log(chalk.white(` ${i + 1}. ${step}`));
704
- });
705
-
706
- console.log(chalk.dim(`
707
- Dashboard: ${integration.dashboardUrl}
708
- Docs: ${integration.docs}
709
- `));
710
-
711
- // Offer to open dashboard
712
- const openDashboard = await p.confirm({
713
- message: `Open ${integration.name} dashboard in browser?`,
714
- initialValue: true,
715
- });
716
-
717
- if (openDashboard && !p.isCancel(openDashboard)) {
718
- await open(integration.dashboardUrl);
719
- console.log(chalk.dim(`\n ✓ Browser opened! Get your keys and come back.\n`));
720
- await sleep(2000);
721
- }
722
-
723
- // Collect credentials
724
- console.log(chalk.cyan(`\n Enter your credentials:\n`));
725
-
726
- const credentials: Record<string, string> = {};
727
-
728
- for (const envVar of integration.envVars) {
729
- const hint = integration.envVarHints?.[envVar] || 'Paste here...';
730
- const isPublic = envVar.startsWith('NEXT_PUBLIC_');
731
- const label = isPublic
732
- ? chalk.yellow('(public)')
733
- : chalk.green('(secret)');
734
-
735
- const value = await p.text({
736
- message: `${envVar} ${label}`,
737
- placeholder: hint,
738
- validate: (v) => !v ? 'Required' : undefined,
739
- });
740
-
741
- if (p.isCancel(value)) return;
742
- credentials[envVar] = value as string;
743
- }
744
-
745
- // Save to .env.local
746
- await saveEnvVars(credentials);
747
- console.log(chalk.green(`\n ✓ Saved to .env.local\n`));
748
- }
749
-
750
- // STEP 3: Generate setup code
751
- const spinner = p.spinner();
752
- spinner.start('Creating setup file...');
753
-
754
- await generateSetupCode(integration);
755
-
756
- spinner.stop(chalk.green('✓ Setup complete'));
757
-
758
- // Success!
759
- console.log(chalk.green(`
760
- ╔═══════════════════════════════════════════════════════════════╗
761
- ║ ✅ ${integration.name} installed!
762
- ╠═══════════════════════════════════════════════════════════════╣
763
- ║ ║
764
- ║ Import: import { ... } from '@/lib/${integration.id}'
765
- ║ Docs: ${integration.docs.substring(0, 45).padEnd(45)}║
766
- ║ ║
767
- ╚═══════════════════════════════════════════════════════════════╝
768
- `));
769
- }
770
-
771
- // ============================================================================
772
- // HELPERS
773
- // ============================================================================
774
-
775
- async function saveEnvVars(vars: Record<string, string>): Promise<void> {
776
- const envPath = path.join(process.cwd(), '.env.local');
777
- let content = '';
778
-
779
- if (await fs.pathExists(envPath)) {
780
- content = await fs.readFile(envPath, 'utf-8');
781
- if (!content.endsWith('\n')) content += '\n';
782
- }
783
-
784
- content += '\n# Added by CodeBakers\n';
785
-
786
- for (const [key, value] of Object.entries(vars)) {
787
- const regex = new RegExp(`^${key}=.*$`, 'm');
788
- if (regex.test(content)) {
789
- content = content.replace(regex, `${key}=${value}`);
790
- } else {
791
- content += `${key}=${value}\n`;
792
- }
793
- }
794
-
795
- await fs.writeFile(envPath, content);
796
- }
797
-
798
- async function generateSetupCode(integration: Integration): Promise<void> {
799
- const libDir = path.join(process.cwd(), 'src', 'lib');
800
- await fs.ensureDir(libDir);
801
-
802
- let code = '';
803
-
804
- switch (integration.id) {
805
- case 'supabase':
806
- case 'supabase-auth':
807
- code = `import { createClient } from '@supabase/supabase-js';
808
-
809
- const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL!;
810
- const supabaseAnonKey = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!;
811
-
812
- export const supabase = createClient(supabaseUrl, supabaseAnonKey);
813
- `;
814
- break;
815
-
816
- case 'stripe':
817
- code = `import Stripe from 'stripe';
818
-
819
- export const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, {
820
- apiVersion: '2023-10-16',
821
- });
822
- `;
823
- break;
824
-
825
- case 'resend':
826
- code = `import { Resend } from 'resend';
827
-
828
- export const resend = new Resend(process.env.RESEND_API_KEY);
829
- `;
830
- break;
831
-
832
- case 'openai':
833
- code = `import OpenAI from 'openai';
834
-
835
- export const openai = new OpenAI({
836
- apiKey: process.env.OPENAI_API_KEY,
837
- });
838
- `;
839
- break;
840
-
841
- case 'anthropic':
842
- code = `import Anthropic from '@anthropic-ai/sdk';
843
-
844
- export const anthropic = new Anthropic({
845
- apiKey: process.env.ANTHROPIC_API_KEY,
846
- });
847
- `;
848
- break;
849
-
850
- case 'clerk':
851
- code = `// Clerk is configured via middleware
852
- // See: https://clerk.com/docs/quickstarts/nextjs
853
-
854
- // In middleware.ts:
855
- // import { clerkMiddleware } from '@clerk/nextjs/server';
856
- // export default clerkMiddleware();
857
-
858
- // In layout.tsx:
859
- // import { ClerkProvider } from '@clerk/nextjs';
860
- // <ClerkProvider>{children}</ClerkProvider>
861
-
862
- export {};
863
- `;
864
- break;
865
-
866
- default:
867
- code = `// ${integration.name}
868
- // Docs: ${integration.docs}
869
- //
870
- // Environment variables:
871
- ${integration.envVars.map(v => `// - ${v}`).join('\n')}
872
-
873
- export {};
874
- `;
875
- }
876
-
877
- await fs.writeFile(path.join(libDir, `${integration.id}.ts`), code);
878
- }
879
-
880
- function sleep(ms: number): Promise<void> {
881
- return new Promise(resolve => setTimeout(resolve, ms));
882
- }
883
-
884
- export { INTEGRATIONS, Integration };