@opensaas/stack-cli 0.1.7 → 0.4.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 (104) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/CHANGELOG.md +348 -0
  3. package/CLAUDE.md +60 -12
  4. package/dist/commands/generate.d.ts.map +1 -1
  5. package/dist/commands/generate.js +13 -13
  6. package/dist/commands/generate.js.map +1 -1
  7. package/dist/commands/mcp.d.ts +6 -0
  8. package/dist/commands/mcp.d.ts.map +1 -0
  9. package/dist/commands/mcp.js +116 -0
  10. package/dist/commands/mcp.js.map +1 -0
  11. package/dist/generator/context.d.ts.map +1 -1
  12. package/dist/generator/context.js +40 -7
  13. package/dist/generator/context.js.map +1 -1
  14. package/dist/generator/index.d.ts +4 -1
  15. package/dist/generator/index.d.ts.map +1 -1
  16. package/dist/generator/index.js +4 -1
  17. package/dist/generator/index.js.map +1 -1
  18. package/dist/generator/lists.d.ts +31 -0
  19. package/dist/generator/lists.d.ts.map +1 -0
  20. package/dist/generator/lists.js +123 -0
  21. package/dist/generator/lists.js.map +1 -0
  22. package/dist/generator/plugin-types.d.ts +10 -0
  23. package/dist/generator/plugin-types.d.ts.map +1 -0
  24. package/dist/generator/plugin-types.js +122 -0
  25. package/dist/generator/plugin-types.js.map +1 -0
  26. package/dist/generator/prisma-config.d.ts +17 -0
  27. package/dist/generator/prisma-config.d.ts.map +1 -0
  28. package/dist/generator/prisma-config.js +40 -0
  29. package/dist/generator/prisma-config.js.map +1 -0
  30. package/dist/generator/prisma-extensions.d.ts +11 -0
  31. package/dist/generator/prisma-extensions.d.ts.map +1 -0
  32. package/dist/generator/prisma-extensions.js +134 -0
  33. package/dist/generator/prisma-extensions.js.map +1 -0
  34. package/dist/generator/prisma.d.ts.map +1 -1
  35. package/dist/generator/prisma.js +5 -2
  36. package/dist/generator/prisma.js.map +1 -1
  37. package/dist/generator/types.d.ts.map +1 -1
  38. package/dist/generator/types.js +201 -17
  39. package/dist/generator/types.js.map +1 -1
  40. package/dist/index.js +3 -0
  41. package/dist/index.js.map +1 -1
  42. package/dist/mcp/lib/documentation-provider.d.ts +43 -0
  43. package/dist/mcp/lib/documentation-provider.d.ts.map +1 -0
  44. package/dist/mcp/lib/documentation-provider.js +163 -0
  45. package/dist/mcp/lib/documentation-provider.js.map +1 -0
  46. package/dist/mcp/lib/features/catalog.d.ts +26 -0
  47. package/dist/mcp/lib/features/catalog.d.ts.map +1 -0
  48. package/dist/mcp/lib/features/catalog.js +291 -0
  49. package/dist/mcp/lib/features/catalog.js.map +1 -0
  50. package/dist/mcp/lib/generators/feature-generator.d.ts +35 -0
  51. package/dist/mcp/lib/generators/feature-generator.d.ts.map +1 -0
  52. package/dist/mcp/lib/generators/feature-generator.js +546 -0
  53. package/dist/mcp/lib/generators/feature-generator.js.map +1 -0
  54. package/dist/mcp/lib/types.d.ts +80 -0
  55. package/dist/mcp/lib/types.d.ts.map +1 -0
  56. package/dist/mcp/lib/types.js +5 -0
  57. package/dist/mcp/lib/types.js.map +1 -0
  58. package/dist/mcp/lib/wizards/wizard-engine.d.ts +71 -0
  59. package/dist/mcp/lib/wizards/wizard-engine.d.ts.map +1 -0
  60. package/dist/mcp/lib/wizards/wizard-engine.js +356 -0
  61. package/dist/mcp/lib/wizards/wizard-engine.js.map +1 -0
  62. package/dist/mcp/server/index.d.ts +8 -0
  63. package/dist/mcp/server/index.d.ts.map +1 -0
  64. package/dist/mcp/server/index.js +202 -0
  65. package/dist/mcp/server/index.js.map +1 -0
  66. package/dist/mcp/server/stack-mcp-server.d.ts +92 -0
  67. package/dist/mcp/server/stack-mcp-server.d.ts.map +1 -0
  68. package/dist/mcp/server/stack-mcp-server.js +265 -0
  69. package/dist/mcp/server/stack-mcp-server.js.map +1 -0
  70. package/package.json +10 -8
  71. package/src/commands/__snapshots__/generate.test.ts.snap +145 -38
  72. package/src/commands/dev.test.ts +0 -1
  73. package/src/commands/generate.test.ts +18 -8
  74. package/src/commands/generate.ts +20 -19
  75. package/src/commands/mcp.ts +135 -0
  76. package/src/generator/__snapshots__/context.test.ts.snap +63 -18
  77. package/src/generator/__snapshots__/prisma.test.ts.snap +8 -16
  78. package/src/generator/__snapshots__/types.test.ts.snap +1267 -95
  79. package/src/generator/context.test.ts +15 -8
  80. package/src/generator/context.ts +40 -7
  81. package/src/generator/index.ts +4 -1
  82. package/src/generator/lists.test.ts +335 -0
  83. package/src/generator/lists.ts +140 -0
  84. package/src/generator/plugin-types.ts +147 -0
  85. package/src/generator/prisma-config.ts +46 -0
  86. package/src/generator/prisma-extensions.ts +159 -0
  87. package/src/generator/prisma.test.ts +0 -10
  88. package/src/generator/prisma.ts +6 -2
  89. package/src/generator/types.test.ts +0 -12
  90. package/src/generator/types.ts +257 -17
  91. package/src/index.ts +4 -0
  92. package/src/mcp/lib/documentation-provider.ts +203 -0
  93. package/src/mcp/lib/features/catalog.ts +301 -0
  94. package/src/mcp/lib/generators/feature-generator.ts +598 -0
  95. package/src/mcp/lib/types.ts +89 -0
  96. package/src/mcp/lib/wizards/wizard-engine.ts +427 -0
  97. package/src/mcp/server/index.ts +240 -0
  98. package/src/mcp/server/stack-mcp-server.ts +301 -0
  99. package/tsconfig.tsbuildinfo +1 -1
  100. package/dist/generator/type-patcher.d.ts +0 -13
  101. package/dist/generator/type-patcher.d.ts.map +0 -1
  102. package/dist/generator/type-patcher.js +0 -68
  103. package/dist/generator/type-patcher.js.map +0 -1
  104. package/src/generator/type-patcher.ts +0 -93
