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.
- package/README.md +54 -255
- package/dist/chunk-HOWR3YTF.js +146 -0
- package/dist/index.d.ts +0 -3
- package/dist/index.js +10489 -7994
- 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
|
@@ -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 };
|