@girardmedia/bootspring 1.2.0 → 2.0.3
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 +107 -14
- package/bin/bootspring.js +166 -27
- package/cli/agent.js +189 -17
- package/cli/analyze.js +499 -0
- package/cli/audit.js +557 -0
- package/cli/auth.js +495 -38
- package/cli/billing.js +302 -0
- package/cli/build.js +695 -0
- package/cli/business.js +109 -26
- package/cli/checkpoint-utils.js +168 -0
- package/cli/checkpoint.js +639 -0
- package/cli/cloud-sync.js +447 -0
- package/cli/content.js +198 -0
- package/cli/context.js +1 -1
- package/cli/deploy.js +543 -0
- package/cli/fundraise.js +112 -50
- package/cli/github-cmd.js +435 -0
- package/cli/health.js +477 -0
- package/cli/init.js +84 -13
- package/cli/legal.js +107 -95
- package/cli/log.js +2 -2
- package/cli/loop.js +976 -73
- package/cli/manager.js +711 -0
- package/cli/metrics.js +480 -0
- package/cli/monitor.js +812 -0
- package/cli/onboard.js +521 -0
- package/cli/orchestrator.js +12 -24
- package/cli/prd.js +594 -0
- package/cli/preseed-start.js +1483 -0
- package/cli/preseed.js +2302 -0
- package/cli/project.js +436 -0
- package/cli/quality.js +233 -0
- package/cli/security.js +913 -0
- package/cli/seed.js +1441 -5
- package/cli/skill.js +273 -211
- package/cli/suggest.js +989 -0
- package/cli/switch.js +453 -0
- package/cli/visualize.js +527 -0
- package/cli/watch.js +769 -0
- package/cli/workspace.js +607 -0
- package/core/analyze-workflow.js +1134 -0
- package/core/api-client.js +535 -22
- package/core/audit-workflow.js +1350 -0
- package/core/build-orchestrator.js +480 -0
- package/core/build-state.js +577 -0
- package/core/checkpoint-engine.js +408 -0
- package/core/config.js +1109 -26
- package/core/context-loader.js +21 -1
- package/core/deploy-workflow.js +836 -0
- package/core/entitlements.js +93 -22
- package/core/github-sync.js +610 -0
- package/core/index.js +8 -1
- package/core/ingest.js +1111 -0
- package/core/metrics-engine.js +768 -0
- package/core/onboard-workflow.js +1007 -0
- package/core/preseed-workflow.js +934 -0
- package/core/preseed.js +1617 -0
- package/core/project-context.js +325 -0
- package/core/project-state.js +694 -0
- package/core/r2-sync.js +583 -0
- package/core/scaffold.js +525 -7
- package/core/session.js +258 -0
- package/core/task-extractor.js +758 -0
- package/core/telemetry.js +28 -6
- package/core/tier-enforcement.js +737 -0
- package/core/utils.js +38 -14
- package/generators/questionnaire.js +15 -12
- package/generators/sections/ai.js +7 -7
- package/generators/sections/content.js +300 -0
- package/generators/sections/index.js +3 -0
- package/generators/sections/plugins.js +7 -6
- package/generators/templates/build-planning.template.js +596 -0
- package/generators/templates/content.template.js +819 -0
- package/generators/templates/index.js +2 -1
- package/hooks/git-autopilot.js +1250 -0
- package/hooks/index.js +9 -0
- package/intelligence/agent-collab.js +2057 -0
- package/intelligence/auto-suggest.js +634 -0
- package/intelligence/content-gen.js +1589 -0
- package/intelligence/cross-project.js +1647 -0
- package/intelligence/index.js +184 -0
- package/intelligence/learning/insights.json +517 -7
- package/intelligence/learning/pattern-learner.js +1008 -14
- package/intelligence/memory/decision-tracker.js +1431 -31
- package/intelligence/memory/decisions.jsonl +0 -0
- package/intelligence/orchestrator.js +2896 -1
- package/intelligence/prd.js +92 -1
- package/intelligence/recommendation-weights.json +14 -2
- package/intelligence/recommendations.js +463 -9
- package/intelligence/workflow-composer.js +1451 -0
- package/marketplace/index.d.ts +324 -0
- package/marketplace/index.js +1921 -0
- package/mcp/contracts/mcp-contract.v1.json +342 -4
- package/mcp/registry.js +680 -3
- package/mcp/response-formatter.js +23 -0
- package/mcp/tools/assist-tool.js +78 -4
- package/mcp/tools/autopilot-tool.js +408 -0
- package/mcp/tools/content-tool.js +571 -0
- package/mcp/tools/dashboard-tool.js +251 -5
- package/mcp/tools/mvp-tool.js +344 -0
- package/mcp/tools/plugin-tool.js +23 -1
- package/mcp/tools/prd-tool.js +579 -0
- package/mcp/tools/seed-tool.js +447 -0
- package/mcp/tools/skill-tool.js +43 -14
- package/mcp/tools/suggest-tool.js +147 -0
- package/package.json +15 -6
- package/agents/README.md +0 -93
- package/agents/ai-integration-expert/context.md +0 -386
- package/agents/api-expert/context.md +0 -416
- package/agents/architecture-expert/context.md +0 -454
- package/agents/auth-expert/context.md +0 -399
- package/agents/backend-expert/context.md +0 -483
- package/agents/business-strategy-expert/context.md +0 -180
- package/agents/code-review-expert/context.md +0 -365
- package/agents/competitive-analysis-expert/context.md +0 -239
- package/agents/data-modeling-expert/context.md +0 -352
- package/agents/database-expert/context.md +0 -250
- package/agents/devops-expert/context.md +0 -446
- package/agents/email-expert/context.md +0 -379
- package/agents/financial-expert/context.md +0 -213
- package/agents/frontend-expert/context.md +0 -364
- package/agents/fundraising-expert/context.md +0 -257
- package/agents/growth-expert/context.md +0 -249
- package/agents/index.js +0 -140
- package/agents/investor-relations-expert/context.md +0 -266
- package/agents/legal-expert/context.md +0 -284
- package/agents/marketing-expert/context.md +0 -236
- package/agents/monitoring-expert/context.md +0 -362
- package/agents/operations-expert/context.md +0 -279
- package/agents/partnerships-expert/context.md +0 -286
- package/agents/payment-expert/context.md +0 -340
- package/agents/performance-expert/context.md +0 -377
- package/agents/private-equity-expert/context.md +0 -246
- package/agents/railway-expert/context.md +0 -284
- package/agents/research-expert/context.md +0 -245
- package/agents/sales-expert/context.md +0 -241
- package/agents/security-expert/context.md +0 -343
- package/agents/testing-expert/context.md +0 -414
- package/agents/ui-ux-expert/context.md +0 -448
- package/agents/vercel-expert/context.md +0 -426
- package/skills/index.js +0 -787
- package/skills/patterns/README.md +0 -163
- package/skills/patterns/ai/agents.md +0 -281
- package/skills/patterns/ai/claude.md +0 -138
- package/skills/patterns/ai/embeddings.md +0 -150
- package/skills/patterns/ai/rag.md +0 -266
- package/skills/patterns/ai/streaming.md +0 -170
- package/skills/patterns/ai/structured-output.md +0 -162
- package/skills/patterns/ai/tools.md +0 -154
- package/skills/patterns/analytics/tracking.md +0 -220
- package/skills/patterns/api/errors.md +0 -296
- package/skills/patterns/api/graphql.md +0 -440
- package/skills/patterns/api/middleware.md +0 -279
- package/skills/patterns/api/openapi.md +0 -285
- package/skills/patterns/api/rate-limiting.md +0 -231
- package/skills/patterns/api/route-handler.md +0 -217
- package/skills/patterns/api/server-action.md +0 -249
- package/skills/patterns/api/versioning.md +0 -443
- package/skills/patterns/api/webhooks.md +0 -247
- package/skills/patterns/auth/clerk.md +0 -132
- package/skills/patterns/auth/mfa.md +0 -313
- package/skills/patterns/auth/nextauth.md +0 -140
- package/skills/patterns/auth/oauth.md +0 -237
- package/skills/patterns/auth/rbac.md +0 -152
- package/skills/patterns/auth/session-management.md +0 -367
- package/skills/patterns/auth/session.md +0 -120
- package/skills/patterns/database/audit.md +0 -177
- package/skills/patterns/database/migrations.md +0 -177
- package/skills/patterns/database/pagination.md +0 -230
- package/skills/patterns/database/pooling.md +0 -357
- package/skills/patterns/database/prisma.md +0 -180
- package/skills/patterns/database/relations.md +0 -187
- package/skills/patterns/database/seeding.md +0 -246
- package/skills/patterns/database/soft-delete.md +0 -153
- package/skills/patterns/database/transactions.md +0 -162
- package/skills/patterns/deployment/ci-cd.md +0 -231
- package/skills/patterns/deployment/docker.md +0 -188
- package/skills/patterns/deployment/monitoring.md +0 -387
- package/skills/patterns/deployment/vercel.md +0 -160
- package/skills/patterns/email/resend.md +0 -143
- package/skills/patterns/email/templates.md +0 -245
- package/skills/patterns/email/transactional.md +0 -503
- package/skills/patterns/email/verification.md +0 -176
- package/skills/patterns/files/download.md +0 -243
- package/skills/patterns/files/upload.md +0 -239
- package/skills/patterns/i18n/nextintl.md +0 -188
- package/skills/patterns/logging/structured.md +0 -292
- package/skills/patterns/notifications/email-queue.md +0 -248
- package/skills/patterns/notifications/push.md +0 -279
- package/skills/patterns/payments/checkout.md +0 -303
- package/skills/patterns/payments/invoices.md +0 -287
- package/skills/patterns/payments/portal.md +0 -245
- package/skills/patterns/payments/stripe.md +0 -272
- package/skills/patterns/payments/subscriptions.md +0 -300
- package/skills/patterns/payments/usage.md +0 -279
- package/skills/patterns/performance/caching.md +0 -276
- package/skills/patterns/performance/code-splitting.md +0 -233
- package/skills/patterns/performance/edge.md +0 -254
- package/skills/patterns/performance/isr.md +0 -266
- package/skills/patterns/performance/lazy-loading.md +0 -281
- package/skills/patterns/realtime/sse.md +0 -327
- package/skills/patterns/realtime/websockets.md +0 -336
- package/skills/patterns/search/filtering.md +0 -329
- package/skills/patterns/search/fulltext.md +0 -260
- package/skills/patterns/security/audit-logging.md +0 -444
- package/skills/patterns/security/csrf.md +0 -234
- package/skills/patterns/security/headers.md +0 -252
- package/skills/patterns/security/sanitization.md +0 -258
- package/skills/patterns/security/secrets.md +0 -261
- package/skills/patterns/security/validation.md +0 -268
- package/skills/patterns/security/xss.md +0 -229
- package/skills/patterns/seo/metadata.md +0 -252
- package/skills/patterns/state/context.md +0 -349
- package/skills/patterns/state/react-query.md +0 -313
- package/skills/patterns/state/url-state.md +0 -482
- package/skills/patterns/state/zustand.md +0 -262
- package/skills/patterns/testing/api.md +0 -259
- package/skills/patterns/testing/component.md +0 -233
- package/skills/patterns/testing/coverage.md +0 -207
- package/skills/patterns/testing/fixtures.md +0 -225
- package/skills/patterns/testing/integration.md +0 -436
- package/skills/patterns/testing/mocking.md +0 -177
- package/skills/patterns/testing/playwright.md +0 -162
- package/skills/patterns/testing/snapshot.md +0 -175
- package/skills/patterns/testing/vitest.md +0 -307
- package/skills/patterns/ui/accordions.md +0 -395
- package/skills/patterns/ui/cards.md +0 -299
- package/skills/patterns/ui/dropdowns.md +0 -476
- package/skills/patterns/ui/empty-states.md +0 -320
- package/skills/patterns/ui/forms.md +0 -405
- package/skills/patterns/ui/inputs.md +0 -319
- package/skills/patterns/ui/layouts.md +0 -282
- package/skills/patterns/ui/loading.md +0 -291
- package/skills/patterns/ui/modals.md +0 -338
- package/skills/patterns/ui/navigation.md +0 -374
- package/skills/patterns/ui/tables.md +0 -407
- package/skills/patterns/ui/toasts.md +0 -300
- package/skills/patterns/ui/tooltips.md +0 -396
- package/skills/patterns/utils/dates.md +0 -435
- package/skills/patterns/utils/errors.md +0 -451
- package/skills/patterns/utils/formatting.md +0 -345
- package/skills/patterns/utils/validation.md +0 -434
- package/templates/bootspring.config.js +0 -83
- package/templates/business/business-model-canvas.md +0 -246
- package/templates/business/business-plan.md +0 -266
- package/templates/business/competitive-analysis.md +0 -312
- package/templates/fundraising/data-room-checklist.md +0 -300
- package/templates/fundraising/investor-research.md +0 -243
- package/templates/fundraising/pitch-deck-outline.md +0 -253
- package/templates/legal/gdpr-checklist.md +0 -339
- package/templates/legal/privacy-policy.md +0 -285
- package/templates/legal/terms-of-service.md +0 -222
- package/templates/mcp.json +0 -9
package/core/scaffold.js
CHANGED
|
@@ -189,6 +189,149 @@ const PRESETS = {
|
|
|
189
189
|
}
|
|
190
190
|
};
|
|
191
191
|
|
|
192
|
+
/**
|
|
193
|
+
* Plugin configurations
|
|
194
|
+
* Each plugin adds directories, files, dependencies, and env vars
|
|
195
|
+
*/
|
|
196
|
+
const PLUGINS = {
|
|
197
|
+
// Auth providers
|
|
198
|
+
clerk: {
|
|
199
|
+
name: 'Clerk',
|
|
200
|
+
directories: ['app/(auth)/sign-in/[[...sign-in]]', 'app/(auth)/sign-up/[[...sign-up]]', 'lib/auth'],
|
|
201
|
+
files: [
|
|
202
|
+
{ path: 'middleware.ts', template: 'clerk/middleware' },
|
|
203
|
+
{ path: 'app/(auth)/sign-in/[[...sign-in]]/page.tsx', template: 'clerk/sign-in' },
|
|
204
|
+
{ path: 'app/(auth)/sign-up/[[...sign-up]]/page.tsx', template: 'clerk/sign-up' },
|
|
205
|
+
{ path: 'lib/auth/clerk.ts', template: 'clerk/auth-utils' }
|
|
206
|
+
],
|
|
207
|
+
dependencies: ['@clerk/nextjs'],
|
|
208
|
+
devDependencies: [],
|
|
209
|
+
envVars: ['NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY', 'CLERK_SECRET_KEY', 'NEXT_PUBLIC_CLERK_SIGN_IN_URL', 'NEXT_PUBLIC_CLERK_SIGN_UP_URL']
|
|
210
|
+
},
|
|
211
|
+
nextauth: {
|
|
212
|
+
name: 'NextAuth.js',
|
|
213
|
+
directories: ['app/api/auth/[...nextauth]', 'lib/auth'],
|
|
214
|
+
files: [
|
|
215
|
+
{ path: 'app/api/auth/[...nextauth]/route.ts', template: 'nextauth/route' },
|
|
216
|
+
{ path: 'lib/auth/config.ts', template: 'nextauth/config' },
|
|
217
|
+
{ path: 'lib/auth/session.ts', template: 'nextauth/session' }
|
|
218
|
+
],
|
|
219
|
+
dependencies: ['next-auth', '@auth/prisma-adapter'],
|
|
220
|
+
devDependencies: [],
|
|
221
|
+
envVars: ['NEXTAUTH_URL', 'NEXTAUTH_SECRET', 'GOOGLE_CLIENT_ID', 'GOOGLE_CLIENT_SECRET']
|
|
222
|
+
},
|
|
223
|
+
supabase: {
|
|
224
|
+
name: 'Supabase Auth',
|
|
225
|
+
directories: ['lib/supabase'],
|
|
226
|
+
files: [
|
|
227
|
+
{ path: 'lib/supabase/client.ts', template: 'supabase/client' },
|
|
228
|
+
{ path: 'lib/supabase/server.ts', template: 'supabase/server' },
|
|
229
|
+
{ path: 'middleware.ts', template: 'supabase/middleware' }
|
|
230
|
+
],
|
|
231
|
+
dependencies: ['@supabase/supabase-js', '@supabase/ssr'],
|
|
232
|
+
devDependencies: [],
|
|
233
|
+
envVars: ['NEXT_PUBLIC_SUPABASE_URL', 'NEXT_PUBLIC_SUPABASE_ANON_KEY', 'SUPABASE_SERVICE_ROLE_KEY']
|
|
234
|
+
},
|
|
235
|
+
|
|
236
|
+
// Payment providers
|
|
237
|
+
stripe: {
|
|
238
|
+
name: 'Stripe',
|
|
239
|
+
directories: ['app/api/webhooks/stripe', 'lib/stripe'],
|
|
240
|
+
files: [
|
|
241
|
+
{ path: 'lib/stripe/client.ts', template: 'stripe/client' },
|
|
242
|
+
{ path: 'lib/stripe/products.ts', template: 'stripe/products' },
|
|
243
|
+
{ path: 'app/api/webhooks/stripe/route.ts', template: 'stripe/webhook' }
|
|
244
|
+
],
|
|
245
|
+
dependencies: ['stripe', '@stripe/stripe-js'],
|
|
246
|
+
devDependencies: [],
|
|
247
|
+
envVars: ['STRIPE_SECRET_KEY', 'NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY', 'STRIPE_WEBHOOK_SECRET']
|
|
248
|
+
},
|
|
249
|
+
paddle: {
|
|
250
|
+
name: 'Paddle',
|
|
251
|
+
directories: ['app/api/webhooks/paddle', 'lib/paddle'],
|
|
252
|
+
files: [
|
|
253
|
+
{ path: 'lib/paddle/client.ts', template: 'paddle/client' },
|
|
254
|
+
{ path: 'app/api/webhooks/paddle/route.ts', template: 'paddle/webhook' }
|
|
255
|
+
],
|
|
256
|
+
dependencies: ['@paddle/paddle-js'],
|
|
257
|
+
devDependencies: [],
|
|
258
|
+
envVars: ['PADDLE_API_KEY', 'NEXT_PUBLIC_PADDLE_CLIENT_TOKEN', 'PADDLE_WEBHOOK_SECRET']
|
|
259
|
+
},
|
|
260
|
+
|
|
261
|
+
// Database providers
|
|
262
|
+
prisma: {
|
|
263
|
+
name: 'Prisma',
|
|
264
|
+
directories: ['prisma', 'lib/db'],
|
|
265
|
+
files: [
|
|
266
|
+
{ path: 'prisma/schema.prisma', template: 'prisma/schema' },
|
|
267
|
+
{ path: 'lib/db/index.ts', template: 'prisma/client' }
|
|
268
|
+
],
|
|
269
|
+
dependencies: ['@prisma/client'],
|
|
270
|
+
devDependencies: ['prisma'],
|
|
271
|
+
envVars: ['DATABASE_URL']
|
|
272
|
+
},
|
|
273
|
+
drizzle: {
|
|
274
|
+
name: 'Drizzle',
|
|
275
|
+
directories: ['drizzle', 'lib/db'],
|
|
276
|
+
files: [
|
|
277
|
+
{ path: 'drizzle/schema.ts', template: 'drizzle/schema' },
|
|
278
|
+
{ path: 'lib/db/index.ts', template: 'drizzle/client' },
|
|
279
|
+
{ path: 'drizzle.config.ts', template: 'drizzle/config' }
|
|
280
|
+
],
|
|
281
|
+
dependencies: ['drizzle-orm', 'postgres'],
|
|
282
|
+
devDependencies: ['drizzle-kit'],
|
|
283
|
+
envVars: ['DATABASE_URL']
|
|
284
|
+
},
|
|
285
|
+
|
|
286
|
+
// AI providers
|
|
287
|
+
anthropic: {
|
|
288
|
+
name: 'Anthropic',
|
|
289
|
+
directories: ['app/api/chat', 'lib/ai'],
|
|
290
|
+
files: [
|
|
291
|
+
{ path: 'lib/ai/anthropic.ts', template: 'anthropic/client' },
|
|
292
|
+
{ path: 'app/api/chat/route.ts', template: 'anthropic/route' }
|
|
293
|
+
],
|
|
294
|
+
dependencies: ['@anthropic-ai/sdk'],
|
|
295
|
+
devDependencies: [],
|
|
296
|
+
envVars: ['ANTHROPIC_API_KEY']
|
|
297
|
+
},
|
|
298
|
+
openai: {
|
|
299
|
+
name: 'OpenAI',
|
|
300
|
+
directories: ['app/api/chat', 'lib/ai'],
|
|
301
|
+
files: [
|
|
302
|
+
{ path: 'lib/ai/openai.ts', template: 'openai/client' },
|
|
303
|
+
{ path: 'app/api/chat/route.ts', template: 'openai/route' }
|
|
304
|
+
],
|
|
305
|
+
dependencies: ['openai'],
|
|
306
|
+
devDependencies: [],
|
|
307
|
+
envVars: ['OPENAI_API_KEY']
|
|
308
|
+
},
|
|
309
|
+
|
|
310
|
+
// Testing
|
|
311
|
+
vitest: {
|
|
312
|
+
name: 'Vitest',
|
|
313
|
+
directories: ['__tests__'],
|
|
314
|
+
files: [
|
|
315
|
+
{ path: 'vitest.config.ts', template: 'vitest/config' },
|
|
316
|
+
{ path: '__tests__/example.test.ts', template: 'vitest/example-test' }
|
|
317
|
+
],
|
|
318
|
+
dependencies: [],
|
|
319
|
+
devDependencies: ['vitest', '@testing-library/react', '@testing-library/jest-dom'],
|
|
320
|
+
envVars: []
|
|
321
|
+
},
|
|
322
|
+
playwright: {
|
|
323
|
+
name: 'Playwright',
|
|
324
|
+
directories: ['e2e'],
|
|
325
|
+
files: [
|
|
326
|
+
{ path: 'playwright.config.ts', template: 'playwright/config' },
|
|
327
|
+
{ path: 'e2e/example.spec.ts', template: 'playwright/example-test' }
|
|
328
|
+
],
|
|
329
|
+
dependencies: [],
|
|
330
|
+
devDependencies: ['@playwright/test'],
|
|
331
|
+
envVars: []
|
|
332
|
+
}
|
|
333
|
+
};
|
|
334
|
+
|
|
192
335
|
/**
|
|
193
336
|
* File templates
|
|
194
337
|
*/
|
|
@@ -1014,6 +1157,185 @@ NEXTAUTH_URL=http://localhost:3000
|
|
|
1014
1157
|
# STRIPE_SECRET_KEY=sk_test_...
|
|
1015
1158
|
# STRIPE_PUBLISHABLE_KEY=pk_test_...
|
|
1016
1159
|
# STRIPE_WEBHOOK_SECRET=whsec_...
|
|
1160
|
+
`,
|
|
1161
|
+
|
|
1162
|
+
// Plugin templates - Clerk
|
|
1163
|
+
'clerk/middleware': `import { clerkMiddleware, createRouteMatcher } from '@clerk/nextjs/server';
|
|
1164
|
+
|
|
1165
|
+
const isProtectedRoute = createRouteMatcher(['/dashboard(.*)']);
|
|
1166
|
+
|
|
1167
|
+
export default clerkMiddleware((auth, req) => {
|
|
1168
|
+
if (isProtectedRoute(req)) auth().protect();
|
|
1169
|
+
});
|
|
1170
|
+
|
|
1171
|
+
export const config = {
|
|
1172
|
+
matcher: ['/((?!.*\\\\..*|_next).*)', '/', '/(api|trpc)(.*)'],
|
|
1173
|
+
};
|
|
1174
|
+
`,
|
|
1175
|
+
|
|
1176
|
+
'clerk/sign-in': `import { SignIn } from '@clerk/nextjs';
|
|
1177
|
+
|
|
1178
|
+
export default function SignInPage() {
|
|
1179
|
+
return <SignIn />;
|
|
1180
|
+
}
|
|
1181
|
+
`,
|
|
1182
|
+
|
|
1183
|
+
'clerk/sign-up': `import { SignUp } from '@clerk/nextjs';
|
|
1184
|
+
|
|
1185
|
+
export default function SignUpPage() {
|
|
1186
|
+
return <SignUp />;
|
|
1187
|
+
}
|
|
1188
|
+
`,
|
|
1189
|
+
|
|
1190
|
+
'clerk/auth-utils': `import { auth } from '@clerk/nextjs/server';
|
|
1191
|
+
|
|
1192
|
+
export async function getUser() {
|
|
1193
|
+
const { userId } = auth();
|
|
1194
|
+
return userId;
|
|
1195
|
+
}
|
|
1196
|
+
`,
|
|
1197
|
+
|
|
1198
|
+
// Plugin templates - Prisma
|
|
1199
|
+
'prisma/schema': `generator client {
|
|
1200
|
+
provider = "prisma-client-js"
|
|
1201
|
+
}
|
|
1202
|
+
|
|
1203
|
+
datasource db {
|
|
1204
|
+
provider = "postgresql"
|
|
1205
|
+
url = env("DATABASE_URL")
|
|
1206
|
+
}
|
|
1207
|
+
|
|
1208
|
+
model User {
|
|
1209
|
+
id String @id @default(cuid())
|
|
1210
|
+
email String @unique
|
|
1211
|
+
name String?
|
|
1212
|
+
createdAt DateTime @default(now())
|
|
1213
|
+
updatedAt DateTime @updatedAt
|
|
1214
|
+
}
|
|
1215
|
+
`,
|
|
1216
|
+
|
|
1217
|
+
'prisma/client': `import { PrismaClient } from '@prisma/client';
|
|
1218
|
+
|
|
1219
|
+
const globalForPrisma = globalThis as unknown as {
|
|
1220
|
+
prisma: PrismaClient | undefined;
|
|
1221
|
+
};
|
|
1222
|
+
|
|
1223
|
+
export const db = globalForPrisma.prisma ?? new PrismaClient();
|
|
1224
|
+
|
|
1225
|
+
if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = db;
|
|
1226
|
+
`,
|
|
1227
|
+
|
|
1228
|
+
// Plugin templates - Stripe
|
|
1229
|
+
'stripe/client': `import Stripe from 'stripe';
|
|
1230
|
+
|
|
1231
|
+
export const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, {
|
|
1232
|
+
apiVersion: '2023-10-16',
|
|
1233
|
+
typescript: true,
|
|
1234
|
+
});
|
|
1235
|
+
`,
|
|
1236
|
+
|
|
1237
|
+
'stripe/products': `export const PLANS = {
|
|
1238
|
+
free: {
|
|
1239
|
+
name: 'Free',
|
|
1240
|
+
priceId: null,
|
|
1241
|
+
features: ['Feature 1', 'Feature 2'],
|
|
1242
|
+
},
|
|
1243
|
+
pro: {
|
|
1244
|
+
name: 'Pro',
|
|
1245
|
+
priceId: process.env.STRIPE_PRO_PRICE_ID,
|
|
1246
|
+
features: ['All Free features', 'Feature 3', 'Feature 4'],
|
|
1247
|
+
},
|
|
1248
|
+
};
|
|
1249
|
+
`,
|
|
1250
|
+
|
|
1251
|
+
'stripe/webhook': `import { headers } from 'next/headers';
|
|
1252
|
+
import { NextResponse } from 'next/server';
|
|
1253
|
+
import { stripe } from '@/lib/stripe/client';
|
|
1254
|
+
|
|
1255
|
+
export async function POST(req: Request) {
|
|
1256
|
+
const body = await req.text();
|
|
1257
|
+
const signature = headers().get('stripe-signature')!;
|
|
1258
|
+
|
|
1259
|
+
try {
|
|
1260
|
+
const event = stripe.webhooks.constructEvent(
|
|
1261
|
+
body,
|
|
1262
|
+
signature,
|
|
1263
|
+
process.env.STRIPE_WEBHOOK_SECRET!
|
|
1264
|
+
);
|
|
1265
|
+
|
|
1266
|
+
switch (event.type) {
|
|
1267
|
+
case 'checkout.session.completed':
|
|
1268
|
+
break;
|
|
1269
|
+
case 'customer.subscription.updated':
|
|
1270
|
+
break;
|
|
1271
|
+
case 'customer.subscription.deleted':
|
|
1272
|
+
break;
|
|
1273
|
+
}
|
|
1274
|
+
|
|
1275
|
+
return NextResponse.json({ received: true });
|
|
1276
|
+
} catch (err) {
|
|
1277
|
+
return NextResponse.json({ error: 'Webhook error' }, { status: 400 });
|
|
1278
|
+
}
|
|
1279
|
+
}
|
|
1280
|
+
`,
|
|
1281
|
+
|
|
1282
|
+
// Plugin templates - Vitest
|
|
1283
|
+
'vitest/config': `import { defineConfig } from 'vitest/config';
|
|
1284
|
+
import react from '@vitejs/plugin-react';
|
|
1285
|
+
import path from 'path';
|
|
1286
|
+
|
|
1287
|
+
export default defineConfig({
|
|
1288
|
+
plugins: [react()],
|
|
1289
|
+
test: {
|
|
1290
|
+
environment: 'jsdom',
|
|
1291
|
+
globals: true,
|
|
1292
|
+
},
|
|
1293
|
+
resolve: {
|
|
1294
|
+
alias: {
|
|
1295
|
+
'@': path.resolve(__dirname, './'),
|
|
1296
|
+
},
|
|
1297
|
+
},
|
|
1298
|
+
});
|
|
1299
|
+
`,
|
|
1300
|
+
|
|
1301
|
+
'vitest/example-test': `import { describe, it, expect } from 'vitest';
|
|
1302
|
+
|
|
1303
|
+
describe('Example', () => {
|
|
1304
|
+
it('should work', () => {
|
|
1305
|
+
expect(1 + 1).toBe(2);
|
|
1306
|
+
});
|
|
1307
|
+
});
|
|
1308
|
+
`,
|
|
1309
|
+
|
|
1310
|
+
// Plugin templates - Anthropic
|
|
1311
|
+
'anthropic/client': `import Anthropic from '@anthropic-ai/sdk';
|
|
1312
|
+
|
|
1313
|
+
export const anthropic = new Anthropic({
|
|
1314
|
+
apiKey: process.env.ANTHROPIC_API_KEY,
|
|
1315
|
+
});
|
|
1316
|
+
`,
|
|
1317
|
+
|
|
1318
|
+
'anthropic/route': `import { anthropic } from '@/lib/ai/anthropic';
|
|
1319
|
+
import { NextResponse } from 'next/server';
|
|
1320
|
+
|
|
1321
|
+
export async function POST(req: Request) {
|
|
1322
|
+
try {
|
|
1323
|
+
const { messages } = await req.json();
|
|
1324
|
+
|
|
1325
|
+
const response = await anthropic.messages.create({
|
|
1326
|
+
model: 'claude-3-sonnet-20240229',
|
|
1327
|
+
max_tokens: 1024,
|
|
1328
|
+
messages,
|
|
1329
|
+
});
|
|
1330
|
+
|
|
1331
|
+
return NextResponse.json(response);
|
|
1332
|
+
} catch (error) {
|
|
1333
|
+
return NextResponse.json(
|
|
1334
|
+
{ error: 'Failed to get response' },
|
|
1335
|
+
{ status: 500 }
|
|
1336
|
+
);
|
|
1337
|
+
}
|
|
1338
|
+
}
|
|
1017
1339
|
`
|
|
1018
1340
|
};
|
|
1019
1341
|
|
|
@@ -1067,18 +1389,148 @@ function planScaffold(config, projectRoot) {
|
|
|
1067
1389
|
const preset = config._preset || detectPreset(config);
|
|
1068
1390
|
const presetConfig = PRESETS[preset] || PRESETS.nextjs;
|
|
1069
1391
|
|
|
1392
|
+
// Start with preset directories and files
|
|
1393
|
+
const directories = [...presetConfig.directories];
|
|
1394
|
+
const files = presetConfig.files.map(f => ({
|
|
1395
|
+
path: f.path,
|
|
1396
|
+
template: f.template,
|
|
1397
|
+
fullPath: path.join(projectRoot, f.path)
|
|
1398
|
+
}));
|
|
1399
|
+
const dependencies = {
|
|
1400
|
+
dependencies: [...(presetConfig.dependencies?.dependencies || [])],
|
|
1401
|
+
devDependencies: [...(presetConfig.dependencies?.devDependencies || [])]
|
|
1402
|
+
};
|
|
1403
|
+
const envVars = [];
|
|
1404
|
+
|
|
1405
|
+
// Add plugin configurations based on config
|
|
1406
|
+
const plugins = detectPlugins(config);
|
|
1407
|
+
|
|
1408
|
+
for (const pluginName of plugins) {
|
|
1409
|
+
const plugin = PLUGINS[pluginName];
|
|
1410
|
+
if (!plugin) continue;
|
|
1411
|
+
|
|
1412
|
+
// Add plugin directories
|
|
1413
|
+
if (plugin.directories) {
|
|
1414
|
+
for (const dir of plugin.directories) {
|
|
1415
|
+
if (!directories.includes(dir)) {
|
|
1416
|
+
directories.push(dir);
|
|
1417
|
+
}
|
|
1418
|
+
}
|
|
1419
|
+
}
|
|
1420
|
+
|
|
1421
|
+
// Add plugin files
|
|
1422
|
+
if (plugin.files) {
|
|
1423
|
+
for (const f of plugin.files) {
|
|
1424
|
+
// Don't add if file already exists in plan
|
|
1425
|
+
if (!files.some(existing => existing.path === f.path)) {
|
|
1426
|
+
files.push({
|
|
1427
|
+
path: f.path,
|
|
1428
|
+
template: f.template,
|
|
1429
|
+
fullPath: path.join(projectRoot, f.path)
|
|
1430
|
+
});
|
|
1431
|
+
}
|
|
1432
|
+
}
|
|
1433
|
+
}
|
|
1434
|
+
|
|
1435
|
+
// Add plugin dependencies
|
|
1436
|
+
if (plugin.dependencies) {
|
|
1437
|
+
for (const dep of plugin.dependencies) {
|
|
1438
|
+
if (!dependencies.dependencies.includes(dep)) {
|
|
1439
|
+
dependencies.dependencies.push(dep);
|
|
1440
|
+
}
|
|
1441
|
+
}
|
|
1442
|
+
}
|
|
1443
|
+
if (plugin.devDependencies) {
|
|
1444
|
+
for (const dep of plugin.devDependencies) {
|
|
1445
|
+
if (!dependencies.devDependencies.includes(dep)) {
|
|
1446
|
+
dependencies.devDependencies.push(dep);
|
|
1447
|
+
}
|
|
1448
|
+
}
|
|
1449
|
+
}
|
|
1450
|
+
|
|
1451
|
+
// Collect env vars
|
|
1452
|
+
if (plugin.envVars) {
|
|
1453
|
+
for (const envVar of plugin.envVars) {
|
|
1454
|
+
if (!envVars.includes(envVar)) {
|
|
1455
|
+
envVars.push(envVar);
|
|
1456
|
+
}
|
|
1457
|
+
}
|
|
1458
|
+
}
|
|
1459
|
+
}
|
|
1460
|
+
|
|
1070
1461
|
return {
|
|
1071
1462
|
preset,
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
dependencies: presetConfig.dependencies
|
|
1463
|
+
framework: presetConfig.framework,
|
|
1464
|
+
plugins,
|
|
1465
|
+
directories,
|
|
1466
|
+
files,
|
|
1467
|
+
dependencies,
|
|
1468
|
+
envVars
|
|
1079
1469
|
};
|
|
1080
1470
|
}
|
|
1081
1471
|
|
|
1472
|
+
/**
|
|
1473
|
+
* Detect which plugins should be included based on config
|
|
1474
|
+
*/
|
|
1475
|
+
function detectPlugins(config) {
|
|
1476
|
+
const plugins = [];
|
|
1477
|
+
|
|
1478
|
+
// Auth provider
|
|
1479
|
+
if (config.enableAuth || config.plugins?.auth?.provider) {
|
|
1480
|
+
const authProvider = config.authProvider || config.plugins?.auth?.provider;
|
|
1481
|
+
if (authProvider && PLUGINS[authProvider]) {
|
|
1482
|
+
plugins.push(authProvider);
|
|
1483
|
+
}
|
|
1484
|
+
}
|
|
1485
|
+
|
|
1486
|
+
// Payments provider
|
|
1487
|
+
if (config.enablePayments || config.plugins?.payments?.provider) {
|
|
1488
|
+
const paymentsProvider = config.paymentsProvider || config.plugins?.payments?.provider;
|
|
1489
|
+
if (paymentsProvider && PLUGINS[paymentsProvider]) {
|
|
1490
|
+
plugins.push(paymentsProvider);
|
|
1491
|
+
}
|
|
1492
|
+
}
|
|
1493
|
+
|
|
1494
|
+
// Database provider
|
|
1495
|
+
if (config.plugins?.database?.provider) {
|
|
1496
|
+
const dbProvider = config.plugins.database.provider;
|
|
1497
|
+
if (PLUGINS[dbProvider]) {
|
|
1498
|
+
plugins.push(dbProvider);
|
|
1499
|
+
}
|
|
1500
|
+
} else if (config.stack?.database === 'postgresql' || config.stack?.database === 'mysql') {
|
|
1501
|
+
// Default to prisma for SQL databases
|
|
1502
|
+
plugins.push('prisma');
|
|
1503
|
+
}
|
|
1504
|
+
|
|
1505
|
+
// AI providers (can be multiple)
|
|
1506
|
+
if (config.enableAI || config.plugins?.ai?.enabled || config.plugins?.ai?.providers?.length) {
|
|
1507
|
+
const aiProviders = config.aiProviders || config.plugins?.ai?.providers || [];
|
|
1508
|
+
// Handle legacy single provider config
|
|
1509
|
+
const legacyProvider = config.aiProvider || config.plugins?.ai?.provider;
|
|
1510
|
+
if (legacyProvider && !aiProviders.includes(legacyProvider)) {
|
|
1511
|
+
aiProviders.push(legacyProvider);
|
|
1512
|
+
}
|
|
1513
|
+
for (const provider of aiProviders) {
|
|
1514
|
+
if (provider && PLUGINS[provider]) {
|
|
1515
|
+
plugins.push(provider);
|
|
1516
|
+
}
|
|
1517
|
+
}
|
|
1518
|
+
}
|
|
1519
|
+
|
|
1520
|
+
// Testing
|
|
1521
|
+
if (config.enableTesting || config.plugins?.testing?.provider) {
|
|
1522
|
+
const testProvider = config.testingProvider || config.plugins?.testing?.provider;
|
|
1523
|
+
if (testProvider === 'both') {
|
|
1524
|
+
plugins.push('vitest');
|
|
1525
|
+
plugins.push('playwright');
|
|
1526
|
+
} else if (testProvider && PLUGINS[testProvider]) {
|
|
1527
|
+
plugins.push(testProvider);
|
|
1528
|
+
}
|
|
1529
|
+
}
|
|
1530
|
+
|
|
1531
|
+
return plugins;
|
|
1532
|
+
}
|
|
1533
|
+
|
|
1082
1534
|
/**
|
|
1083
1535
|
* Detect preset from config
|
|
1084
1536
|
*/
|
|
@@ -1125,6 +1577,37 @@ async function execute(plan, projectRoot) {
|
|
|
1125
1577
|
}
|
|
1126
1578
|
}
|
|
1127
1579
|
|
|
1580
|
+
// Create package.json if dependencies exist
|
|
1581
|
+
if (plan.dependencies) {
|
|
1582
|
+
const packageJsonPath = path.join(projectRoot, 'package.json');
|
|
1583
|
+
if (!fs.existsSync(packageJsonPath)) {
|
|
1584
|
+
try {
|
|
1585
|
+
const projectName = path.basename(projectRoot);
|
|
1586
|
+
const packageJson = {
|
|
1587
|
+
name: projectName,
|
|
1588
|
+
version: '0.1.0',
|
|
1589
|
+
private: true,
|
|
1590
|
+
scripts: getScriptsForFramework(plan.framework || 'node'),
|
|
1591
|
+
dependencies: {},
|
|
1592
|
+
devDependencies: {}
|
|
1593
|
+
};
|
|
1594
|
+
|
|
1595
|
+
// Add dependencies
|
|
1596
|
+
for (const dep of (plan.dependencies.dependencies || [])) {
|
|
1597
|
+
packageJson.dependencies[dep] = 'latest';
|
|
1598
|
+
}
|
|
1599
|
+
for (const dep of (plan.dependencies.devDependencies || [])) {
|
|
1600
|
+
packageJson.devDependencies[dep] = 'latest';
|
|
1601
|
+
}
|
|
1602
|
+
|
|
1603
|
+
fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2));
|
|
1604
|
+
result.filesCreated++;
|
|
1605
|
+
} catch (error) {
|
|
1606
|
+
result.warnings.push(`Could not create package.json: ${error.message}`);
|
|
1607
|
+
}
|
|
1608
|
+
}
|
|
1609
|
+
}
|
|
1610
|
+
|
|
1128
1611
|
// Create files
|
|
1129
1612
|
for (const file of plan.files) {
|
|
1130
1613
|
const template = TEMPLATES[file.template];
|
|
@@ -1156,6 +1639,41 @@ async function execute(plan, projectRoot) {
|
|
|
1156
1639
|
return result;
|
|
1157
1640
|
}
|
|
1158
1641
|
|
|
1642
|
+
/**
|
|
1643
|
+
* Get npm scripts based on framework
|
|
1644
|
+
*/
|
|
1645
|
+
function getScriptsForFramework(framework) {
|
|
1646
|
+
switch (framework) {
|
|
1647
|
+
case 'nextjs':
|
|
1648
|
+
return {
|
|
1649
|
+
dev: 'next dev',
|
|
1650
|
+
build: 'next build',
|
|
1651
|
+
start: 'next start',
|
|
1652
|
+
lint: 'next lint'
|
|
1653
|
+
};
|
|
1654
|
+
case 'react':
|
|
1655
|
+
return {
|
|
1656
|
+
dev: 'vite',
|
|
1657
|
+
build: 'vite build',
|
|
1658
|
+
preview: 'vite preview'
|
|
1659
|
+
};
|
|
1660
|
+
case 'express':
|
|
1661
|
+
case 'node':
|
|
1662
|
+
return {
|
|
1663
|
+
dev: 'tsx watch src/index.ts',
|
|
1664
|
+
build: 'tsc',
|
|
1665
|
+
start: 'node dist/index.js',
|
|
1666
|
+
test: 'vitest'
|
|
1667
|
+
};
|
|
1668
|
+
default:
|
|
1669
|
+
return {
|
|
1670
|
+
dev: 'npm run start',
|
|
1671
|
+
build: 'echo "No build script"',
|
|
1672
|
+
start: 'node index.js'
|
|
1673
|
+
};
|
|
1674
|
+
}
|
|
1675
|
+
}
|
|
1676
|
+
|
|
1159
1677
|
module.exports = {
|
|
1160
1678
|
getPresets,
|
|
1161
1679
|
getPresetInfo,
|