@@ -0,0 +1,546 @@
1
+ /**
2
+ * Feature generator - Generates code, config, and documentation for features
3
+ */
4
+ export class FeatureGenerator {
5
+ feature;
6
+ answers;
7
+ followUpAnswers;
8
+ constructor(feature, answers, followUpAnswers) {
9
+ this.feature = feature;
10
+ this.answers = answers;
11
+ this.followUpAnswers = followUpAnswers;
12
+ }
13
+ /**
14
+ * Generate complete feature implementation
15
+ */
16
+ generate() {
17
+ const featureType = this.feature.id;
18
+ switch (featureType) {
19
+ case 'authentication':
20
+ return this.generateAuthentication();
21
+ case 'blog':
22
+ return this.generateBlog();
23
+ case 'comments':
24
+ return this.generateComments();
25
+ case 'file-upload':
26
+ return this.generateFileUpload();
27
+ case 'semantic-search':
28
+ return this.generateSemanticSearch();
29
+ default:
30
+ throw new Error(`Unknown feature type: ${featureType}`);
31
+ }
32
+ }
33
+ /**
34
+ * Generate authentication feature
35
+ */
36
+ generateAuthentication() {
37
+ const authMethods = this.answers['auth-methods'];
38
+ const hasRoles = this.answers['user-roles'];
39
+ const roles = hasRoles
40
+ ? this.followUpAnswers['user-roles_followup']
41
+ ?.split(',')
42
+ .map((r) => r.trim()) || ['admin', 'user']
43
+ : null;
44
+ const userFields = this.answers['user-fields'] || [];
45
+ const emailVerification = this.answers['email-verification'];
46
+ const hasOAuth = authMethods.some((m) => ['Google OAuth', 'GitHub OAuth'].includes(m));
47
+ const hasPassword = authMethods.includes('Email & Password');
48
+ const hasMagicLink = authMethods.includes('Magic Links');
49
+ // Build User list fields
50
+ const fields = ['email: text({ validation: { isRequired: true } })'];
51
+ if (hasPassword) {
52
+ fields.push('password: password({ validation: { isRequired: true } })');
53
+ }
54
+ fields.push('name: text()');
55
+ if (hasRoles && roles) {
56
+ fields.push(`role: select({ options: [${roles.map((r) => `'${r}'`).join(', ')}], defaultValue: '${roles[roles.length - 1]}' })`);
57
+ }
58
+ if (userFields.includes('Avatar')) {
59
+ fields.push('avatar: text()');
60
+ }
61
+ if (userFields.includes('Bio')) {
62
+ fields.push('bio: text({ ui: { displayMode: "textarea" } })');
63
+ }
64
+ if (userFields.includes('Phone')) {
65
+ fields.push('phone: text()');
66
+ }
67
+ if (userFields.includes('Location')) {
68
+ fields.push('location: text()');
69
+ }
70
+ if (userFields.includes('Website')) {
71
+ fields.push('website: text()');
72
+ }
73
+ // Config updates
74
+ const configUpdates = `import { config, list } from '@opensaas/stack-core';
75
+ import { text, password, select } from '@opensaas/stack-core/fields';
76
+ import { authPlugin } from '@opensaas/stack-auth';
77
+
78
+ export default config({
79
+ plugins: [
80
+ authPlugin({
81
+ emailAndPassword: { enabled: ${hasPassword} },
82
+ ${hasOAuth
83
+ ? `oauth: {
84
+ google: { enabled: ${authMethods.includes('Google OAuth')} },
85
+ github: { enabled: ${authMethods.includes('GitHub OAuth')} },
86
+ },`
87
+ : ''}
88
+ ${hasMagicLink ? `magicLink: { enabled: true },` : ''}
89
+ ${emailVerification ? `emailVerification: { enabled: true },` : ''}
90
+ sessionFields: ['userId', 'email', 'name'${hasRoles ? ", 'role'" : ''}],
91
+ }),
92
+ ],
93
+ db: {
94
+ provider: 'postgresql', // or 'sqlite'
95
+ url: process.env.DATABASE_URL,
96
+ },
97
+ lists: {
98
+ User: list({
99
+ fields: {
100
+ ${fields.join(',\n ')}
101
+ },
102
+ access: {
103
+ operation: {
104
+ query: () => true,
105
+ create: () => true, // Public sign-up
106
+ update: ({ session, item }) => session?.userId === item.id,
107
+ delete: ({ session }) => session?.role === 'admin',
108
+ },
109
+ },
110
+ }),
111
+ // Add your other lists here
112
+ },
113
+ });`;
114
+ // Generated files
115
+ const files = [];
116
+ // Sign-in page
117
+ if (hasPassword || hasOAuth) {
118
+ files.push({
119
+ path: 'app/sign-in/page.tsx',
120
+ language: 'tsx',
121
+ description: 'Sign-in page with form and OAuth buttons',
122
+ content: `import { SignInForm } from '@opensaas/stack-auth/ui';
123
+
124
+ export default function SignInPage() {
125
+ return (
126
+ <div className="min-h-screen flex items-center justify-center">
127
+ <div className="w-full max-w-md">
128
+ <h1 className="text-2xl font-bold mb-6">Sign In</h1>
129
+ <SignInForm
130
+ ${hasPassword ? 'emailAndPassword' : ''}
131
+ ${hasOAuth ? `oauth={[${authMethods.includes('Google OAuth') ? "'google'" : ''}${authMethods.includes('GitHub OAuth') ? ", 'github'" : ''}]}` : ''}
132
+ redirectTo="/dashboard"
133
+ />
134
+ </div>
135
+ </div>
136
+ );
137
+ }`,
138
+ });
139
+ }
140
+ // Sign-up page
141
+ if (hasPassword) {
142
+ files.push({
143
+ path: 'app/sign-up/page.tsx',
144
+ language: 'tsx',
145
+ description: 'Sign-up page with registration form',
146
+ content: `import { SignUpForm } from '@opensaas/stack-auth/ui';
147
+
148
+ export default function SignUpPage() {
149
+ return (
150
+ <div className="min-h-screen flex items-center justify-center">
151
+ <div className="w-full max-w-md">
152
+ <h1 className="text-2xl font-bold mb-6">Create Account</h1>
153
+ <SignUpForm
154
+ fields={['email', 'password', 'name']}
155
+ redirectTo="/dashboard"
156
+ ${emailVerification ? 'requireEmailVerification' : ''}
157
+ />
158
+ </div>
159
+ </div>
160
+ );
161
+ }`,
162
+ });
163
+ }
164
+ // Access control helpers
165
+ files.push({
166
+ path: 'lib/access-control.ts',
167
+ language: 'typescript',
168
+ description: 'Reusable access control functions',
169
+ content: `import type { AccessControl } from '@opensaas/stack-core';
170
+
171
+ export const isAuthenticated: AccessControl = ({ session }) => {
172
+ return !!session?.userId;
173
+ };
174
+
175
+ ${hasRoles
176
+ ? `export const isAdmin: AccessControl = ({ session }) => {
177
+ return session?.role === 'admin';
178
+ };
179
+
180
+ export const isOwner: AccessControl = ({ session, item }) => {
181
+ return session?.userId === item.id;
182
+ };
183
+
184
+ export const isAdminOrOwner: AccessControl = ({ session, item }) => {
185
+ return session?.role === 'admin' || session?.userId === item.id;
186
+ };`
187
+ : ''}
188
+
189
+ export const requireAuth: AccessControl = ({ session }) => {
190
+ if (!session?.userId) {
191
+ throw new Error('Authentication required');
192
+ }
193
+ return true;
194
+ };`,
195
+ });
196
+ // Environment variables
197
+ const envVars = {
198
+ DATABASE_URL: 'postgresql://user:password@localhost:5432/mydb',
199
+ BETTER_AUTH_SECRET: '<generate-with-openssl-rand-base64-32>',
200
+ BETTER_AUTH_URL: 'http://localhost:3000',
201
+ };
202
+ if (authMethods.includes('Google OAuth')) {
203
+ envVars.GOOGLE_CLIENT_ID = '<your-google-client-id>';
204
+ envVars.GOOGLE_CLIENT_SECRET = '<your-google-client-secret>';
205
+ }
206
+ if (authMethods.includes('GitHub OAuth')) {
207
+ envVars.GITHUB_CLIENT_ID = '<your-github-client-id>';
208
+ envVars.GITHUB_CLIENT_SECRET = '<your-github-client-secret>';
209
+ }
210
+ // Next steps
211
+ const nextSteps = [
212
+ 'Copy the config updates to your `opensaas.config.ts`',
213
+ 'Create the files shown above in your project',
214
+ 'Add environment variables to your `.env` file',
215
+ hasOAuth ? 'Set up OAuth applications in Google/GitHub developer consoles' : null,
216
+ 'Run `pnpm generate` to update Prisma schema',
217
+ 'Run `pnpm db:push` to update your database',
218
+ 'Start your dev server: `pnpm dev`',
219
+ `Visit http://localhost:3000/${hasPassword ? 'sign-up' : 'sign-in'} to test authentication`,
220
+ ].filter(Boolean);
221
+ // Dev guide section
222
+ const devGuideSection = `## Authentication Feature
223
+
224
+ This project uses Better-auth for authentication with the following configuration:
225
+
226
+ ${authMethods.map((m) => `- ${m}`).join('\n')}
227
+ ${hasRoles ? `\n**User Roles**: ${roles?.join(', ')}` : ''}
228
+
229
+ ### Access Control Helpers
230
+
231
+ Use these functions in your list configurations:
232
+
233
+ \`\`\`typescript
234
+ import { isAuthenticated${hasRoles ? ', isAdmin, isOwner' : ''} } from './lib/access-control';
235
+
236
+ // In your list config:
237
+ access: {
238
+ operation: {
239
+ query: () => true,
240
+ create: isAuthenticated,
241
+ update: isOwner,
242
+ delete: ${hasRoles ? 'isAdmin' : 'isOwner'},
243
+ }
244
+ }
245
+ \`\`\`
246
+
247
+ ### Protected Routes
248
+
249
+ To protect a route, check the session in your server components:
250
+
251
+ \`\`\`typescript
252
+ import { auth } from '@/lib/auth';
253
+
254
+ export default async function ProtectedPage() {
255
+ const session = await auth();
256
+
257
+ if (!session) {
258
+ redirect('/sign-in');
259
+ }
260
+
261
+ return <div>Protected content for {session.user.name}</div>;
262
+ }
263
+ \`\`\`
264
+
265
+ ### Getting the Current User
266
+
267
+ In server actions or API routes:
268
+
269
+ \`\`\`typescript
270
+ import { getContext } from '@/.opensaas/context';
271
+
272
+ const context = await getContext();
273
+ const currentUser = await context.db.user.findUnique({
274
+ where: { id: context.session?.userId }
275
+ });
276
+ \`\`\``;
277
+ return {
278
+ configUpdates,
279
+ files,
280
+ instructions: nextSteps,
281
+ devGuideSection,
282
+ envVars,
283
+ nextSteps,
284
+ };
285
+ }
286
+ /**
287
+ * Generate blog feature
288
+ */
289
+ generateBlog() {
290
+ const contentEditor = this.answers['content-editor'];
291
+ const hasStatus = this.answers['post-status'];
292
+ const taxonomy = this.answers['taxonomy'] || [];
293
+ const postFields = this.answers['post-fields'] || [];
294
+ const useTiptap = contentEditor === 'Rich text editor (Tiptap)';
295
+ const useMarkdown = contentEditor === 'Markdown';
296
+ // Build Post fields
297
+ const fields = [
298
+ 'title: text({ validation: { isRequired: true } })',
299
+ 'slug: text({ validation: { isRequired: true } })',
300
+ ];
301
+ if (useTiptap) {
302
+ fields.push('content: richText({ validation: { isRequired: true } })');
303
+ }
304
+ else if (useMarkdown) {
305
+ fields.push('content: text({ ui: { displayMode: "textarea" }, validation: { isRequired: true } })');
306
+ }
307
+ else {
308
+ fields.push('content: text({ ui: { displayMode: "textarea" }, validation: { isRequired: true } })');
309
+ }
310
+ fields.push('author: relationship({ ref: "User.posts" })');
311
+ if (hasStatus) {
312
+ fields.push("status: select({ options: ['draft', 'published'], defaultValue: 'draft' })");
313
+ fields.push('publishedAt: timestamp()');
314
+ }
315
+ if (postFields.includes('Featured image')) {
316
+ fields.push('featuredImage: text()');
317
+ }
318
+ if (postFields.includes('Excerpt/summary')) {
319
+ fields.push('excerpt: text({ ui: { displayMode: "textarea" } })');
320
+ }
321
+ if (postFields.includes('SEO metadata (title, description)')) {
322
+ fields.push('seoTitle: text()');
323
+ fields.push('seoDescription: text()');
324
+ }
325
+ if (postFields.includes('Reading time estimate')) {
326
+ fields.push('readingTime: integer()');
327
+ }
328
+ const configUpdates = `import { config, list } from '@opensaas/stack-core';
329
+ import { text, select, relationship, timestamp${useTiptap ? '' : ', integer'} } from '@opensaas/stack-core/fields';
330
+ ${useTiptap ? "import { richText } from '@opensaas/stack-tiptap/fields';" : ''}
331
+
332
+ export default config({
333
+ lists: {
334
+ Post: list({
335
+ fields: {
336
+ ${fields.join(',\n ')},
337
+ },
338
+ access: {
339
+ operation: {
340
+ query: ({ session }) => {
341
+ ${hasStatus ? "if (!session) return { status: { equals: 'published' } };" : ''}
342
+ return true;
343
+ },
344
+ create: ({ session }) => !!session?.userId,
345
+ update: ({ session, item }) => session?.userId === item.authorId,
346
+ delete: ({ session, item }) =>
347
+ session?.role === 'admin' || session?.userId === item.authorId,
348
+ },
349
+ },
350
+ hooks: {
351
+ ${hasStatus
352
+ ? `resolveInput: async ({ resolvedData, operation }) => {
353
+ // Auto-set publishedAt when publishing
354
+ if (operation === 'update' && resolvedData.status === 'published' && !resolvedData.publishedAt) {
355
+ resolvedData.publishedAt = new Date();
356
+ }
357
+ return resolvedData;
358
+ },`
359
+ : ''}
360
+ },
361
+ }),
362
+ ${taxonomy.includes('Categories')
363
+ ? `Category: list({
364
+ fields: {
365
+ name: text({ validation: { isRequired: true } }),
366
+ slug: text({ validation: { isRequired: true } }),
367
+ posts: relationship({ ref: 'Post.category', many: true }),
368
+ },
369
+ }),`
370
+ : ''}
371
+ ${taxonomy.includes('Tags')
372
+ ? `Tag: list({
373
+ fields: {
374
+ name: text({ validation: { isRequired: true } }),
375
+ posts: relationship({ ref: 'Post.tags', many: true }),
376
+ },
377
+ }),`
378
+ : ''}
379
+ },
380
+ });`;
381
+ const files = [];
382
+ // Blog list page
383
+ files.push({
384
+ path: 'app/blog/page.tsx',
385
+ language: 'tsx',
386
+ description: 'Blog listing page',
387
+ content: `import { getContext } from '@/.opensaas/context';
388
+ import Link from 'next/link';
389
+
390
+ export default async function BlogPage() {
391
+ const context = await getContext();
392
+
393
+ const posts = await context.db.post.findMany({
394
+ ${hasStatus ? "where: { status: 'published' }," : ''}
395
+ orderBy: { ${hasStatus ? 'publishedAt' : 'createdAt'}: 'desc' },
396
+ include: { author: true },
397
+ });
398
+
399
+ return (
400
+ <div className="container mx-auto py-8">
401
+ <h1 className="text-4xl font-bold mb-8">Blog</h1>
402
+ <div className="grid gap-6">
403
+ {posts.map((post) => (
404
+ <article key={post.id} className="border rounded-lg p-6">
405
+ <Link href={\`/blog/\${post.slug}\`}>
406
+ <h2 className="text-2xl font-bold hover:underline">
407
+ {post.title}
408
+ </h2>
409
+ </Link>
410
+ ${postFields.includes('Excerpt/summary') ? '<p className="mt-2 text-gray-600">{post.excerpt}</p>' : ''}
411
+ <div className="mt-4 text-sm text-gray-500">
412
+ By {post.author.name} · ${hasStatus ? '{post.publishedAt?.toLocaleDateString()}' : '{post.createdAt.toLocaleDateString()}'}
413
+ </div>
414
+ </article>
415
+ ))}
416
+ </div>
417
+ </div>
418
+ );
419
+ }`,
420
+ });
421
+ // Blog post page
422
+ files.push({
423
+ path: 'app/blog/[slug]/page.tsx',
424
+ language: 'tsx',
425
+ description: 'Individual blog post page',
426
+ content: `import { getContext } from '@/.opensaas/context';
427
+ import { notFound } from 'next/navigation';
428
+
429
+ export default async function BlogPostPage({
430
+ params,
431
+ }: {
432
+ params: { slug: string };
433
+ }) {
434
+ const context = await getContext();
435
+
436
+ const post = await context.db.post.findFirst({
437
+ where: {
438
+ slug: params.slug,
439
+ ${hasStatus ? "status: 'published'," : ''}
440
+ },
441
+ include: { author: true },
442
+ });
443
+
444
+ if (!post) {
445
+ notFound();
446
+ }
447
+
448
+ return (
449
+ <article className="container mx-auto py-8 max-w-3xl">
450
+ <h1 className="text-4xl font-bold mb-4">{post.title}</h1>
451
+ <div className="text-gray-600 mb-8">
452
+ By {post.author.name} · ${hasStatus ? '{post.publishedAt?.toLocaleDateString()}' : '{post.createdAt.toLocaleDateString()}'}
453
+ </div>
454
+ ${useTiptap ? '<div className="prose max-w-none" dangerouslySetInnerHTML={{ __html: post.content }} />' : useMarkdown ? '<div className="prose max-w-none">{/* Render markdown here */}{post.content}</div>' : '<div className="prose max-w-none whitespace-pre-wrap">{post.content}</div>'}
455
+ </article>
456
+ );
457
+ }`,
458
+ });
459
+ const nextSteps = [
460
+ 'Copy the config updates to your `opensaas.config.ts`',
461
+ 'Add the `posts` relationship field to your User list',
462
+ useTiptap ? 'Install Tiptap package: `pnpm add @opensaas/stack-tiptap`' : null,
463
+ 'Create the blog pages in your `app/` directory',
464
+ 'Run `pnpm generate` to update Prisma schema',
465
+ 'Run `pnpm db:push` to update database',
466
+ 'Create your first blog post in the admin UI',
467
+ ].filter(Boolean);
468
+ const devGuideSection = `## Blog Feature
469
+
470
+ This project includes a blog system with:
471
+
472
+ - ${contentEditor} for writing posts
473
+ ${hasStatus ? '- Draft/publish workflow' : ''}
474
+ ${taxonomy.length > 0 ? `- ${taxonomy.join(' and ')} for organization` : ''}
475
+
476
+ ### Creating a Post
477
+
478
+ ${hasStatus
479
+ ? `Posts start as drafts and can be published when ready:
480
+
481
+ \`\`\`typescript
482
+ const post = await context.db.post.create({
483
+ data: {
484
+ title: 'My Post',
485
+ slug: 'my-post',
486
+ content: '...',
487
+ authorId: session.userId,
488
+ status: 'draft', // or 'published'
489
+ }
490
+ });
491
+ \`\`\``
492
+ : ''}
493
+
494
+ ### Access Control
495
+
496
+ - Anyone can read ${hasStatus ? 'published posts' : 'posts'}
497
+ - Only authenticated users can create posts
498
+ - Only authors can update their own posts
499
+ - Admins and authors can delete posts`;
500
+ return {
501
+ configUpdates,
502
+ files,
503
+ instructions: nextSteps,
504
+ devGuideSection,
505
+ envVars: useTiptap ? {} : undefined,
506
+ nextSteps,
507
+ };
508
+ }
509
+ /**
510
+ * Generate comments feature (stub - to be implemented)
511
+ */
512
+ generateComments() {
513
+ return {
514
+ configUpdates: '// Comments feature implementation coming soon',
515
+ files: [],
516
+ instructions: ['Feature implementation in progress'],
517
+ devGuideSection: '## Comments Feature\n\nComing soon...',
518
+ nextSteps: ['Feature implementation in progress'],
519
+ };
520
+ }
521
+ /**
522
+ * Generate file upload feature (stub - to be implemented)
523
+ */
524
+ generateFileUpload() {
525
+ return {
526
+ configUpdates: '// File upload feature implementation coming soon',
527
+ files: [],
528
+ instructions: ['Feature implementation in progress'],
529
+ devGuideSection: '## File Upload Feature\n\nComing soon...',
530
+ nextSteps: ['Feature implementation in progress'],
531
+ };
532
+ }
533
+ /**
534
+ * Generate semantic search feature (stub - to be implemented)
535
+ */
536
+ generateSemanticSearch() {
537
+ return {
538
+ configUpdates: '// Semantic search feature implementation coming soon',
539
+ files: [],
540
+ instructions: ['Feature implementation in progress'],
541
+ devGuideSection: '## Semantic Search Feature\n\nComing soon...',
542
+ nextSteps: ['Feature implementation in progress'],
543
+ };
544
+ }
545
+ }
546
+ //# sourceMappingURL=feature-generator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"feature-generator.js","sourceRoot":"","sources":["../../../../src/mcp/lib/generators/feature-generator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,80 @@
1
+ /**
2
+ * Feature catalog types for OpenSaaS Stack MCP server
3
+ */
4
+ export type QuestionType = 'text' | 'textarea' | 'select' | 'multiselect' | 'boolean';
5
+ export interface FeatureQuestion {
6
+ id: string;
7
+ text: string;
8
+ type: QuestionType;
9
+ required?: boolean;
10
+ options?: string[];
11
+ defaultValue?: string | boolean | string[];
12
+ dependsOn?: {
13
+ questionId: string;
14
+ value: string | boolean;
15
+ };
16
+ followUp?: {
17
+ if: string | boolean;
18
+ ask: string;
19
+ type: QuestionType;
20
+ options?: string[];
21
+ };
22
+ }
23
+ export interface Feature {
24
+ id: string;
25
+ name: string;
26
+ description: string;
27
+ includes: string[];
28
+ dependsOn?: string[];
29
+ questions: FeatureQuestion[];
30
+ category: 'authentication' | 'content' | 'storage' | 'search' | 'custom';
31
+ }
32
+ export interface WizardSession {
33
+ id: string;
34
+ featureId: string;
35
+ feature: Feature;
36
+ currentQuestionIndex: number;
37
+ answers: Record<string, string | boolean | string[]>;
38
+ followUpAnswers: Record<string, string | boolean | string[]>;
39
+ isComplete: boolean;
40
+ createdAt: Date;
41
+ updatedAt: Date;
42
+ }
43
+ export interface SessionStorage {
44
+ [sessionId: string]: WizardSession;
45
+ }
46
+ export interface GeneratedFile {
47
+ path: string;
48
+ content: string;
49
+ language: string;
50
+ description: string;
51
+ }
52
+ export interface FeatureImplementation {
53
+ configUpdates: string;
54
+ files: GeneratedFile[];
55
+ instructions: string[];
56
+ devGuideSection: string;
57
+ envVars?: Record<string, string>;
58
+ nextSteps: string[];
59
+ }
60
+ export interface DocumentationLookup {
61
+ topic: string;
62
+ content: string;
63
+ url: string;
64
+ codeExamples: string[];
65
+ relatedTopics: string[];
66
+ }
67
+ export interface ValidationError {
68
+ message: string;
69
+ location: string;
70
+ suggestion: string;
71
+ before?: string;
72
+ after?: string;
73
+ }
74
+ export interface ValidationResult {
75
+ valid: boolean;
76
+ errors: ValidationError[];
77
+ warnings: string[];
78
+ suggestions: string[];
79
+ }
80
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/mcp/lib/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Feature catalog types for OpenSaaS Stack MCP server
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/mcp/lib/types.ts"],"names":[],"mappings":"AAAA;;GAEG"}