@mars-stack/cli 0.2.0 → 1.0.2

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 (175) hide show
  1. package/dist/index.js +137 -12
  2. package/dist/index.js.map +1 -1
  3. package/package.json +4 -3
  4. package/template/.cursor/rules/composition-patterns.mdc +186 -0
  5. package/template/.cursor/rules/data-access.mdc +29 -0
  6. package/template/.cursor/rules/project-structure.mdc +34 -0
  7. package/template/.cursor/rules/security.mdc +25 -0
  8. package/template/.cursor/rules/testing.mdc +24 -0
  9. package/template/.cursor/rules/ui-conventions.mdc +29 -0
  10. package/template/.cursor/skills/add-api-route/SKILL.md +122 -0
  11. package/template/.cursor/skills/add-audit-log/SKILL.md +375 -0
  12. package/template/.cursor/skills/add-blog/SKILL.md +447 -0
  13. package/template/.cursor/skills/add-command-palette/SKILL.md +438 -0
  14. package/template/.cursor/skills/add-component/SKILL.md +158 -0
  15. package/template/.cursor/skills/add-crud-routes/SKILL.md +221 -0
  16. package/template/.cursor/skills/add-e2e-test/SKILL.md +227 -0
  17. package/template/.cursor/skills/add-error-boundary/SKILL.md +472 -0
  18. package/template/.cursor/skills/add-feature/SKILL.md +174 -0
  19. package/template/.cursor/skills/add-middleware/SKILL.md +135 -0
  20. package/template/.cursor/skills/add-page/SKILL.md +151 -0
  21. package/template/.cursor/skills/add-prisma-model/SKILL.md +148 -0
  22. package/template/.cursor/skills/add-protected-resource/SKILL.md +192 -0
  23. package/template/.cursor/skills/add-role/SKILL.md +156 -0
  24. package/template/.cursor/skills/add-server-action/SKILL.md +167 -0
  25. package/template/.cursor/skills/add-webhook/SKILL.md +192 -0
  26. package/template/.cursor/skills/build-complete-feature/SKILL.md +227 -0
  27. package/template/.cursor/skills/build-dashboard/SKILL.md +211 -0
  28. package/template/.cursor/skills/build-data-table/SKILL.md +283 -0
  29. package/template/.cursor/skills/build-form/SKILL.md +231 -0
  30. package/template/.cursor/skills/build-landing-page/SKILL.md +248 -0
  31. package/template/.cursor/skills/configure-ai/SKILL.md +617 -0
  32. package/template/.cursor/skills/configure-analytics/SKILL.md +413 -0
  33. package/template/.cursor/skills/configure-dark-mode/SKILL.md +309 -0
  34. package/template/.cursor/skills/configure-email/SKILL.md +170 -0
  35. package/template/.cursor/skills/configure-email-verification/SKILL.md +333 -0
  36. package/template/.cursor/skills/configure-feature-flags/SKILL.md +361 -0
  37. package/template/.cursor/skills/configure-i18n/SKILL.md +518 -0
  38. package/template/.cursor/skills/configure-jobs/SKILL.md +500 -0
  39. package/template/.cursor/skills/configure-magic-links/SKILL.md +385 -0
  40. package/template/.cursor/skills/configure-multi-tenancy/SKILL.md +611 -0
  41. package/template/.cursor/skills/configure-notifications/SKILL.md +569 -0
  42. package/template/.cursor/skills/configure-oauth/SKILL.md +217 -0
  43. package/template/.cursor/skills/configure-onboarding/SKILL.md +483 -0
  44. package/template/.cursor/skills/configure-payments/SKILL.md +243 -0
  45. package/template/.cursor/skills/configure-realtime/SKILL.md +733 -0
  46. package/template/.cursor/skills/configure-search/SKILL.md +581 -0
  47. package/template/.cursor/skills/configure-storage/SKILL.md +273 -0
  48. package/template/.cursor/skills/configure-two-factor/SKILL.md +518 -0
  49. package/template/.cursor/skills/create-execution-plan/SKILL.md +204 -0
  50. package/template/.cursor/skills/create-seed/SKILL.md +191 -0
  51. package/template/.cursor/skills/deploy-to-vercel/SKILL.md +300 -0
  52. package/template/.cursor/skills/design-tokens/SKILL.md +138 -0
  53. package/template/.cursor/skills/mars-capture-conversation-context/SKILL.md +119 -0
  54. package/template/.cursor/skills/setup-billing/SKILL.md +322 -0
  55. package/template/.cursor/skills/setup-project/SKILL.md +104 -0
  56. package/template/.cursor/skills/setup-teams/SKILL.md +682 -0
  57. package/template/.cursor/skills/test-api-route/SKILL.md +219 -0
  58. package/template/.cursor/skills/update-architecture-docs/SKILL.md +99 -0
  59. package/template/AGENTS.md +104 -0
  60. package/template/ARCHITECTURE.md +102 -0
  61. package/template/docs/QUALITY_SCORE.md +20 -0
  62. package/template/docs/design-docs/conversation-as-system-record.md +70 -0
  63. package/template/docs/design-docs/core-beliefs.md +43 -0
  64. package/template/docs/design-docs/index.md +8 -0
  65. package/template/docs/exec-plans/active/.gitkeep +0 -0
  66. package/template/docs/exec-plans/completed/.gitkeep +0 -0
  67. package/template/docs/exec-plans/tech-debt.md +7 -0
  68. package/template/docs/generated/.gitkeep +0 -0
  69. package/template/docs/product-specs/index.md +7 -0
  70. package/template/docs/references/index.md +18 -0
  71. package/template/e2e/api.spec.ts +20 -0
  72. package/template/e2e/auth.spec.ts +24 -0
  73. package/template/e2e/public.spec.ts +25 -0
  74. package/template/eslint.config.mjs +24 -0
  75. package/template/next-env.d.ts +6 -0
  76. package/template/next.config.ts +45 -0
  77. package/template/package.json +80 -0
  78. package/template/playwright.config.ts +31 -0
  79. package/template/postcss.config.mjs +8 -0
  80. package/template/prisma/generated/prisma/browser.ts +49 -0
  81. package/template/prisma/generated/prisma/client.ts +73 -0
  82. package/template/prisma/generated/prisma/commonInputTypes.ts +406 -0
  83. package/template/prisma/generated/prisma/enums.ts +15 -0
  84. package/template/prisma/generated/prisma/internal/class.ts +254 -0
  85. package/template/prisma/generated/prisma/internal/prismaNamespace.ts +1240 -0
  86. package/template/prisma/generated/prisma/internal/prismaNamespaceBrowser.ts +190 -0
  87. package/template/prisma/generated/prisma/models/Account.ts +1543 -0
  88. package/template/prisma/generated/prisma/models/File.ts +1529 -0
  89. package/template/prisma/generated/prisma/models/Session.ts +1415 -0
  90. package/template/prisma/generated/prisma/models/Subscription.ts +1455 -0
  91. package/template/prisma/generated/prisma/models/User.ts +2235 -0
  92. package/template/prisma/generated/prisma/models/VerificationToken.ts +1099 -0
  93. package/template/prisma/generated/prisma/models.ts +17 -0
  94. package/template/prisma/schema/auth.prisma +69 -0
  95. package/template/prisma/schema/base.prisma +8 -0
  96. package/template/prisma/schema/file.prisma +15 -0
  97. package/template/prisma/schema/subscription.prisma +17 -0
  98. package/template/prisma.config.ts +13 -0
  99. package/template/scripts/check-architecture.ts +221 -0
  100. package/template/scripts/check-doc-freshness.ts +242 -0
  101. package/template/scripts/ensure-db.mjs +291 -0
  102. package/template/scripts/generate-docs.ts +143 -0
  103. package/template/scripts/generate-env-example.ts +89 -0
  104. package/template/scripts/seed.ts +56 -0
  105. package/template/scripts/update-quality-score.ts +263 -0
  106. package/template/src/__tests__/architecture.test.ts +114 -0
  107. package/template/src/app/(auth)/forgotten-password/page.tsx +92 -0
  108. package/template/src/app/(auth)/layout.tsx +11 -0
  109. package/template/src/app/(auth)/register/page.tsx +162 -0
  110. package/template/src/app/(auth)/reset-password/page.tsx +109 -0
  111. package/template/src/app/(auth)/sign-in/page.tsx +122 -0
  112. package/template/src/app/(auth)/verify/[token]/page.tsx +87 -0
  113. package/template/src/app/(auth)/verify/page.tsx +56 -0
  114. package/template/src/app/(protected)/admin/page.tsx +108 -0
  115. package/template/src/app/(protected)/dashboard/loading.tsx +20 -0
  116. package/template/src/app/(protected)/dashboard/page.tsx +22 -0
  117. package/template/src/app/(protected)/layout.tsx +262 -0
  118. package/template/src/app/(protected)/settings/page.tsx +370 -0
  119. package/template/src/app/api/auth/forgot/route.ts +63 -0
  120. package/template/src/app/api/auth/login/route.ts +121 -0
  121. package/template/src/app/api/auth/logout/route.ts +19 -0
  122. package/template/src/app/api/auth/me/route.ts +30 -0
  123. package/template/src/app/api/auth/reset/route.ts +45 -0
  124. package/template/src/app/api/auth/signup/route.ts +85 -0
  125. package/template/src/app/api/auth/verify/route.ts +46 -0
  126. package/template/src/app/api/csrf/route.ts +12 -0
  127. package/template/src/app/api/health/route.ts +10 -0
  128. package/template/src/app/api/protected/admin/users/route.ts +24 -0
  129. package/template/src/app/api/protected/billing/checkout/route.ts +83 -0
  130. package/template/src/app/api/protected/billing/portal/route.ts +39 -0
  131. package/template/src/app/api/protected/files/[fileId]/route.ts +86 -0
  132. package/template/src/app/api/protected/files/upload/route.ts +64 -0
  133. package/template/src/app/api/protected/user/password/route.ts +63 -0
  134. package/template/src/app/api/protected/user/profile/route.ts +35 -0
  135. package/template/src/app/api/protected/user/sessions/[sessionId]/route.ts +33 -0
  136. package/template/src/app/api/protected/user/sessions/route.ts +22 -0
  137. package/template/src/app/api/readiness/route.ts +15 -0
  138. package/template/src/app/api/webhooks/stripe/route.ts +166 -0
  139. package/template/src/app/error.tsx +33 -0
  140. package/template/src/app/layout.tsx +29 -0
  141. package/template/src/app/not-found.tsx +20 -0
  142. package/template/src/app/page.tsx +136 -0
  143. package/template/src/app/privacy/page.tsx +178 -0
  144. package/template/src/app/providers.tsx +8 -0
  145. package/template/src/app/terms/page.tsx +139 -0
  146. package/template/src/config/app.config.ts +70 -0
  147. package/template/src/config/routes.ts +17 -0
  148. package/template/src/features/admin/index.ts +11 -0
  149. package/template/src/features/admin/permissions.ts +64 -0
  150. package/template/src/features/auth/context/AuthContext.tsx +96 -0
  151. package/template/src/features/auth/context/index.ts +2 -0
  152. package/template/src/features/auth/index.ts +3 -0
  153. package/template/src/features/auth/server/consent.ts +66 -0
  154. package/template/src/features/auth/server/session-revocation.ts +20 -0
  155. package/template/src/features/auth/server/sessions.ts +66 -0
  156. package/template/src/features/auth/server/user.ts +166 -0
  157. package/template/src/features/auth/types.ts +19 -0
  158. package/template/src/features/auth/validators.ts +29 -0
  159. package/template/src/features/billing/server/index.ts +66 -0
  160. package/template/src/features/billing/types.ts +43 -0
  161. package/template/src/features/uploads/server/index.ts +49 -0
  162. package/template/src/features/uploads/types.ts +26 -0
  163. package/template/src/lib/core/email/templates/base-layout.ts +122 -0
  164. package/template/src/lib/core/email/templates/index.ts +4 -0
  165. package/template/src/lib/core/email/templates/password-reset-email.ts +42 -0
  166. package/template/src/lib/core/email/templates/verification-email.ts +41 -0
  167. package/template/src/lib/core/email/templates/welcome-email.ts +40 -0
  168. package/template/src/lib/mars.ts +56 -0
  169. package/template/src/lib/prisma.ts +19 -0
  170. package/template/src/proxy.ts +92 -0
  171. package/template/src/styles/brand.css +15 -0
  172. package/template/src/styles/globals.css +7 -0
  173. package/template/tsconfig.json +59 -0
  174. package/template/vitest.config.ts +41 -0
  175. package/template/vitest.setup.ts +24 -0
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/utils/logger.ts","../src/utils/rollback.ts","../src/utils/dependencies.ts","../src/generators/features/blog.ts","../src/generators/features/dark-mode.ts","../src/utils/prisma.ts","../src/generators/features/notifications.ts","../src/generators/features/analytics.ts","../src/generators/features/command-palette.ts","../src/generators/features/onboarding.ts","../src/generators/features/search.ts","../src/generators/features/realtime.ts","../src/generators/features/ai.ts","../src/generators/features/cookie-consent.ts","../src/generators/features/coming-soon.ts","../src/generators/features/sentry.ts","../src/generators/features/feature-flags.ts","../src/index.ts","../src/commands/create.ts","../src/utils/template.ts","../src/prompts/project-info.ts","../src/prompts/features.ts","../src/prompts/services.ts","../src/prompts/theme.ts","../src/generators/scaffold.ts","../src/generators/app-config.ts","../src/generators/env.ts","../src/generators/generate-selected.ts","../src/utils/telemetry.ts","../src/commands/doctor.ts","../src/commands/add.ts","../src/utils/doc-updater.ts","../src/commands/configure.ts","../src/commands/deploy.ts","../src/commands/upgrade.ts"],"sourcesContent":["import pc from 'picocolors';\n\nexport const log = {\n info: (msg: string) => console.log(pc.cyan('ℹ'), msg),\n success: (msg: string) => console.log(pc.green('✔'), msg),\n warn: (msg: string) => console.warn(pc.yellow('⚠'), msg),\n error: (msg: string) => console.error(pc.red('✖'), msg),\n step: (msg: string) => console.log(pc.blue('→'), msg),\n blank: () => console.log(),\n title: (msg: string) => {\n log.blank();\n console.log(pc.bold(pc.magenta(msg)));\n log.blank();\n },\n banner: () => {\n console.log(\n pc.bold(\n pc.magenta(`\n ╔══════════════════════════════════════════╗\n ║ MARS · Modular Architecture for ║\n ║ Rapid SaaS ║\n ╚══════════════════════════════════════════╝`),\n ),\n );\n log.blank();\n },\n};\n","import fs from 'fs-extra';\nimport path from 'node:path';\nimport os from 'node:os';\n\ninterface RollbackManifest {\n filesCreated: string[];\n filesModified: Array<{ path: string; backup: string }>;\n depsInstalled: string[];\n}\n\ninterface RollbackContext {\n trackCreatedFile(filePath: string): void;\n trackModifiedFile(filePath: string): Promise<void>;\n trackInstalledDep(depName: string): void;\n rollback(): Promise<void>;\n commit(): Promise<void>;\n}\n\nexport function createRollbackContext(): RollbackContext {\n const manifest: RollbackManifest = {\n filesCreated: [],\n filesModified: [],\n depsInstalled: [],\n };\n\n const backupDir = path.join(os.tmpdir(), `mars-rollback-${Date.now()}`);\n\n function trackCreatedFile(filePath: string): void {\n manifest.filesCreated.push(filePath);\n }\n\n async function trackModifiedFile(filePath: string): Promise<void> {\n if (!(await fs.pathExists(filePath))) return;\n\n await fs.ensureDir(backupDir);\n const backupPath = path.join(backupDir, `${manifest.filesModified.length}-${path.basename(filePath)}`);\n await fs.copy(filePath, backupPath);\n manifest.filesModified.push({ path: filePath, backup: backupPath });\n }\n\n function trackInstalledDep(depName: string): void {\n manifest.depsInstalled.push(depName);\n }\n\n async function rollback(): Promise<void> {\n for (const filePath of manifest.filesCreated.reverse()) {\n try {\n await fs.remove(filePath);\n } catch {\n // Best-effort cleanup\n }\n }\n\n for (const { path: originalPath, backup } of manifest.filesModified) {\n try {\n await fs.copy(backup, originalPath, { overwrite: true });\n } catch {\n // Best-effort restore\n }\n }\n\n await cleanupBackups();\n }\n\n async function commit(): Promise<void> {\n await cleanupBackups();\n }\n\n async function cleanupBackups(): Promise<void> {\n if (await fs.pathExists(backupDir)) {\n try {\n await fs.remove(backupDir);\n } catch {\n // Non-critical\n }\n }\n }\n\n return {\n trackCreatedFile,\n trackModifiedFile,\n trackInstalledDep,\n rollback,\n commit,\n };\n}\n","import fs from 'fs-extra';\nimport path from 'node:path';\n\nexport async function addDependencies(\n projectRoot: string,\n deps: Record<string, string>,\n dev = false,\n): Promise<void> {\n const pkgPath = path.join(projectRoot, 'package.json');\n if (!(await fs.pathExists(pkgPath))) return;\n\n const pkg = await fs.readJson(pkgPath);\n const key = dev ? 'devDependencies' : 'dependencies';\n pkg[key] = { ...pkg[key], ...deps };\n await fs.writeJson(pkgPath, pkg, { spaces: 2 });\n}\n","import fs from 'fs-extra';\nimport path from 'node:path';\nimport { log } from '../../utils/logger.js';\nimport { createRollbackContext } from '../../utils/rollback.js';\nimport { addDependencies } from '../../utils/dependencies.js';\n\nconst GENERATOR_VERSION = '0.1.0';\nconst STAMP = `// @mars-generated blog@${GENERATOR_VERSION}`;\n\nexport async function generateBlog(projectRoot: string): Promise<void> {\n const featureDir = path.join(projectRoot, 'src', 'features', 'blog');\n\n if (await fs.pathExists(featureDir)) {\n log.error('Blog feature already exists at src/features/blog/');\n return;\n }\n\n const ctx = createRollbackContext();\n\n try {\n const files: Record<string, string> = {\n 'src/features/blog/validation/schemas.ts': schemas(),\n 'src/features/blog/types.ts': types(),\n 'src/features/blog/server/index.ts': serverLogic(),\n 'src/features/blog/components/PostCard.tsx': postCard(),\n 'src/features/blog/components/PostHeader.tsx': postHeader(),\n 'src/features/blog/components/index.ts': componentIndex(),\n 'src/app/blog/page.tsx': blogListingPage(),\n 'src/app/blog/[slug]/page.tsx': blogPostPage(),\n 'src/app/feed.xml/route.ts': rssFeedRoute(),\n 'content/blog/getting-started.mdx': samplePostGettingStarted(),\n 'content/blog/welcome.mdx': samplePostWelcome(),\n };\n\n let count = 0;\n for (const [filePath, content] of Object.entries(files)) {\n const fullPath = path.join(projectRoot, filePath);\n ctx.trackCreatedFile(fullPath);\n await fs.ensureDir(path.dirname(fullPath));\n await fs.writeFile(fullPath, content);\n count++;\n }\n\n await addDependencies(projectRoot, {\n 'gray-matter': '^4.0.0',\n 'reading-time': '^1.5.0',\n '@mdx-js/mdx': '^3.0.0',\n '@mdx-js/react': '^3.0.0',\n 'remark-gfm': '^4.0.0',\n });\n await addDependencies(projectRoot, { '@types/mdx': '^2.0.0' }, true);\n await setConfigFlag(projectRoot, ctx);\n await ctx.commit();\n\n log.success(`Generated blog feature with ${count} files`);\n log.blank();\n log.step('src/features/blog/ — validation, types, server logic, components');\n log.step('src/app/blog/ — listing page and [slug] post page');\n log.step('src/app/feed.xml/ — RSS feed route');\n log.step('content/blog/ — sample MDX posts');\n log.blank();\n } catch (error) {\n await ctx.rollback();\n throw error;\n }\n}\n\nasync function setConfigFlag(projectRoot: string, ctx: { trackModifiedFile: (p: string) => Promise<void> }): Promise<void> {\n const configPath = path.join(projectRoot, 'src', 'config', 'app.config.ts');\n if (!(await fs.pathExists(configPath))) return;\n\n await ctx.trackModifiedFile(configPath);\n const content = await fs.readFile(configPath, 'utf-8');\n const updated = content.replace(/blog:\\s*false/, 'blog: true');\n await fs.writeFile(configPath, updated);\n}\n\nfunction schemas(): string {\n return `${STAMP}\nimport { z } from 'zod';\n\nexport const frontmatterSchema = z.object({\n title: z.string().min(1),\n description: z.string().min(1).max(160),\n date: z.string().refine((val) => !isNaN(Date.parse(val)), 'Invalid date'),\n author: z.string().default('Team'),\n tags: z.array(z.string()).default([]),\n image: z.string().optional(),\n published: z.boolean().default(true),\n});\n\nexport type Frontmatter = z.infer<typeof frontmatterSchema>;\n`;\n}\n\nfunction types(): string {\n return `${STAMP}\nimport type { Frontmatter } from './validation/schemas';\n\nexport interface BlogPost {\n slug: string;\n frontmatter: Frontmatter;\n content: string;\n readingTime: string;\n excerpt: string;\n}\n`;\n}\n\nfunction serverLogic(): string {\n return `${STAMP}\nimport 'server-only';\n\nimport fs from 'fs';\nimport path from 'path';\nimport matter from 'gray-matter';\nimport readingTime from 'reading-time';\nimport { frontmatterSchema } from '../validation/schemas';\nimport type { BlogPost } from '../types';\n\nconst CONTENT_DIR = path.join(process.cwd(), 'content', 'blog');\n\nexport function getAllPosts(): BlogPost[] {\n if (!fs.existsSync(CONTENT_DIR)) return [];\n\n const files = fs.readdirSync(CONTENT_DIR).filter((f) => f.endsWith('.mdx'));\n\n const posts = files\n .map((filename) => {\n const slug = filename.replace(/\\\\.mdx$/, '');\n const filePath = path.join(CONTENT_DIR, filename);\n const raw = fs.readFileSync(filePath, 'utf-8');\n const { data, content } = matter(raw);\n\n const parsed = frontmatterSchema.safeParse(data);\n if (!parsed.success) {\n console.warn(\\`Invalid frontmatter in \\${filename}:\\`, parsed.error.message);\n return null;\n }\n\n if (!parsed.data.published) return null;\n\n const stats = readingTime(content);\n const excerpt = content.replace(/^#+\\\\s.*$/gm, '').trim().slice(0, 200) + '...';\n\n return {\n slug,\n frontmatter: parsed.data,\n content,\n readingTime: stats.text,\n excerpt,\n };\n })\n .filter(Boolean) as BlogPost[];\n\n return posts.sort(\n (a, b) => new Date(b.frontmatter.date).getTime() - new Date(a.frontmatter.date).getTime(),\n );\n}\n\nexport function getPostBySlug(slug: string): BlogPost | null {\n const filePath = path.join(CONTENT_DIR, \\`\\${slug}.mdx\\`);\n\n if (!fs.existsSync(filePath)) return null;\n\n const raw = fs.readFileSync(filePath, 'utf-8');\n const { data, content } = matter(raw);\n\n const parsed = frontmatterSchema.safeParse(data);\n if (!parsed.success) return null;\n\n const stats = readingTime(content);\n const excerpt = content.replace(/^#+\\\\s.*$/gm, '').trim().slice(0, 200) + '...';\n\n return {\n slug,\n frontmatter: parsed.data,\n content,\n readingTime: stats.text,\n excerpt,\n };\n}\n\nexport function generateRSSFeed(posts: BlogPost[], siteUrl: string): string {\n const items = posts\n .map(\n (post) => \\`\n <item>\n <title><![CDATA[\\${post.frontmatter.title}]]></title>\n <link>\\${siteUrl}/blog/\\${post.slug}</link>\n <guid isPermaLink=\"true\">\\${siteUrl}/blog/\\${post.slug}</guid>\n <description><![CDATA[\\${post.frontmatter.description}]]></description>\n <pubDate>\\${new Date(post.frontmatter.date).toUTCString()}</pubDate>\n \\${post.frontmatter.tags.map((tag) => \\`<category>\\${tag}</category>\\`).join('\\\\n ')}\n </item>\\`,\n )\n .join('\\\\n');\n\n return \\`<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<rss version=\"2.0\" xmlns:atom=\"http://www.w3.org/2005/Atom\">\n <channel>\n <title>Blog</title>\n <link>\\${siteUrl}/blog</link>\n <description>Latest posts</description>\n <atom:link href=\"\\${siteUrl}/feed.xml\" rel=\"self\" type=\"application/rss+xml\" />\n \\${items}\n </channel>\n</rss>\\`;\n}\n`;\n}\n\nfunction postCard(): string {\n return `${STAMP}\nimport Link from 'next/link';\nimport type { BlogPost } from '../types';\n\nexport function PostCard({ post }: { post: BlogPost }) {\n const date = new Date(post.frontmatter.date).toLocaleDateString('en-US', {\n year: 'numeric',\n month: 'long',\n day: 'numeric',\n });\n\n return (\n <article className=\"group\">\n <Link href={\\`/blog/\\${post.slug}\\`} className=\"block\">\n <div className=\"rounded-2xl border border-border-default bg-surface-card p-6 transition-all hover:border-brand-primary hover:shadow-md\">\n <div className=\"flex items-center gap-3 text-sm text-text-muted\">\n <time dateTime={post.frontmatter.date}>{date}</time>\n <span aria-hidden=\"true\">&middot;</span>\n <span>{post.readingTime}</span>\n </div>\n <h2 className=\"mt-2 text-xl font-semibold text-text-primary group-hover:text-brand-primary\">\n {post.frontmatter.title}\n </h2>\n <p className=\"mt-2 text-text-secondary\">{post.frontmatter.description}</p>\n {post.frontmatter.tags.length > 0 && (\n <div className=\"mt-3 flex flex-wrap gap-2\">\n {post.frontmatter.tags.map((tag) => (\n <span\n key={tag}\n className=\"rounded-full bg-surface-background px-2.5 py-0.5 text-xs font-medium text-text-secondary\"\n >\n {tag}\n </span>\n ))}\n </div>\n )}\n </div>\n </Link>\n </article>\n );\n}\n`;\n}\n\nfunction postHeader(): string {\n return `${STAMP}\nimport Link from 'next/link';\n\ninterface PostHeaderProps {\n title: string;\n date: string;\n author: string;\n readingTime: string;\n tags: string[];\n}\n\nexport function PostHeader({ title, date, author, readingTime, tags }: PostHeaderProps) {\n const formattedDate = new Date(date).toLocaleDateString('en-US', {\n year: 'numeric',\n month: 'long',\n day: 'numeric',\n });\n\n return (\n <header>\n <Link\n href=\"/blog\"\n className=\"mb-8 inline-flex items-center gap-1.5 text-sm text-text-secondary transition-colors hover:text-text-primary\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" strokeWidth={1.5} stroke=\"currentColor\" className=\"size-4\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M15.75 19.5 8.25 12l7.5-7.5\" />\n </svg>\n Back to blog\n </Link>\n\n <h1 className=\"text-4xl font-bold tracking-tight text-text-primary sm:text-5xl\">\n {title}\n </h1>\n\n <div className=\"mt-4 flex flex-wrap items-center gap-3 text-sm text-text-muted\">\n <span>{author}</span>\n <span aria-hidden=\"true\">&middot;</span>\n <time dateTime={date}>{formattedDate}</time>\n <span aria-hidden=\"true\">&middot;</span>\n <span>{readingTime}</span>\n </div>\n\n {tags.length > 0 && (\n <div className=\"mt-4 flex flex-wrap gap-2\">\n {tags.map((tag) => (\n <span\n key={tag}\n className=\"rounded-full bg-surface-card px-3 py-1 text-xs font-medium text-text-secondary\"\n >\n {tag}\n </span>\n ))}\n </div>\n )}\n </header>\n );\n}\n`;\n}\n\nfunction componentIndex(): string {\n return `${STAMP}\nexport { PostCard } from './PostCard';\nexport { PostHeader } from './PostHeader';\n`;\n}\n\nfunction blogListingPage(): string {\n return `${STAMP}\nimport type { Metadata } from 'next';\nimport Link from 'next/link';\nimport { getAllPosts } from '@/features/blog/server';\nimport { PostCard } from '@/features/blog/components';\nimport { appConfig } from '@/config/app.config';\n\nexport const metadata: Metadata = {\n title: 'Blog',\n description: \\`Latest articles and updates from \\${appConfig.name}\\`,\n};\n\nexport default function BlogPage() {\n const posts = getAllPosts();\n\n return (\n <div className=\"flex min-h-screen flex-col bg-surface-background\">\n <nav className=\"border-b border-border-default bg-surface-card px-6 py-4\">\n <div className=\"mx-auto flex max-w-4xl items-center justify-between\">\n <Link href=\"/\" className=\"text-lg font-semibold text-text-primary\">\n {appConfig.name}\n </Link>\n <Link href=\"/blog\" className=\"text-sm font-medium text-brand-primary\">\n Blog\n </Link>\n </div>\n </nav>\n\n <main className=\"mx-auto w-full max-w-4xl flex-1 px-4 py-12\">\n <h1 className=\"text-4xl font-bold tracking-tight text-text-primary\">Blog</h1>\n <p className=\"mt-2 text-lg text-text-secondary\">Latest articles and updates</p>\n\n <div className=\"mt-10 space-y-6\">\n {posts.length === 0 && (\n <div className=\"rounded-2xl border border-border-default bg-surface-card p-12 text-center\">\n <p className=\"text-text-muted\">No posts yet. Add .mdx files to content/blog/.</p>\n </div>\n )}\n {posts.map((post) => (\n <PostCard key={post.slug} post={post} />\n ))}\n </div>\n </main>\n </div>\n );\n}\n`;\n}\n\nfunction blogPostPage(): string {\n return `${STAMP}\nimport type { Metadata } from 'next';\nimport { notFound } from 'next/navigation';\nimport { compile, run } from '@mdx-js/mdx';\nimport * as runtime from 'react/jsx-runtime';\nimport remarkGfm from 'remark-gfm';\nimport { getAllPosts, getPostBySlug } from '@/features/blog/server';\nimport { PostHeader } from '@/features/blog/components';\n\ninterface PostPageProps {\n params: Promise<{ slug: string }>;\n}\n\nexport async function generateStaticParams() {\n const posts = getAllPosts();\n return posts.map((post) => ({ slug: post.slug }));\n}\n\nexport async function generateMetadata({ params }: PostPageProps): Promise<Metadata> {\n const { slug } = await params;\n const post = getPostBySlug(slug);\n if (!post) return {};\n\n const siteUrl = process.env.APP_URL || 'http://localhost:3000';\n\n return {\n title: post.frontmatter.title,\n description: post.frontmatter.description,\n openGraph: {\n title: post.frontmatter.title,\n description: post.frontmatter.description,\n type: 'article',\n publishedTime: post.frontmatter.date,\n url: \\`\\${siteUrl}/blog/\\${slug}\\`,\n images: post.frontmatter.image ? [{ url: post.frontmatter.image }] : [],\n },\n };\n}\n\nexport default async function PostPage({ params }: PostPageProps) {\n const { slug } = await params;\n const post = getPostBySlug(slug);\n if (!post) notFound();\n\n const siteUrl = process.env.APP_URL || 'http://localhost:3000';\n\n const compiled = await compile(post.content, {\n outputFormat: 'function-body',\n remarkPlugins: [remarkGfm],\n });\n\n const { default: MDXContent } = await run(String(compiled), {\n ...runtime,\n baseUrl: import.meta.url,\n } as Parameters<typeof run>[1]);\n\n const jsonLd = {\n '@context': 'https://schema.org',\n '@type': 'BlogPosting',\n headline: post.frontmatter.title,\n description: post.frontmatter.description,\n datePublished: post.frontmatter.date,\n author: { '@type': 'Person', name: post.frontmatter.author },\n url: \\`\\${siteUrl}/blog/\\${slug}\\`,\n };\n\n return (\n <article className=\"mx-auto max-w-3xl px-4 py-12\">\n <script\n type=\"application/ld+json\"\n dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}\n />\n <PostHeader\n title={post.frontmatter.title}\n date={post.frontmatter.date}\n author={post.frontmatter.author}\n readingTime={post.readingTime}\n tags={post.frontmatter.tags}\n />\n <div className=\"prose prose-neutral dark:prose-invert mt-10 max-w-none prose-headings:text-text-primary prose-p:text-text-secondary prose-a:text-brand-primary prose-strong:text-text-primary prose-code:text-text-primary\">\n <MDXContent />\n </div>\n </article>\n );\n}\n`;\n}\n\nfunction rssFeedRoute(): string {\n return `${STAMP}\nimport { getAllPosts, generateRSSFeed } from '@/features/blog/server';\n\nexport async function GET() {\n const posts = getAllPosts();\n const siteUrl = process.env.APP_URL || 'http://localhost:3000';\n const feed = generateRSSFeed(posts, siteUrl);\n\n return new Response(feed, {\n headers: {\n 'Content-Type': 'application/xml',\n 'Cache-Control': 'public, max-age=3600, s-maxage=3600',\n },\n });\n}\n`;\n}\n\nfunction samplePostGettingStarted(): string {\n return `---\ntitle: \"Getting Started with Your App\"\ndescription: \"A quick guide to setting up and customizing your new application.\"\ndate: \"${new Date().toISOString().split('T')[0]}\"\nauthor: \"Team\"\ntags: [\"getting-started\", \"tutorial\"]\npublished: true\n---\n\n# Getting Started\n\nWelcome to your new application! This guide walks you through the basics.\n\n## Prerequisites\n\nMake sure you have the following installed:\n\n- **Node.js** 20+ (we recommend using nvm)\n- **Yarn** or npm for package management\n\n## Setting Up\n\nInstall dependencies and start the dev server:\n\n\\`\\`\\`bash\nyarn install\nyarn dev\n\\`\\`\\`\n\nYour app will be available at [http://localhost:3000](http://localhost:3000).\n\n## Project Structure\n\n- \\`src/app/\\` — Next.js app router pages\n- \\`src/features/\\` — Feature modules with components, server logic, and validation\n- \\`src/config/\\` — Application configuration\n- \\`src/lib/\\` — Shared utilities and core infrastructure\n\n## Next Steps\n\n- Explore the **dashboard** after signing up\n- Customize your theme in \\`src/config/app.config.ts\\`\n- Add new blog posts by creating \\`.mdx\\` files in \\`content/blog/\\`\n`;\n}\n\nfunction samplePostWelcome(): string {\n const yesterday = new Date(Date.now() - 86400000).toISOString().split('T')[0];\n return `---\ntitle: \"Welcome to the Blog\"\ndescription: \"Your blog is set up and ready for content.\"\ndate: \"${yesterday}\"\nauthor: \"Team\"\ntags: [\"announcement\"]\npublished: true\n---\n\n# Welcome\n\nYour blog is live! This post was generated automatically when the blog feature was added.\n\n## Adding New Posts\n\nCreate \\`.mdx\\` files in the \\`content/blog/\\` directory with YAML frontmatter:\n\n\\`\\`\\`yaml\n---\ntitle: \"My Post Title\"\ndescription: \"A short description (max 160 chars).\"\ndate: \"2026-01-15\"\nauthor: \"Your Name\"\ntags: [\"topic\"]\npublished: true\n---\n\\`\\`\\`\n\nPosts with \\`published: false\\` are excluded from the listing and RSS feed.\n\n## Features\n\n- **MDX support** — Write content with Markdown and JSX components\n- **Frontmatter validation** — Zod schema ensures all posts have valid metadata\n- **RSS feed** — Available at \\`/feed.xml\\`\n- **SEO** — JSON-LD structured data and Open Graph tags on every post\n- **Reading time** — Automatically calculated from content length\n`;\n}\n","import fs from 'fs-extra';\nimport path from 'node:path';\nimport { log } from '../../utils/logger.js';\nimport { createRollbackContext } from '../../utils/rollback.js';\n\nconst GENERATOR_VERSION = '0.1.0';\nconst STAMP = `// @mars-generated dark-mode@${GENERATOR_VERSION}`;\n\nexport async function generateDarkMode(projectRoot: string): Promise<void> {\n const featureDir = path.join(projectRoot, 'src', 'features', 'dark-mode');\n\n if (await fs.pathExists(featureDir)) {\n log.error('Dark mode feature already exists at src/features/dark-mode/');\n return;\n }\n\n const ctx = createRollbackContext();\n\n try {\n const files: Record<string, string> = {\n 'src/lib/shared/components/providers/ThemeProvider.tsx': themeProvider(),\n 'src/lib/shared/components/patterns/ThemeToggle.tsx': themeToggle(),\n 'src/lib/shared/components/patterns/ThemeToggleSimple.tsx': themeToggleSimple(),\n 'src/features/dark-mode/theme-script.ts': themeScript(),\n 'src/features/dark-mode/index.ts': barrelExport(),\n };\n\n let count = 0;\n for (const [filePath, content] of Object.entries(files)) {\n const fullPath = path.join(projectRoot, filePath);\n ctx.trackCreatedFile(fullPath);\n await fs.ensureDir(path.dirname(fullPath));\n await fs.writeFile(fullPath, content);\n count++;\n }\n\n await setConfigFlag(projectRoot, ctx);\n await ctx.commit();\n\n log.success(`Generated dark mode feature with ${count} files`);\n log.blank();\n log.step('src/lib/shared/components/providers/ThemeProvider.tsx — context, hook, persistence');\n log.step('src/lib/shared/components/patterns/ThemeToggle.tsx — three-option toggle');\n log.step('src/lib/shared/components/patterns/ThemeToggleSimple.tsx — simple sun/moon toggle');\n log.step('src/features/dark-mode/theme-script.ts — FOUC prevention script');\n log.step('src/features/dark-mode/index.ts — barrel exports');\n log.blank();\n log.warn('Complete setup in your root layout (src/app/layout.tsx):');\n log.step('1. Add suppressHydrationWarning to <html>');\n log.step('2. Add the theme script to <head>:');\n log.step(' import { getThemeScript } from \"@/features/dark-mode/theme-script\"');\n log.step(' <script dangerouslySetInnerHTML={{ __html: getThemeScript() }} />');\n log.step('3. Wrap the app with <ThemeProvider>');\n log.step('4. Add <ThemeToggle /> or <ThemeToggleSimple /> to your navbar');\n log.step('5. Ensure darkMode: \"class\" is set in your Tailwind config');\n log.blank();\n } catch (error) {\n await ctx.rollback();\n throw error;\n }\n}\n\nasync function setConfigFlag(projectRoot: string, ctx: { trackModifiedFile: (p: string) => Promise<void> }): Promise<void> {\n const configPath = path.join(projectRoot, 'src', 'config', 'app.config.ts');\n if (!(await fs.pathExists(configPath))) return;\n\n await ctx.trackModifiedFile(configPath);\n const content = await fs.readFile(configPath, 'utf-8');\n const updated = content.replace(/darkMode:\\s*false/, 'darkMode: true');\n await fs.writeFile(configPath, updated);\n}\n\nfunction themeProvider(): string {\n return `${STAMP}\n'use client';\n\nimport { createContext, useCallback, useContext, useEffect, useMemo, useState } from 'react';\n\nexport type Theme = 'light' | 'dark' | 'system';\n\nexport interface ThemeContextValue {\n theme: Theme;\n resolvedTheme: 'light' | 'dark';\n setTheme: (theme: Theme) => void;\n}\n\nconst STORAGE_KEY = 'mars-theme';\n\nconst ThemeContext = createContext<ThemeContextValue | undefined>(undefined);\n\nfunction getSystemTheme(): 'light' | 'dark' {\n if (typeof window === 'undefined') return 'light';\n return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';\n}\n\nfunction applyTheme(resolved: 'light' | 'dark'): void {\n document.documentElement.classList.toggle('dark', resolved === 'dark');\n}\n\nexport function ThemeProvider({ children }: { children: React.ReactNode }) {\n const [theme, setThemeState] = useState<Theme>(() => {\n if (typeof window === 'undefined') return 'system';\n return (localStorage.getItem(STORAGE_KEY) as Theme) || 'system';\n });\n\n const [systemTheme, setSystemTheme] = useState<'light' | 'dark'>(getSystemTheme);\n\n const resolvedTheme = theme === 'system' ? systemTheme : theme;\n\n const setTheme = useCallback((next: Theme) => {\n setThemeState(next);\n localStorage.setItem(STORAGE_KEY, next);\n }, []);\n\n useEffect(() => {\n applyTheme(resolvedTheme);\n }, [resolvedTheme]);\n\n useEffect(() => {\n const mq = window.matchMedia('(prefers-color-scheme: dark)');\n const handler = (e: MediaQueryListEvent) => setSystemTheme(e.matches ? 'dark' : 'light');\n\n mq.addEventListener('change', handler);\n return () => mq.removeEventListener('change', handler);\n }, []);\n\n const value = useMemo<ThemeContextValue>(\n () => ({ theme, resolvedTheme, setTheme }),\n [theme, resolvedTheme, setTheme],\n );\n\n return <ThemeContext.Provider value={value}>{children}</ThemeContext.Provider>;\n}\n\nexport function useTheme(): ThemeContextValue {\n const ctx = useContext(ThemeContext);\n if (!ctx) throw new Error('useTheme must be used within a ThemeProvider');\n return ctx;\n}\n`;\n}\n\nfunction themeToggle(): string {\n return `${STAMP}\n'use client';\n\nimport { useTheme, type Theme } from '../providers/ThemeProvider';\n\nconst options: Array<{ value: Theme; label: string }> = [\n { value: 'light', label: 'Light' },\n { value: 'system', label: 'System' },\n { value: 'dark', label: 'Dark' },\n];\n\nfunction SunIcon({ className }: { className?: string }) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n strokeWidth={1.5}\n stroke=\"currentColor\"\n className={className}\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M12 3v2.25m6.364.386-1.591 1.591M21 12h-2.25m-.386 6.364-1.591-1.591M12 18.75V21m-4.773-4.227-1.591 1.591M5.25 12H3m4.227-4.773L5.636 5.636M15.75 12a3.75 3.75 0 1 1-7.5 0 3.75 3.75 0 0 1 7.5 0Z\"\n />\n </svg>\n );\n}\n\nfunction MoonIcon({ className }: { className?: string }) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n strokeWidth={1.5}\n stroke=\"currentColor\"\n className={className}\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M21.752 15.002A9.72 9.72 0 0 1 18 15.75c-5.385 0-9.75-4.365-9.75-9.75 0-1.33.266-2.597.748-3.752A9.753 9.753 0 0 0 3 11.25C3 16.635 7.365 21 12.75 21a9.753 9.753 0 0 0 9.002-5.998Z\"\n />\n </svg>\n );\n}\n\nfunction MonitorIcon({ className }: { className?: string }) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n strokeWidth={1.5}\n stroke=\"currentColor\"\n className={className}\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M9 17.25v1.007a3 3 0 0 1-.879 2.122L7.5 21h9l-.621-.621A3 3 0 0 1 15 18.257V17.25m6-12V15a2.25 2.25 0 0 1-2.25 2.25H5.25A2.25 2.25 0 0 1 3 15V5.25A2.25 2.25 0 0 1 5.25 3h13.5A2.25 2.25 0 0 1 21 5.25Z\"\n />\n </svg>\n );\n}\n\nfunction iconForTheme(value: Theme, className: string) {\n switch (value) {\n case 'light':\n return <SunIcon className={className} />;\n case 'dark':\n return <MoonIcon className={className} />;\n case 'system':\n return <MonitorIcon className={className} />;\n }\n}\n\nexport function ThemeToggle() {\n const { theme, setTheme } = useTheme();\n\n return (\n <div className=\"inline-flex items-center gap-1 rounded-full bg-surface-secondary p-1 shadow-sm\">\n {options.map((opt) => {\n const active = theme === opt.value;\n return (\n <button\n key={opt.value}\n type=\"button\"\n onClick={() => setTheme(opt.value)}\n aria-label={\\`Switch to \\${opt.label} theme\\`}\n className={\\`rounded-full p-1.5 transition-colors \\${\n active\n ? 'bg-surface-primary text-content-primary shadow-sm'\n : 'text-content-tertiary hover:text-content-primary'\n }\\`}\n >\n {iconForTheme(opt.value, 'size-4')}\n </button>\n );\n })}\n </div>\n );\n}\n`;\n}\n\nfunction themeToggleSimple(): string {\n return `${STAMP}\n'use client';\n\nimport { useTheme } from '../providers/ThemeProvider';\n\nfunction SunIcon({ className }: { className?: string }) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n strokeWidth={1.5}\n stroke=\"currentColor\"\n className={className}\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M12 3v2.25m6.364.386-1.591 1.591M21 12h-2.25m-.386 6.364-1.591-1.591M12 18.75V21m-4.773-4.227-1.591 1.591M5.25 12H3m4.227-4.773L5.636 5.636M15.75 12a3.75 3.75 0 1 1-7.5 0 3.75 3.75 0 0 1 7.5 0Z\"\n />\n </svg>\n );\n}\n\nfunction MoonIcon({ className }: { className?: string }) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n strokeWidth={1.5}\n stroke=\"currentColor\"\n className={className}\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M21.752 15.002A9.72 9.72 0 0 1 18 15.75c-5.385 0-9.75-4.365-9.75-9.75 0-1.33.266-2.597.748-3.752A9.753 9.753 0 0 0 3 11.25C3 16.635 7.365 21 12.75 21a9.753 9.753 0 0 0 9.002-5.998Z\"\n />\n </svg>\n );\n}\n\nexport function ThemeToggleSimple() {\n const { resolvedTheme, setTheme } = useTheme();\n\n return (\n <button\n type=\"button\"\n onClick={() => setTheme(resolvedTheme === 'dark' ? 'light' : 'dark')}\n aria-label={\\`Switch to \\${resolvedTheme === 'dark' ? 'light' : 'dark'} theme\\`}\n className=\"rounded-full p-2 text-content-primary transition-colors hover:bg-surface-secondary\"\n >\n {resolvedTheme === 'dark' ? (\n <SunIcon className=\"size-5\" />\n ) : (\n <MoonIcon className=\"size-5\" />\n )}\n </button>\n );\n}\n`;\n}\n\nfunction themeScript(): string {\n return `${STAMP}\nexport function getThemeScript(): string {\n return \\`\n (function() {\n try {\n var stored = localStorage.getItem('mars-theme');\n var prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;\n var isDark = stored === 'dark' || (stored !== 'light' && prefersDark);\n document.documentElement.classList.toggle('dark', isDark);\n } catch (e) {}\n })();\n \\`;\n}\n`;\n}\n\nfunction barrelExport(): string {\n return `${STAMP}\nexport { getThemeScript } from './theme-script';\nexport { ThemeProvider, useTheme, type Theme, type ThemeContextValue } from '@/lib/shared/components/providers/ThemeProvider';\nexport { ThemeToggle } from '@/lib/shared/components/patterns/ThemeToggle';\nexport { ThemeToggleSimple } from '@/lib/shared/components/patterns/ThemeToggleSimple';\n`;\n}\n","import fs from 'fs-extra';\nimport path from 'node:path';\n\nexport async function addUserRelation(\n projectRoot: string,\n field: string,\n ctx: { trackModifiedFile: (p: string) => Promise<void> },\n): Promise<void> {\n const authPath = path.join(projectRoot, 'prisma', 'schema', 'auth.prisma');\n if (!(await fs.pathExists(authPath))) return;\n\n await ctx.trackModifiedFile(authPath);\n let content = await fs.readFile(authPath, 'utf-8');\n\n if (content.includes(field)) return;\n\n const insertBefore = ' @@index([email])';\n content = content.replace(insertBefore, ` ${field}\\n\\n${insertBefore}`);\n await fs.writeFile(authPath, content);\n}\n","import fs from 'fs-extra';\nimport path from 'node:path';\nimport { log } from '../../utils/logger.js';\nimport { createRollbackContext } from '../../utils/rollback.js';\nimport { addUserRelation } from '../../utils/prisma.js';\n\nconst GENERATOR_VERSION = '0.1.0';\nconst STAMP = `// @mars-generated notifications@${GENERATOR_VERSION}`;\n\nexport async function generateNotifications(projectRoot: string): Promise<void> {\n const featureDir = path.join(projectRoot, 'src', 'features', 'notifications');\n\n if (await fs.pathExists(featureDir)) {\n log.error('Notifications feature already exists at src/features/notifications/');\n return;\n }\n\n const ctx = createRollbackContext();\n\n try {\n const files: Record<string, string> = {\n 'prisma/schema/notification.prisma': prismaSchema(),\n 'src/features/notifications/types.ts': types(),\n 'src/features/notifications/validation/schemas.ts': schemas(),\n 'src/features/notifications/server/index.ts': serverLogic(),\n 'src/features/notifications/hooks/use-notifications.ts': useNotificationsHook(),\n 'src/features/notifications/components/NotificationBell.tsx': notificationBell(),\n 'src/features/notifications/components/NotificationPanel.tsx': notificationPanel(),\n 'src/features/notifications/components/index.ts': componentIndex(),\n 'src/app/api/protected/notifications/route.ts': listRoute(),\n 'src/app/api/protected/notifications/[id]/read/route.ts': markReadRoute(),\n 'src/app/api/protected/notifications/read-all/route.ts': markAllReadRoute(),\n 'src/app/api/protected/notifications/count/route.ts': countRoute(),\n };\n\n let count = 0;\n for (const [filePath, content] of Object.entries(files)) {\n const fullPath = path.join(projectRoot, filePath);\n ctx.trackCreatedFile(fullPath);\n await fs.ensureDir(path.dirname(fullPath));\n await fs.writeFile(fullPath, content);\n count++;\n }\n\n await addUserRelation(projectRoot, 'notifications Notification[]', ctx);\n await setConfigFlag(projectRoot, ctx);\n await ctx.commit();\n\n log.success(`Generated notifications feature with ${count} files`);\n log.blank();\n log.step('prisma/schema/notification.prisma — Notification model');\n log.step('src/features/notifications/ — types, validation, server logic, hooks, components');\n log.step('src/app/api/protected/notifications/ — CRUD API routes');\n log.blank();\n log.warn('Next steps:');\n log.step('1. Run yarn db:push to sync the Prisma schema');\n log.step('2. Add <NotificationBell /> to your navbar/header');\n log.step('3. Import createNotification from server to trigger notifications from other features:');\n log.step(' import { createNotification } from \"@/features/notifications/server\"');\n log.blank();\n } catch (error) {\n await ctx.rollback();\n throw error;\n }\n}\n\nasync function setConfigFlag(projectRoot: string, ctx: { trackModifiedFile: (p: string) => Promise<void> }): Promise<void> {\n const configPath = path.join(projectRoot, 'src', 'config', 'app.config.ts');\n if (!(await fs.pathExists(configPath))) return;\n\n await ctx.trackModifiedFile(configPath);\n const content = await fs.readFile(configPath, 'utf-8');\n const updated = content.replace(/notifications:\\s*false/, 'notifications: true');\n await fs.writeFile(configPath, updated);\n}\n\nfunction prismaSchema(): string {\n return `// Generated by mars generate notifications (notifications@${GENERATOR_VERSION})\n\nmodel Notification {\n id String @id @default(cuid())\n userId String\n type String\n title String\n body String?\n resourceId String?\n resourceType String?\n read Boolean @default(false)\n readAt DateTime?\n createdAt DateTime @default(now())\n\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n\n @@index([userId, read])\n @@index([userId, createdAt])\n}\n`;\n}\n\nfunction types(): string {\n return `${STAMP}\n\nexport const NOTIFICATION_TYPES = {\n SYSTEM: 'system',\n WELCOME: 'welcome',\n ACCOUNT: 'account',\n SECURITY: 'security',\n BILLING: 'billing',\n MENTION: 'mention',\n UPDATE: 'update',\n} as const;\n\nexport type NotificationType = (typeof NOTIFICATION_TYPES)[keyof typeof NOTIFICATION_TYPES];\n\nexport interface NotificationItem {\n id: string;\n userId: string;\n type: string;\n title: string;\n body: string | null;\n resourceId: string | null;\n resourceType: string | null;\n read: boolean;\n readAt: Date | null;\n createdAt: Date;\n}\n`;\n}\n\nfunction schemas(): string {\n return `${STAMP}\nimport { z } from 'zod';\n\nexport const listNotificationsSchema = z.object({\n page: z.coerce.number().int().min(1).default(1),\n limit: z.coerce.number().int().min(1).max(100).default(20),\n unreadOnly: z\n .enum(['true', 'false'])\n .default('false')\n .transform((v) => v === 'true'),\n});\n\nexport type ListNotificationsParams = z.infer<typeof listNotificationsSchema>;\n`;\n}\n\nfunction serverLogic(): string {\n return `${STAMP}\nimport 'server-only';\n\nimport { prisma } from '@/lib/prisma';\nimport type { NotificationType } from '../types';\n\ninterface CreateNotificationInput {\n userId: string;\n type: NotificationType | string;\n title: string;\n body?: string;\n resourceId?: string;\n resourceType?: string;\n}\n\nexport async function createNotification(input: CreateNotificationInput) {\n return prisma.notification.create({\n data: {\n userId: input.userId,\n type: input.type,\n title: input.title,\n body: input.body ?? null,\n resourceId: input.resourceId ?? null,\n resourceType: input.resourceType ?? null,\n },\n });\n}\n\ninterface ListNotificationsOptions {\n userId: string;\n page?: number;\n limit?: number;\n unreadOnly?: boolean;\n}\n\nexport async function listNotifications({\n userId,\n page = 1,\n limit = 20,\n unreadOnly = false,\n}: ListNotificationsOptions) {\n const where = {\n userId,\n ...(unreadOnly ? { read: false } : {}),\n };\n\n const [notifications, total] = await prisma.$transaction([\n prisma.notification.findMany({\n where,\n orderBy: { createdAt: 'desc' },\n skip: (page - 1) * limit,\n take: limit,\n }),\n prisma.notification.count({ where }),\n ]);\n\n return {\n notifications,\n total,\n page,\n limit,\n totalPages: Math.ceil(total / limit),\n };\n}\n\nexport async function markAsRead(notificationId: string, userId: string) {\n return prisma.notification.updateMany({\n where: { id: notificationId, userId },\n data: { read: true, readAt: new Date() },\n });\n}\n\nexport async function markAllAsRead(userId: string) {\n return prisma.notification.updateMany({\n where: { userId, read: false },\n data: { read: true, readAt: new Date() },\n });\n}\n\nexport async function getUnreadCount(userId: string) {\n return prisma.notification.count({\n where: { userId, read: false },\n });\n}\n`;\n}\n\nfunction useNotificationsHook(): string {\n return `${STAMP}\n'use client';\n\nimport { useCallback, useEffect, useRef, useState } from 'react';\nimport type { NotificationItem } from '../types';\n\ninterface UseNotificationsOptions {\n pollingInterval?: number;\n}\n\ninterface UseNotificationsReturn {\n notifications: NotificationItem[];\n unreadCount: number;\n isLoading: boolean;\n error: string | null;\n markAsRead: (id: string) => Promise<void>;\n markAllAsRead: () => Promise<void>;\n refresh: () => Promise<void>;\n}\n\nexport function useNotifications({\n pollingInterval = 30000,\n}: UseNotificationsOptions = {}): UseNotificationsReturn {\n const [notifications, setNotifications] = useState<NotificationItem[]>([]);\n const [unreadCount, setUnreadCount] = useState(0);\n const [isLoading, setIsLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const intervalRef = useRef<ReturnType<typeof setInterval> | null>(null);\n\n const fetchNotifications = useCallback(async () => {\n try {\n const res = await fetch('/api/protected/notifications?limit=20');\n if (!res.ok) throw new Error('Failed to fetch notifications');\n const data = await res.json();\n setNotifications(data.notifications);\n setError(null);\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Unknown error');\n }\n }, []);\n\n const fetchUnreadCount = useCallback(async () => {\n try {\n const res = await fetch('/api/protected/notifications/count');\n if (!res.ok) throw new Error('Failed to fetch unread count');\n const data = await res.json();\n setUnreadCount(data.count);\n } catch {\n // Silently fail for count polling\n }\n }, []);\n\n const refresh = useCallback(async () => {\n setIsLoading(true);\n await Promise.all([fetchNotifications(), fetchUnreadCount()]);\n setIsLoading(false);\n }, [fetchNotifications, fetchUnreadCount]);\n\n const markAsRead = useCallback(\n async (id: string) => {\n const res = await fetch(\\`/api/protected/notifications/\\${id}/read\\`, {\n method: 'PATCH',\n });\n if (!res.ok) throw new Error('Failed to mark notification as read');\n\n setNotifications((prev) =>\n prev.map((n) => (n.id === id ? { ...n, read: true, readAt: new Date() } : n)),\n );\n setUnreadCount((prev) => Math.max(0, prev - 1));\n },\n [],\n );\n\n const markAllAsRead = useCallback(async () => {\n const res = await fetch('/api/protected/notifications/read-all', {\n method: 'PATCH',\n });\n if (!res.ok) throw new Error('Failed to mark all as read');\n\n setNotifications((prev) =>\n prev.map((n) => ({ ...n, read: true, readAt: new Date() })),\n );\n setUnreadCount(0);\n }, []);\n\n useEffect(() => {\n refresh();\n }, [refresh]);\n\n useEffect(() => {\n if (pollingInterval <= 0) return;\n\n intervalRef.current = setInterval(() => {\n fetchUnreadCount();\n }, pollingInterval);\n\n return () => {\n if (intervalRef.current) clearInterval(intervalRef.current);\n };\n }, [pollingInterval, fetchUnreadCount]);\n\n return {\n notifications,\n unreadCount,\n isLoading,\n error,\n markAsRead,\n markAllAsRead,\n refresh,\n };\n}\n`;\n}\n\nfunction notificationBell(): string {\n return `${STAMP}\n'use client';\n\nimport { useState, useRef, useEffect } from 'react';\nimport { useNotifications } from '../hooks/use-notifications';\nimport { NotificationPanel } from './NotificationPanel';\n\nexport function NotificationBell() {\n const [isOpen, setIsOpen] = useState(false);\n const containerRef = useRef<HTMLDivElement>(null);\n const { notifications, unreadCount, isLoading, markAsRead, markAllAsRead, refresh } =\n useNotifications();\n\n useEffect(() => {\n function handleClickOutside(event: MouseEvent) {\n if (containerRef.current && !containerRef.current.contains(event.target as Node)) {\n setIsOpen(false);\n }\n }\n\n document.addEventListener('mousedown', handleClickOutside);\n return () => document.removeEventListener('mousedown', handleClickOutside);\n }, []);\n\n function handleToggle() {\n if (!isOpen) refresh();\n setIsOpen((prev) => !prev);\n }\n\n return (\n <div ref={containerRef} className=\"relative\">\n <button\n type=\"button\"\n onClick={handleToggle}\n aria-label={\\`Notifications\\${unreadCount > 0 ? \\` (\\${unreadCount} unread)\\` : ''}\\`}\n className=\"relative rounded-full p-2 text-text-secondary transition-colors hover:bg-surface-secondary hover:text-text-primary\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n strokeWidth={1.5}\n stroke=\"currentColor\"\n className=\"size-5\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M14.857 17.082a23.848 23.848 0 0 0 5.454-1.31A8.967 8.967 0 0 1 18 9.75V9A6 6 0 0 0 6 9v.75a8.967 8.967 0 0 1-2.312 6.022c1.733.64 3.56 1.085 5.455 1.31m5.714 0a24.255 24.255 0 0 1-5.714 0m5.714 0a3 3 0 1 1-5.714 0\"\n />\n </svg>\n {unreadCount > 0 && (\n <span className=\"absolute -right-0.5 -top-0.5 flex size-5 items-center justify-center rounded-full bg-brand-primary text-[10px] font-bold text-text-on-brand\">\n {unreadCount > 99 ? '99+' : unreadCount}\n </span>\n )}\n </button>\n\n {isOpen && (\n <NotificationPanel\n notifications={notifications}\n isLoading={isLoading}\n onMarkAsRead={markAsRead}\n onMarkAllAsRead={markAllAsRead}\n onClose={() => setIsOpen(false)}\n />\n )}\n </div>\n );\n}\n`;\n}\n\nfunction notificationPanel(): string {\n return `${STAMP}\n'use client';\n\nimport type { NotificationItem } from '../types';\n\ninterface NotificationPanelProps {\n notifications: NotificationItem[];\n isLoading: boolean;\n onMarkAsRead: (id: string) => Promise<void>;\n onMarkAllAsRead: () => Promise<void>;\n onClose: () => void;\n}\n\nfunction formatRelativeTime(date: Date | string): string {\n const now = Date.now();\n const then = new Date(date).getTime();\n const seconds = Math.floor((now - then) / 1000);\n\n if (seconds < 60) return 'just now';\n\n const minutes = Math.floor(seconds / 60);\n if (minutes < 60) return \\`\\${minutes}m ago\\`;\n\n const hours = Math.floor(minutes / 60);\n if (hours < 24) return \\`\\${hours}h ago\\`;\n\n const days = Math.floor(hours / 24);\n if (days < 7) return \\`\\${days}d ago\\`;\n\n const weeks = Math.floor(days / 7);\n if (weeks < 4) return \\`\\${weeks}w ago\\`;\n\n const months = Math.floor(days / 30);\n if (months < 12) return \\`\\${months}mo ago\\`;\n\n const years = Math.floor(days / 365);\n return \\`\\${years}y ago\\`;\n}\n\nexport function NotificationPanel({\n notifications,\n isLoading,\n onMarkAsRead,\n onMarkAllAsRead,\n onClose,\n}: NotificationPanelProps) {\n const hasUnread = notifications.some((n) => !n.read);\n\n return (\n <div className=\"absolute right-0 top-full z-50 mt-2 w-80 overflow-hidden rounded-xl border border-border-default bg-surface-primary shadow-lg sm:w-96\">\n <div className=\"flex items-center justify-between border-b border-border-default px-4 py-3\">\n <h2 className=\"text-sm font-semibold text-text-primary\">Notifications</h2>\n {hasUnread && (\n <button\n type=\"button\"\n onClick={onMarkAllAsRead}\n className=\"text-xs font-medium text-brand-primary transition-colors hover:text-brand-primary-hover\"\n >\n Mark all as read\n </button>\n )}\n </div>\n\n <div className=\"max-h-96 overflow-y-auto\">\n {isLoading && notifications.length === 0 ? (\n <div className=\"flex items-center justify-center py-12\">\n <div className=\"size-5 animate-spin rounded-full border-2 border-border-default border-t-brand-primary\" />\n </div>\n ) : notifications.length === 0 ? (\n <div className=\"px-4 py-12 text-center\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n strokeWidth={1.5}\n stroke=\"currentColor\"\n className=\"mx-auto size-8 text-text-muted\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M14.857 17.082a23.848 23.848 0 0 0 5.454-1.31A8.967 8.967 0 0 1 18 9.75V9A6 6 0 0 0 6 9v.75a8.967 8.967 0 0 1-2.312 6.022c1.733.64 3.56 1.085 5.455 1.31m5.714 0a24.255 24.255 0 0 1-5.714 0m5.714 0a3 3 0 1 1-5.714 0\"\n />\n </svg>\n <p className=\"mt-2 text-sm text-text-muted\">No notifications yet</p>\n </div>\n ) : (\n <ul role=\"list\">\n {notifications.map((notification) => (\n <li key={notification.id}>\n <button\n type=\"button\"\n onClick={() => {\n if (!notification.read) onMarkAsRead(notification.id);\n }}\n className={\\`flex w-full gap-3 px-4 py-3 text-left transition-colors hover:bg-surface-secondary \\${\n !notification.read ? 'bg-surface-background' : ''\n }\\`}\n >\n <div className=\"mt-1.5 flex shrink-0\">\n {!notification.read && (\n <span className=\"size-2 rounded-full bg-brand-primary\" />\n )}\n {notification.read && <span className=\"size-2\" />}\n </div>\n <div className=\"min-w-0 flex-1\">\n <p className={\\`text-sm \\${\n !notification.read\n ? 'font-semibold text-text-primary'\n : 'text-text-secondary'\n }\\`}>\n {notification.title}\n </p>\n {notification.body && (\n <p className=\"mt-0.5 line-clamp-2 text-xs text-text-muted\">\n {notification.body}\n </p>\n )}\n <p className=\"mt-1 text-xs text-text-muted\">\n {formatRelativeTime(notification.createdAt)}\n </p>\n </div>\n </button>\n </li>\n ))}\n </ul>\n )}\n </div>\n </div>\n );\n}\n`;\n}\n\nfunction componentIndex(): string {\n return `${STAMP}\nexport { NotificationBell } from './NotificationBell';\nexport { NotificationPanel } from './NotificationPanel';\n`;\n}\n\nfunction listRoute(): string {\n return `${STAMP}\nimport { withAuthNoParams, handleApiError } from '@/lib/mars';\nimport { listNotifications } from '@/features/notifications/server';\nimport { listNotificationsSchema } from '@/features/notifications/validation/schemas';\nimport type { AuthenticatedRequest } from '@mars-stack/core/auth/middleware';\nimport { NextResponse } from 'next/server';\n\nexport const GET = withAuthNoParams(async (request: AuthenticatedRequest) => {\n try {\n const url = new URL(request.url);\n const params = listNotificationsSchema.parse({\n page: url.searchParams.get('page') ?? undefined,\n limit: url.searchParams.get('limit') ?? undefined,\n unreadOnly: url.searchParams.get('unreadOnly') ?? undefined,\n });\n\n const result = await listNotifications({\n userId: request.session.userId,\n ...params,\n });\n\n return NextResponse.json(result);\n } catch (error) {\n return handleApiError(error, { endpoint: '/api/protected/notifications' });\n }\n});\n`;\n}\n\nfunction markReadRoute(): string {\n return `${STAMP}\nimport { withAuth, handleApiError } from '@/lib/mars';\nimport { markAsRead } from '@/features/notifications/server';\nimport type { AuthenticatedRequest } from '@mars-stack/core/auth/middleware';\nimport { NextResponse } from 'next/server';\n\nexport const PATCH = withAuth(\n async (\n request: AuthenticatedRequest,\n context: { params: Promise<{ [key: string]: string }> },\n ) => {\n try {\n const { id } = await context.params;\n\n await markAsRead(id, request.session.userId);\n\n return NextResponse.json({ success: true });\n } catch (error) {\n return handleApiError(error, {\n endpoint: '/api/protected/notifications/[id]/read',\n });\n }\n },\n);\n`;\n}\n\nfunction markAllReadRoute(): string {\n return `${STAMP}\nimport { withAuthNoParams, handleApiError } from '@/lib/mars';\nimport { markAllAsRead } from '@/features/notifications/server';\nimport type { AuthenticatedRequest } from '@mars-stack/core/auth/middleware';\nimport { NextResponse } from 'next/server';\n\nexport const PATCH = withAuthNoParams(async (request: AuthenticatedRequest) => {\n try {\n await markAllAsRead(request.session.userId);\n return NextResponse.json({ success: true });\n } catch (error) {\n return handleApiError(error, { endpoint: '/api/protected/notifications/read-all' });\n }\n});\n`;\n}\n\nfunction countRoute(): string {\n return `${STAMP}\nimport { withAuthNoParams, handleApiError } from '@/lib/mars';\nimport { getUnreadCount } from '@/features/notifications/server';\nimport type { AuthenticatedRequest } from '@mars-stack/core/auth/middleware';\nimport { NextResponse } from 'next/server';\n\nexport const GET = withAuthNoParams(async (request: AuthenticatedRequest) => {\n try {\n const count = await getUnreadCount(request.session.userId);\n return NextResponse.json({ count });\n } catch (error) {\n return handleApiError(error, { endpoint: '/api/protected/notifications/count' });\n }\n});\n`;\n}\n","import fs from 'fs-extra';\nimport path from 'node:path';\nimport { log } from '../../utils/logger.js';\nimport { createRollbackContext } from '../../utils/rollback.js';\n\nconst GENERATOR_VERSION = '0.1.0';\nconst STAMP = `// @mars-generated analytics@${GENERATOR_VERSION}`;\n\nexport async function generateAnalytics(projectRoot: string): Promise<void> {\n const featureDir = path.join(projectRoot, 'src', 'features', 'analytics');\n\n if (await fs.pathExists(featureDir)) {\n log.error('Analytics feature already exists at src/features/analytics/');\n return;\n }\n\n const ctx = createRollbackContext();\n\n try {\n const files: Record<string, string> = {\n 'src/features/analytics/types.ts': types(),\n 'src/features/analytics/index.ts': barrelExports(),\n 'src/lib/shared/components/providers/AnalyticsProvider.tsx': analyticsProvider(),\n 'src/lib/shared/utils/analytics.ts': analyticsUtils(),\n 'src/lib/shared/components/patterns/ConsentBanner.tsx': consentBanner(),\n };\n\n let count = 0;\n for (const [filePath, content] of Object.entries(files)) {\n const fullPath = path.join(projectRoot, filePath);\n ctx.trackCreatedFile(fullPath);\n await fs.ensureDir(path.dirname(fullPath));\n await fs.writeFile(fullPath, content);\n count++;\n }\n\n await setConfigFlag(projectRoot, ctx);\n await ctx.commit();\n\n log.success(`Generated analytics feature with ${count} files`);\n log.blank();\n log.step('src/features/analytics/ — types and barrel exports');\n log.step('src/lib/shared/components/providers/AnalyticsProvider.tsx — provider wrapper');\n log.step('src/lib/shared/utils/analytics.ts — unified tracking API');\n log.step('src/lib/shared/components/patterns/ConsentBanner.tsx — cookie consent banner');\n log.blank();\n log.warn('Install dependencies for your chosen provider:');\n log.step('Vercel: yarn add @vercel/analytics @vercel/speed-insights');\n log.step('PostHog: yarn add posthog-js');\n log.step('Google: No packages needed');\n log.blank();\n log.warn('Next steps:');\n log.step('Set the provider in appConfig.services.analytics.provider');\n log.step('Set required environment variables for the chosen provider');\n log.step('Add <AnalyticsProvider> and <ConsentBanner /> to your root layout');\n log.blank();\n } catch (error) {\n await ctx.rollback();\n throw error;\n }\n}\n\nasync function setConfigFlag(projectRoot: string, ctx: { trackModifiedFile: (p: string) => Promise<void> }): Promise<void> {\n const configPath = path.join(projectRoot, 'src', 'config', 'app.config.ts');\n if (!(await fs.pathExists(configPath))) return;\n\n await ctx.trackModifiedFile(configPath);\n const content = await fs.readFile(configPath, 'utf-8');\n const updated = content.replace(/analytics:\\s*false/, 'analytics: true');\n await fs.writeFile(configPath, updated);\n}\n\nfunction types(): string {\n return `${STAMP}\n\nexport type AnalyticsProvider = 'vercel' | 'posthog' | 'google' | 'none';\n\nexport interface TrackEventParams {\n eventName: string;\n properties?: Record<string, string | number | boolean>;\n}\n`;\n}\n\nfunction barrelExports(): string {\n return `${STAMP}\n\nexport type { AnalyticsProvider, TrackEventParams } from './types';\n`;\n}\n\nfunction analyticsProvider(): string {\n return `${STAMP}\n'use client';\n\nimport { useEffect, useState } from 'react';\nimport { usePathname, useSearchParams } from 'next/navigation';\nimport Script from 'next/script';\nimport { appConfig } from '@/config/app.config';\nimport { trackPageView } from '@/lib/shared/utils/analytics';\n\ninterface AnalyticsProviderProps {\n children: React.ReactNode;\n}\n\nexport function AnalyticsProvider({ children }: AnalyticsProviderProps) {\n const provider: string = appConfig.services.analytics.provider;\n const isDev = process.env.NODE_ENV === 'development';\n\n if (provider === 'none' || isDev) {\n return <>{children}</>;\n }\n\n return (\n <>\n {provider === 'vercel' && <VercelAnalyticsProvider />}\n {provider === 'posthog' && <PostHogAnalyticsProvider />}\n {provider === 'google' && <GoogleAnalyticsProvider />}\n <PageViewTracker />\n {children}\n </>\n );\n}\n\nfunction VercelAnalyticsProvider() {\n const [components, setComponents] = useState<{ Analytics: React.ComponentType; SpeedInsights: React.ComponentType } | null>(null);\n\n useEffect(() => {\n const analyticsSpec = '@vercel/analytics/react';\n const insightsSpec = '@vercel/speed-insights/next';\n Promise.all([import(/* webpackIgnore: true */ analyticsSpec), import(/* webpackIgnore: true */ insightsSpec)])\n .then(([a, s]) => setComponents({ Analytics: a.Analytics, SpeedInsights: s.SpeedInsights }))\n .catch(() => {\n if (process.env.NODE_ENV === 'development') {\n console.warn('[mars/analytics] @vercel/analytics or @vercel/speed-insights not installed. Run: yarn add @vercel/analytics @vercel/speed-insights');\n }\n });\n }, []);\n\n if (!components) return null;\n const { Analytics, SpeedInsights } = components;\n\n return (\n <>\n <Analytics />\n <SpeedInsights />\n </>\n );\n}\n\nfunction PostHogAnalyticsProvider() {\n const posthogKey = process.env.NEXT_PUBLIC_POSTHOG_KEY;\n const posthogHost = process.env.NEXT_PUBLIC_POSTHOG_HOST || 'https://us.i.posthog.com';\n\n useEffect(() => {\n if (!posthogKey) {\n console.warn('[mars/analytics] NEXT_PUBLIC_POSTHOG_KEY is not set. PostHog analytics disabled.');\n return;\n }\n\n const spec = 'posthog-js';\n import(/* webpackIgnore: true */ spec)\n .then((mod) => {\n const posthog = mod.default;\n posthog.init(posthogKey, {\n api_host: posthogHost,\n capture_pageview: false,\n capture_pageleave: true,\n });\n })\n .catch(() => {\n console.warn('[mars/analytics] posthog-js not installed. Run: yarn add posthog-js');\n });\n }, [posthogKey, posthogHost]);\n\n return null;\n}\n\nfunction GoogleAnalyticsProvider() {\n const gaId = process.env.NEXT_PUBLIC_GA_MEASUREMENT_ID;\n\n if (!gaId) {\n if (process.env.NODE_ENV === 'development') {\n console.warn('[mars/analytics] NEXT_PUBLIC_GA_MEASUREMENT_ID is not set. Google Analytics disabled.');\n }\n return null;\n }\n\n return (\n <>\n <Script\n src={\\`https://www.googletagmanager.com/gtag/js?id=\\${gaId}\\`}\n strategy=\"afterInteractive\"\n />\n <Script id=\"google-analytics\" strategy=\"afterInteractive\">\n {\\`\n window.dataLayer = window.dataLayer || [];\n function gtag(){dataLayer.push(arguments);}\n gtag('js', new Date());\n gtag('config', '\\${gaId}');\n \\`}\n </Script>\n </>\n );\n}\n\nfunction PageViewTracker() {\n const pathname = usePathname();\n const searchParams = useSearchParams();\n\n useEffect(() => {\n const url = searchParams.toString()\n ? \\`\\${pathname}?\\${searchParams.toString()}\\`\n : pathname;\n trackPageView(url);\n }, [pathname, searchParams]);\n\n return null;\n}\n`;\n}\n\nfunction analyticsUtils(): string {\n return `${STAMP}\n\nimport { appConfig } from '@/config/app.config';\n\nfunction getProvider(): string {\n return appConfig.services.analytics.provider;\n}\n\nfunction isDisabledInDev(): boolean {\n return process.env.NODE_ENV === 'development';\n}\n\nexport function trackPageView(url: string): void {\n const provider = getProvider();\n\n if (provider === 'none' || isDisabledInDev()) {\n if (process.env.NODE_ENV === 'development') {\n console.debug('[mars/analytics] pageview:', url);\n }\n return;\n }\n\n switch (provider) {\n case 'vercel':\n break;\n\n case 'posthog': {\n const spec = 'posthog-js';\n import(/* webpackIgnore: true */ spec)\n .then((mod) => mod.default.capture('$pageview', { $current_url: url }))\n .catch(() => {});\n break;\n }\n\n case 'google': {\n if (typeof window !== 'undefined' && typeof window.gtag === 'function') {\n window.gtag('config', process.env.NEXT_PUBLIC_GA_MEASUREMENT_ID!, {\n page_path: url,\n });\n }\n break;\n }\n }\n}\n\nexport function trackEvent(\n eventName: string,\n properties?: Record<string, string | number | boolean>,\n): void {\n const provider = getProvider();\n\n if (provider === 'none' || isDisabledInDev()) {\n if (process.env.NODE_ENV === 'development') {\n console.debug('[mars/analytics] event:', eventName, properties);\n }\n return;\n }\n\n switch (provider) {\n case 'vercel': {\n try {\n const { track } = require('@vercel/analytics');\n track(eventName, properties);\n } catch {\n // @vercel/analytics not available\n }\n break;\n }\n\n case 'posthog': {\n try {\n const posthog = require('posthog-js').default;\n posthog.capture(eventName, properties);\n } catch {\n // posthog-js not available\n }\n break;\n }\n\n case 'google': {\n if (typeof window !== 'undefined' && typeof window.gtag === 'function') {\n window.gtag('event', eventName, properties);\n }\n break;\n }\n }\n}\n\nexport function identifyUser(\n userId: string,\n traits?: Record<string, string>,\n): void {\n const provider = getProvider();\n\n if (provider === 'none' || isDisabledInDev()) {\n if (process.env.NODE_ENV === 'development') {\n console.debug('[mars/analytics] identify:', userId, traits);\n }\n return;\n }\n\n switch (provider) {\n case 'vercel':\n break;\n\n case 'posthog': {\n try {\n const posthog = require('posthog-js').default;\n posthog.identify(userId, traits);\n } catch {\n // posthog-js not available\n }\n break;\n }\n\n case 'google': {\n if (typeof window !== 'undefined' && typeof window.gtag === 'function') {\n window.gtag('set', { user_id: userId, ...traits });\n }\n break;\n }\n }\n}\n\ndeclare global {\n interface Window {\n gtag: (...args: unknown[]) => void;\n dataLayer: unknown[];\n }\n}\n`;\n}\n\nfunction consentBanner(): string {\n return `${STAMP}\n'use client';\n\nimport { useState, useEffect } from 'react';\n\nconst CONSENT_KEY = 'mars-analytics-consent';\n\ntype ConsentStatus = 'accepted' | 'declined' | null;\n\nfunction getStoredConsent(): ConsentStatus {\n if (typeof window === 'undefined') return null;\n return localStorage.getItem(CONSENT_KEY) as ConsentStatus;\n}\n\nexport function ConsentBanner() {\n const [consent, setConsent] = useState<ConsentStatus>(null);\n const [mounted, setMounted] = useState(false);\n\n useEffect(() => {\n setMounted(true);\n setConsent(getStoredConsent());\n }, []);\n\n if (!mounted || consent !== null) {\n return null;\n }\n\n function handleAccept() {\n localStorage.setItem(CONSENT_KEY, 'accepted');\n setConsent('accepted');\n }\n\n function handleDecline() {\n localStorage.setItem(CONSENT_KEY, 'declined');\n setConsent('declined');\n }\n\n return (\n <div className=\"fixed inset-x-0 bottom-0 z-50 p-4\">\n <div className=\"mx-auto flex max-w-xl items-center justify-between gap-4 rounded-xl border border-border-default bg-surface-card px-6 py-4 shadow-lg\">\n <p className=\"text-sm text-text-secondary\">\n We use cookies and analytics to improve your experience.\n </p>\n <div className=\"flex shrink-0 gap-2\">\n <button\n onClick={handleDecline}\n className=\"rounded-lg border border-border-default px-4 py-2 text-sm font-medium text-text-secondary transition-colors hover:bg-surface-background\"\n >\n Decline\n </button>\n <button\n onClick={handleAccept}\n className=\"rounded-lg bg-brand-primary px-4 py-2 text-sm font-medium text-text-on-brand transition-colors hover:opacity-90\"\n >\n Accept\n </button>\n </div>\n </div>\n </div>\n );\n}\n`;\n}\n","import fs from 'fs-extra';\nimport path from 'node:path';\nimport { log } from '../../utils/logger.js';\nimport { createRollbackContext } from '../../utils/rollback.js';\nimport { addDependencies } from '../../utils/dependencies.js';\n\nconst GENERATOR_VERSION = '0.1.0';\nconst STAMP = `// @mars-generated command-palette@${GENERATOR_VERSION}`;\n\nexport async function generateCommandPalette(projectRoot: string): Promise<void> {\n const featureDir = path.join(projectRoot, 'src', 'features', 'command-palette');\n\n if (await fs.pathExists(featureDir)) {\n log.error('Command palette feature already exists at src/features/command-palette/');\n return;\n }\n\n const ctx = createRollbackContext();\n\n try {\n const files: Record<string, string> = {\n 'src/features/command-palette/types.ts': types(),\n 'src/features/command-palette/actions.ts': actions(),\n 'src/features/command-palette/registry.ts': registry(),\n 'src/features/command-palette/recent.ts': recent(),\n 'src/features/command-palette/components/CommandPalette.tsx': commandPalette(),\n 'src/features/command-palette/components/CommandTrigger.tsx': commandTrigger(),\n 'src/features/command-palette/components/index.ts': componentIndex(),\n 'src/features/command-palette/index.ts': featureIndex(),\n };\n\n let count = 0;\n for (const [filePath, content] of Object.entries(files)) {\n const fullPath = path.join(projectRoot, filePath);\n ctx.trackCreatedFile(fullPath);\n await fs.ensureDir(path.dirname(fullPath));\n await fs.writeFile(fullPath, content);\n count++;\n }\n\n await addDependencies(projectRoot, { cmdk: '^1.0.0' });\n await setConfigFlag(projectRoot, ctx);\n await ctx.commit();\n\n log.success(`Generated command palette feature with ${count} files`);\n log.blank();\n log.step('src/features/command-palette/ — types, actions, registry, recent, components');\n log.blank();\n log.warn('Integration steps:');\n log.step('Add <CommandPalette /> to your protected layout');\n log.step('Optionally add <CommandTrigger /> to your navbar for discoverability');\n log.step('Register custom actions with registerAction() from any feature');\n log.blank();\n } catch (error) {\n await ctx.rollback();\n throw error;\n }\n}\n\nasync function setConfigFlag(projectRoot: string, ctx: { trackModifiedFile: (p: string) => Promise<void> }): Promise<void> {\n const configPath = path.join(projectRoot, 'src', 'config', 'app.config.ts');\n if (!(await fs.pathExists(configPath))) return;\n\n await ctx.trackModifiedFile(configPath);\n const content = await fs.readFile(configPath, 'utf-8');\n const updated = content.replace(/commandPalette:\\s*false/, 'commandPalette: true');\n await fs.writeFile(configPath, updated);\n}\n\nfunction types(): string {\n return `${STAMP}\nimport type { ReactNode } from 'react';\n\nexport interface CommandAction {\n id: string;\n label: string;\n description?: string;\n icon?: ReactNode;\n keywords?: string[];\n shortcut?: string[];\n section: string;\n onSelect: () => void;\n}\n`;\n}\n\nfunction actions(): string {\n return `${STAMP}\n'use client';\n\nimport type { AppRouterInstance } from 'next/dist/shared/lib/app-router-context.shared-runtime';\nimport type { CommandAction } from './types';\n\nexport function createNavigationActions(router: AppRouterInstance): CommandAction[] {\n return [\n {\n id: 'nav-dashboard',\n label: 'Go to Dashboard',\n description: 'Navigate to the main dashboard',\n keywords: ['home', 'main', 'overview'],\n section: 'Navigation',\n onSelect: () => router.push('/dashboard'),\n },\n {\n id: 'nav-settings',\n label: 'Go to Settings',\n description: 'Manage your account settings',\n keywords: ['preferences', 'account', 'config'],\n section: 'Navigation',\n onSelect: () => router.push('/settings'),\n },\n {\n id: 'nav-profile',\n label: 'Go to Profile',\n description: 'View and edit your profile',\n keywords: ['user', 'account', 'me'],\n section: 'Navigation',\n onSelect: () => router.push('/profile'),\n },\n ];\n}\n\nexport function createThemeActions(setTheme: (theme: string) => void): CommandAction[] {\n return [\n {\n id: 'theme-light',\n label: 'Switch to Light Mode',\n description: 'Use the light color scheme',\n keywords: ['appearance', 'bright'],\n section: 'Theme',\n onSelect: () => setTheme('light'),\n },\n {\n id: 'theme-dark',\n label: 'Switch to Dark Mode',\n description: 'Use the dark color scheme',\n keywords: ['appearance', 'night'],\n section: 'Theme',\n onSelect: () => setTheme('dark'),\n },\n {\n id: 'theme-system',\n label: 'Use System Theme',\n description: 'Follow your operating system preference',\n keywords: ['appearance', 'auto', 'default'],\n section: 'Theme',\n onSelect: () => setTheme('system'),\n },\n ];\n}\n\nexport function createUserActions(callbacks: { onSignOut: () => void }): CommandAction[] {\n return [\n {\n id: 'user-signout',\n label: 'Sign Out',\n description: 'Log out of your account',\n keywords: ['logout', 'exit', 'leave'],\n section: 'User',\n onSelect: callbacks.onSignOut,\n },\n ];\n}\n`;\n}\n\nfunction registry(): string {\n return `${STAMP}\n'use client';\n\nimport type { CommandAction } from './types';\n\nconst customActions = new Map<string, CommandAction>();\n\nexport function registerAction(action: CommandAction): void {\n customActions.set(action.id, action);\n}\n\nexport function getCustomActions(): CommandAction[] {\n return Array.from(customActions.values());\n}\n`;\n}\n\nfunction recent(): string {\n return `${STAMP}\n'use client';\n\nconst STORAGE_KEY = 'mars:command-palette:recent';\nconst MAX_RECENT = 5;\n\nexport function getRecentActions(): string[] {\n if (typeof window === 'undefined') return [];\n\n try {\n const stored = localStorage.getItem(STORAGE_KEY);\n if (!stored) return [];\n const parsed: unknown = JSON.parse(stored);\n if (!Array.isArray(parsed)) return [];\n return parsed.filter((item): item is string => typeof item === 'string');\n } catch {\n return [];\n }\n}\n\nexport function addRecentAction(actionId: string): void {\n if (typeof window === 'undefined') return;\n\n try {\n const recent = getRecentActions().filter((id) => id !== actionId);\n recent.unshift(actionId);\n localStorage.setItem(STORAGE_KEY, JSON.stringify(recent.slice(0, MAX_RECENT)));\n } catch {\n // localStorage may be unavailable\n }\n}\n`;\n}\n\nfunction commandPalette(): string {\n return `${STAMP}\n'use client';\n\nimport { useState, useEffect, useCallback } from 'react';\nimport { useRouter } from 'next/navigation';\nimport { Command } from 'cmdk';\nimport type { CommandAction } from '../types';\nimport { createNavigationActions, createThemeActions, createUserActions } from '../actions';\nimport { getCustomActions } from '../registry';\nimport { addRecentAction, getRecentActions } from '../recent';\n\nfunction SearchIcon({ className }: { className?: string }) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n strokeWidth={1.5}\n stroke=\"currentColor\"\n className={className}\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"m21 21-5.197-5.197m0 0A7.5 7.5 0 1 0 5.196 5.196a7.5 7.5 0 0 0 10.607 10.607Z\"\n />\n </svg>\n );\n}\n\nexport function CommandPalette() {\n const [open, setOpen] = useState(false);\n const router = useRouter();\n\n const handleKeyDown = useCallback((e: KeyboardEvent) => {\n if ((e.metaKey || e.ctrlKey) && e.key === 'k') {\n e.preventDefault();\n setOpen((prev) => !prev);\n }\n }, []);\n\n useEffect(() => {\n document.addEventListener('keydown', handleKeyDown);\n return () => document.removeEventListener('keydown', handleKeyDown);\n }, [handleKeyDown]);\n\n const navigationActions = createNavigationActions(router);\n const themeActions = createThemeActions((theme) => {\n document.documentElement.setAttribute('data-theme', theme);\n });\n const userActions = createUserActions({\n onSignOut: () => router.push('/api/auth/signout'),\n });\n const customActions = getCustomActions();\n\n const allActions = [...navigationActions, ...themeActions, ...userActions, ...customActions];\n\n const recentIds = getRecentActions();\n const recentActions = recentIds\n .map((id) => allActions.find((a) => a.id === id))\n .filter((a): a is CommandAction => a !== undefined);\n\n const sections = allActions.reduce<Record<string, CommandAction[]>>((acc, action) => {\n if (!acc[action.section]) acc[action.section] = [];\n acc[action.section].push(action);\n return acc;\n }, {});\n\n function handleSelect(action: CommandAction) {\n setOpen(false);\n addRecentAction(action.id);\n action.onSelect();\n }\n\n if (!open) return null;\n\n return (\n <div className=\"fixed inset-0 z-50\">\n <div\n className=\"fixed inset-0 bg-surface-overlay backdrop-blur-sm\"\n onClick={() => setOpen(false)}\n aria-hidden=\"true\"\n />\n\n <div className=\"fixed left-1/2 top-[20%] w-full max-w-lg -translate-x-1/2\">\n <Command\n className=\"overflow-hidden rounded-xl border border-border-default bg-surface-card shadow-2xl\"\n loop\n >\n <div className=\"flex items-center gap-2 border-b border-border-default px-4\">\n <SearchIcon className=\"size-4 shrink-0 text-text-muted\" />\n <Command.Input\n placeholder=\"Type a command or search...\"\n className=\"flex-1 bg-transparent py-3 text-sm text-text-primary outline-none placeholder:text-text-muted\"\n />\n <kbd className=\"rounded border border-border-default bg-surface-background px-1.5 py-0.5 text-[10px] font-medium text-text-muted\">\n ESC\n </kbd>\n </div>\n\n <Command.List className=\"max-h-80 overflow-y-auto p-2\">\n <Command.Empty className=\"py-6 text-center text-sm text-text-muted\">\n No results found.\n </Command.Empty>\n\n {recentActions.length > 0 && (\n <Command.Group heading=\"Recent\">\n {recentActions.map((action) => (\n <CommandItem key={\\`recent-\\${action.id}\\`} action={action} onSelect={handleSelect} />\n ))}\n </Command.Group>\n )}\n\n {Object.entries(sections).map(([section, sectionActions]) => (\n <Command.Group key={section} heading={section}>\n {sectionActions.map((action) => (\n <CommandItem key={action.id} action={action} onSelect={handleSelect} />\n ))}\n </Command.Group>\n ))}\n </Command.List>\n\n <div className=\"flex items-center justify-between border-t border-border-default px-4 py-2 text-xs text-text-muted\">\n <div className=\"flex items-center gap-2\">\n <span className=\"flex items-center gap-1\">\n <kbd className=\"rounded border border-border-default bg-surface-background px-1 py-0.5 text-[10px]\">↑</kbd>\n <kbd className=\"rounded border border-border-default bg-surface-background px-1 py-0.5 text-[10px]\">↓</kbd>\n navigate\n </span>\n <span className=\"flex items-center gap-1\">\n <kbd className=\"rounded border border-border-default bg-surface-background px-1 py-0.5 text-[10px]\">↵</kbd>\n select\n </span>\n </div>\n <span className=\"flex items-center gap-1\">\n <kbd className=\"rounded border border-border-default bg-surface-background px-1 py-0.5 text-[10px]\">esc</kbd>\n close\n </span>\n </div>\n </Command>\n </div>\n </div>\n );\n}\n\nfunction CommandItem({\n action,\n onSelect,\n}: {\n action: CommandAction;\n onSelect: (action: CommandAction) => void;\n}) {\n return (\n <Command.Item\n value={\\`\\${action.label} \\${action.keywords?.join(' ') ?? ''}\\`}\n onSelect={() => onSelect(action)}\n className=\"flex cursor-pointer items-center justify-between rounded-lg px-3 py-2 text-sm text-text-primary aria-selected:bg-brand-primary aria-selected:text-text-on-brand\"\n >\n <div className=\"flex items-center gap-3\">\n {action.icon && <span className=\"shrink-0\">{action.icon}</span>}\n <div>\n <div className=\"font-medium\">{action.label}</div>\n {action.description && (\n <div className=\"text-xs text-text-muted aria-selected:text-text-on-brand/70\">\n {action.description}\n </div>\n )}\n </div>\n </div>\n {action.shortcut && action.shortcut.length > 0 && (\n <div className=\"flex items-center gap-0.5\">\n {action.shortcut.map((key) => (\n <kbd\n key={key}\n className=\"rounded border border-border-default bg-surface-background px-1.5 py-0.5 text-[10px] font-medium text-text-muted\"\n >\n {key}\n </kbd>\n ))}\n </div>\n )}\n </Command.Item>\n );\n}\n`;\n}\n\nfunction commandTrigger(): string {\n return `${STAMP}\n'use client';\n\nfunction SearchIcon({ className }: { className?: string }) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n strokeWidth={1.5}\n stroke=\"currentColor\"\n className={className}\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"m21 21-5.197-5.197m0 0A7.5 7.5 0 1 0 5.196 5.196a7.5 7.5 0 0 0 10.607 10.607Z\"\n />\n </svg>\n );\n}\n\nexport function CommandTrigger() {\n function handleClick() {\n const event = new KeyboardEvent('keydown', {\n key: 'k',\n metaKey: true,\n bubbles: true,\n });\n document.dispatchEvent(event);\n }\n\n return (\n <button\n type=\"button\"\n onClick={handleClick}\n className=\"flex items-center gap-2 rounded-lg border border-border-default bg-surface-background px-3 py-1.5 text-sm text-text-muted transition-colors hover:border-border-default hover:text-text-primary\"\n >\n <SearchIcon className=\"size-4\" />\n <span>Search...</span>\n <kbd className=\"rounded border border-border-default bg-surface-card px-1.5 py-0.5 text-[10px] font-medium\">\n ⌘K\n </kbd>\n </button>\n );\n}\n`;\n}\n\nfunction componentIndex(): string {\n return `${STAMP}\nexport { CommandPalette } from './CommandPalette';\nexport { CommandTrigger } from './CommandTrigger';\n`;\n}\n\nfunction featureIndex(): string {\n return `${STAMP}\nexport { CommandPalette, CommandTrigger } from './components';\nexport { registerAction, getCustomActions } from './registry';\nexport { createNavigationActions, createThemeActions, createUserActions } from './actions';\nexport { getRecentActions, addRecentAction } from './recent';\nexport type { CommandAction } from './types';\n`;\n}\n","import fs from 'fs-extra';\nimport path from 'node:path';\nimport { log } from '../../utils/logger.js';\nimport { createRollbackContext } from '../../utils/rollback.js';\nimport { addUserRelation } from '../../utils/prisma.js';\n\nconst GENERATOR_VERSION = '0.1.0';\nconst STAMP = `// @mars-generated onboarding@${GENERATOR_VERSION}`;\n\nexport async function generateOnboarding(projectRoot: string): Promise<void> {\n const featureDir = path.join(projectRoot, 'src', 'features', 'onboarding');\n\n if (await fs.pathExists(featureDir)) {\n log.error('Onboarding feature already exists at src/features/onboarding/');\n return;\n }\n\n const ctx = createRollbackContext();\n\n try {\n const files: Record<string, string> = {\n 'prisma/schema/onboarding.prisma': prismaSchema(),\n 'src/features/onboarding/config.ts': stepConfig(),\n 'src/features/onboarding/types.ts': types(),\n 'src/features/onboarding/server/index.ts': serverLogic(),\n 'src/features/onboarding/validation/schemas.ts': schemas(),\n 'src/features/onboarding/components/OnboardingProgress.tsx': progressBar(),\n 'src/features/onboarding/components/OnboardingFlow.tsx': flowComponent(),\n 'src/features/onboarding/components/index.ts': componentIndex(),\n 'src/app/(protected)/onboarding/page.tsx': onboardingPage(),\n 'src/app/api/protected/onboarding/route.ts': getProgressRoute(),\n 'src/app/api/protected/onboarding/step/route.ts': stepActionRoute(),\n 'src/features/onboarding/index.ts': featureIndex(),\n };\n\n let count = 0;\n for (const [filePath, content] of Object.entries(files)) {\n const fullPath = path.join(projectRoot, filePath);\n ctx.trackCreatedFile(fullPath);\n await fs.ensureDir(path.dirname(fullPath));\n await fs.writeFile(fullPath, content);\n count++;\n }\n\n await addUserRelation(projectRoot, 'onboardingProgress OnboardingProgress?', ctx);\n await setConfigFlag(projectRoot, ctx);\n await ctx.commit();\n\n log.success(`Generated onboarding feature with ${count} files`);\n log.blank();\n log.step('src/features/onboarding/ — config, types, server logic, validation, components');\n log.step('src/app/(protected)/onboarding/ — onboarding page');\n log.step('src/app/api/protected/onboarding/ — progress and step API routes');\n log.step('prisma/schema/onboarding.prisma — OnboardingProgress model');\n log.blank();\n log.warn('Next steps:');\n log.step('Run `yarn db:push` to sync the Prisma schema');\n log.step('Add onboarding redirect check to your protected layout');\n log.step('Customize steps in `src/features/onboarding/config.ts`');\n log.blank();\n } catch (error) {\n await ctx.rollback();\n throw error;\n }\n}\n\nasync function setConfigFlag(projectRoot: string, ctx: { trackModifiedFile: (p: string) => Promise<void> }): Promise<void> {\n const configPath = path.join(projectRoot, 'src', 'config', 'app.config.ts');\n if (!(await fs.pathExists(configPath))) return;\n\n await ctx.trackModifiedFile(configPath);\n const content = await fs.readFile(configPath, 'utf-8');\n const updated = content.replace(/onboarding:\\s*false/, 'onboarding: true');\n await fs.writeFile(configPath, updated);\n}\n\nfunction prismaSchema(): string {\n return `// Generated by mars generate onboarding (onboarding@${GENERATOR_VERSION})\nmodel OnboardingProgress {\n id String @id @default(cuid())\n userId String @unique\n completedAt DateTime?\n currentStep Int @default(0)\n stepsData String @default(\"{}\")\n skippedSteps String @default(\"[]\")\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n}\n`;\n}\n\nfunction stepConfig(): string {\n return `${STAMP}\n\nexport interface OnboardingStep {\n id: string;\n title: string;\n description: string;\n required: boolean;\n}\n\nexport const ONBOARDING_STEPS: OnboardingStep[] = [\n {\n id: 'profile',\n title: 'Complete Your Profile',\n description: 'Add your name and profile details to personalize your experience.',\n required: true,\n },\n {\n id: 'preferences',\n title: 'Set Preferences',\n description: 'Choose your notification and display preferences.',\n required: false,\n },\n {\n id: 'workspace',\n title: 'Create a Workspace',\n description: 'Set up your first workspace to start collaborating.',\n required: true,\n },\n {\n id: 'invite',\n title: 'Invite Team Members',\n description: 'Bring your team on board to work together.',\n required: false,\n },\n];\n`;\n}\n\nfunction types(): string {\n return `${STAMP}\nimport type { OnboardingStep } from './config';\n\nexport interface OnboardingProgressData {\n id: string;\n userId: string;\n completedAt: Date | null;\n currentStep: number;\n stepsData: Record<string, unknown>;\n skippedSteps: number[];\n createdAt: Date;\n updatedAt: Date;\n}\n\nexport type StepStatus = 'complete' | 'current' | 'skipped' | 'pending';\n\nexport interface StepWithStatus extends OnboardingStep {\n index: number;\n status: StepStatus;\n}\n`;\n}\n\nfunction serverLogic(): string {\n return `${STAMP}\nimport 'server-only';\n\nimport { prisma } from '@/lib/prisma';\nimport { ONBOARDING_STEPS } from '../config';\n\nexport async function getOnboardingProgress(userId: string) {\n const existing = await prisma.onboardingProgress.findUnique({\n where: { userId },\n });\n\n if (existing) {\n return {\n ...existing,\n stepsData: JSON.parse(existing.stepsData) as Record<string, unknown>,\n skippedSteps: JSON.parse(existing.skippedSteps) as number[],\n };\n }\n\n const created = await prisma.onboardingProgress.create({\n data: { userId },\n });\n\n return {\n ...created,\n stepsData: {} as Record<string, unknown>,\n skippedSteps: [] as number[],\n };\n}\n\nexport async function updateOnboardingStep(\n userId: string,\n stepIndex: number,\n data?: Record<string, unknown>,\n) {\n const progress = await getOnboardingProgress(userId);\n const stepsData = { ...progress.stepsData };\n\n if (data) {\n const step = ONBOARDING_STEPS[stepIndex];\n if (step) {\n stepsData[step.id] = data;\n }\n }\n\n const nextStep = stepIndex + 1;\n\n return prisma.onboardingProgress.update({\n where: { userId },\n data: {\n currentStep: nextStep,\n stepsData: JSON.stringify(stepsData),\n },\n });\n}\n\nexport async function skipOnboardingStep(userId: string, stepIndex: number) {\n const step = ONBOARDING_STEPS[stepIndex];\n\n if (!step) {\n throw new Error(\\`Invalid step index: \\${stepIndex}\\`);\n }\n\n if (step.required) {\n throw new Error(\\`Cannot skip required step: \\${step.title}\\`);\n }\n\n const progress = await getOnboardingProgress(userId);\n const skippedSteps = [...progress.skippedSteps, stepIndex];\n const nextStep = stepIndex + 1;\n\n return prisma.onboardingProgress.update({\n where: { userId },\n data: {\n currentStep: nextStep,\n skippedSteps: JSON.stringify(skippedSteps),\n },\n });\n}\n\nexport async function completeOnboarding(userId: string) {\n return prisma.onboardingProgress.update({\n where: { userId },\n data: {\n completedAt: new Date(),\n currentStep: ONBOARDING_STEPS.length,\n },\n });\n}\n\nexport async function isOnboardingComplete(userId: string): Promise<boolean> {\n const progress = await prisma.onboardingProgress.findUnique({\n where: { userId },\n select: { completedAt: true },\n });\n\n return progress?.completedAt !== null && progress?.completedAt !== undefined;\n}\n`;\n}\n\nfunction schemas(): string {\n return `${STAMP}\nimport { z } from 'zod';\n\nexport const stepActionSchema = z.object({\n stepIndex: z.number().int().min(0),\n action: z.enum(['complete', 'skip']),\n data: z.record(z.string(), z.unknown()).optional(),\n});\n\nexport type StepAction = z.infer<typeof stepActionSchema>;\n`;\n}\n\nfunction progressBar(): string {\n return `${STAMP}\nimport type { StepWithStatus } from '../types';\n\ninterface OnboardingProgressProps {\n steps: StepWithStatus[];\n}\n\nexport function OnboardingProgress({ steps }: OnboardingProgressProps) {\n return (\n <nav aria-label=\"Onboarding progress\" className=\"w-full\">\n <ol className=\"flex items-center\">\n {steps.map((step, index) => (\n <li key={step.id} className=\"flex items-center\">\n <div className=\"flex flex-col items-center\">\n <div className=\"flex items-center justify-center\">\n {step.status === 'complete' ? (\n <span className=\"flex h-8 w-8 items-center justify-center rounded-full bg-brand-primary\">\n <svg\n className=\"h-4 w-4 text-text-on-brand\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n strokeWidth={2.5}\n stroke=\"currentColor\"\n >\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M4.5 12.75l6 6 9-13.5\" />\n </svg>\n </span>\n ) : step.status === 'current' ? (\n <span className=\"flex h-8 w-8 items-center justify-center rounded-full border-2 border-brand-primary bg-surface-card\">\n <span className=\"text-sm font-semibold text-brand-primary\">{index + 1}</span>\n </span>\n ) : step.status === 'skipped' ? (\n <span className=\"flex h-8 w-8 items-center justify-center rounded-full bg-surface-muted\">\n <span className=\"text-sm text-text-muted line-through\">{index + 1}</span>\n </span>\n ) : (\n <span className=\"flex h-8 w-8 items-center justify-center rounded-full border border-border-default bg-surface-card\">\n <span className=\"text-sm text-text-muted\">{index + 1}</span>\n </span>\n )}\n </div>\n <span\n className={\\`mt-2 text-center text-xs font-medium \\${\n step.status === 'current'\n ? 'text-brand-primary'\n : step.status === 'complete'\n ? 'text-text-primary'\n : 'text-text-muted'\n }\\`}\n >\n {step.title}\n </span>\n </div>\n\n {index < steps.length - 1 && (\n <div\n className={\\`mx-2 h-0.5 w-12 sm:w-20 \\${\n step.status === 'complete' ? 'bg-brand-primary' : 'bg-border-default'\n }\\`}\n />\n )}\n </li>\n ))}\n </ol>\n </nav>\n );\n}\n`;\n}\n\nfunction flowComponent(): string {\n return `${STAMP}\n'use client';\n\nimport { useState, useCallback } from 'react';\nimport { useRouter } from 'next/navigation';\nimport { OnboardingProgress } from './OnboardingProgress';\nimport { ONBOARDING_STEPS } from '../config';\nimport type { StepWithStatus, OnboardingProgressData } from '../types';\n\ninterface OnboardingFlowProps {\n initialProgress: OnboardingProgressData;\n}\n\nexport function OnboardingFlow({ initialProgress }: OnboardingFlowProps) {\n const router = useRouter();\n const [currentStep, setCurrentStep] = useState(initialProgress.currentStep);\n const [skippedSteps, setSkippedSteps] = useState<number[]>(initialProgress.skippedSteps);\n const [isLoading, setIsLoading] = useState(false);\n\n const steps: StepWithStatus[] = ONBOARDING_STEPS.map((step, index) => ({\n ...step,\n index,\n status:\n index < currentStep\n ? skippedSteps.includes(index)\n ? 'skipped'\n : 'complete'\n : index === currentStep\n ? 'current'\n : 'pending',\n }));\n\n const activeStep = ONBOARDING_STEPS[currentStep];\n const isLastStep = currentStep >= ONBOARDING_STEPS.length;\n\n const handleAction = useCallback(\n async (action: 'complete' | 'skip') => {\n setIsLoading(true);\n try {\n const response = await fetch('/api/protected/onboarding/step', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n credentials: 'include',\n body: JSON.stringify({ stepIndex: currentStep, action }),\n });\n\n if (!response.ok) {\n const errorData: { error?: string } = await response.json();\n throw new Error(errorData.error || 'Failed to update step');\n }\n\n if (action === 'skip') {\n setSkippedSteps((prev) => [...prev, currentStep]);\n }\n\n const nextStep = currentStep + 1;\n setCurrentStep(nextStep);\n\n if (nextStep >= ONBOARDING_STEPS.length) {\n router.push('/dashboard');\n }\n } catch (error) {\n console.error('Onboarding step error:', error);\n } finally {\n setIsLoading(false);\n }\n },\n [currentStep, router],\n );\n\n if (isLastStep) {\n return (\n <div className=\"flex min-h-[400px] items-center justify-center\">\n <div className=\"text-center\">\n <h2 className=\"text-2xl font-bold text-text-primary\">All done!</h2>\n <p className=\"mt-2 text-text-secondary\">Redirecting to your dashboard...</p>\n </div>\n </div>\n );\n }\n\n return (\n <div className=\"mx-auto w-full max-w-2xl px-4 py-12\">\n <OnboardingProgress steps={steps} />\n\n <div className=\"mt-10 rounded-2xl border border-border-default bg-surface-card p-8\">\n <h2 className=\"text-2xl font-bold text-text-primary\">{activeStep?.title}</h2>\n <p className=\"mt-2 text-text-secondary\">{activeStep?.description}</p>\n\n <div className=\"mt-8 flex items-center gap-3\">\n <button\n type=\"button\"\n onClick={() => handleAction('complete')}\n disabled={isLoading}\n className=\"rounded-lg bg-brand-primary px-6 py-2.5 text-sm font-medium text-text-on-brand transition-colors hover:bg-brand-primary-hover disabled:opacity-50\"\n >\n {isLoading ? 'Saving...' : 'Complete Step'}\n </button>\n\n {activeStep && !activeStep.required && (\n <button\n type=\"button\"\n onClick={() => handleAction('skip')}\n disabled={isLoading}\n className=\"rounded-lg border border-border-default bg-surface-card px-6 py-2.5 text-sm font-medium text-text-secondary transition-colors hover:bg-surface-muted disabled:opacity-50\"\n >\n Skip\n </button>\n )}\n </div>\n </div>\n </div>\n );\n}\n`;\n}\n\nfunction componentIndex(): string {\n return `${STAMP}\nexport { OnboardingProgress } from './OnboardingProgress';\nexport { OnboardingFlow } from './OnboardingFlow';\n`;\n}\n\nfunction onboardingPage(): string {\n return `${STAMP}\nimport { redirect } from 'next/navigation';\nimport { getSession } from '@/lib/mars';\nimport { getOnboardingProgress, isOnboardingComplete } from '@/features/onboarding/server';\nimport { OnboardingFlow } from '@/features/onboarding/components';\n\nexport default async function OnboardingPage() {\n const session = await getSession();\n\n if (!session) {\n redirect('/sign-in');\n }\n\n const complete = await isOnboardingComplete(session.userId);\n if (complete) {\n redirect('/dashboard');\n }\n\n const progress = await getOnboardingProgress(session.userId);\n\n return (\n <div className=\"flex min-h-screen flex-col items-center justify-center bg-surface-background\">\n <div className=\"w-full max-w-3xl\">\n <div className=\"mb-8 text-center\">\n <h1 className=\"text-3xl font-bold tracking-tight text-text-primary\">\n Welcome! Let&apos;s get you set up.\n </h1>\n <p className=\"mt-2 text-text-secondary\">\n Complete these steps to get the most out of your account.\n </p>\n </div>\n <OnboardingFlow initialProgress={progress} />\n </div>\n </div>\n );\n}\n`;\n}\n\nfunction getProgressRoute(): string {\n return `${STAMP}\nimport { withAuthNoParams, handleApiError } from '@/lib/mars';\nimport { getOnboardingProgress } from '@/features/onboarding/server';\nimport type { AuthenticatedRequest } from '@mars-stack/core/auth/middleware';\nimport { NextResponse } from 'next/server';\n\nexport const GET = withAuthNoParams(async (request: AuthenticatedRequest) => {\n try {\n const progress = await getOnboardingProgress(request.session.userId);\n return NextResponse.json({ progress });\n } catch (error) {\n return handleApiError(error, { endpoint: '/api/protected/onboarding' });\n }\n});\n`;\n}\n\nfunction stepActionRoute(): string {\n return `${STAMP}\nimport { withAuthNoParams, handleApiError } from '@/lib/mars';\nimport {\n updateOnboardingStep,\n skipOnboardingStep,\n completeOnboarding,\n} from '@/features/onboarding/server';\nimport { stepActionSchema } from '@/features/onboarding/validation/schemas';\nimport { ONBOARDING_STEPS } from '@/features/onboarding/config';\nimport type { AuthenticatedRequest } from '@mars-stack/core/auth/middleware';\nimport { NextResponse } from 'next/server';\n\nexport const POST = withAuthNoParams(async (request: AuthenticatedRequest) => {\n try {\n const body = await request.json();\n const result = stepActionSchema.safeParse(body);\n\n if (!result.success) {\n return NextResponse.json(\n { error: result.error.issues[0]?.message || 'Invalid input' },\n { status: 400 },\n );\n }\n\n const { stepIndex, action, data } = result.data;\n const userId = request.session.userId;\n\n if (stepIndex < 0 || stepIndex >= ONBOARDING_STEPS.length) {\n return NextResponse.json({ error: 'Invalid step index' }, { status: 400 });\n }\n\n if (action === 'skip') {\n await skipOnboardingStep(userId, stepIndex);\n } else {\n await updateOnboardingStep(userId, stepIndex, data);\n }\n\n const isLastStep = stepIndex + 1 >= ONBOARDING_STEPS.length;\n if (isLastStep) {\n await completeOnboarding(userId);\n }\n\n return NextResponse.json({ success: true });\n } catch (error) {\n if (error instanceof Error && error.message.startsWith('Cannot skip required step')) {\n return NextResponse.json({ error: error.message }, { status: 400 });\n }\n return handleApiError(error, { endpoint: '/api/protected/onboarding/step' });\n }\n});\n`;\n}\n\nfunction featureIndex(): string {\n return `${STAMP}\nexport { ONBOARDING_STEPS } from './config';\nexport type { OnboardingStep } from './config';\nexport type { OnboardingProgressData, StepStatus, StepWithStatus } from './types';\nexport {\n getOnboardingProgress,\n updateOnboardingStep,\n skipOnboardingStep,\n completeOnboarding,\n isOnboardingComplete,\n} from './server';\n`;\n}\n","import fs from 'fs-extra';\nimport path from 'node:path';\nimport { log } from '../../utils/logger.js';\nimport { createRollbackContext } from '../../utils/rollback.js';\n\nconst GENERATOR_VERSION = '0.1.0';\nconst STAMP = `// @mars-generated search@${GENERATOR_VERSION}`;\n\nexport async function generateSearch(projectRoot: string): Promise<void> {\n const featureDir = path.join(projectRoot, 'src', 'features', 'search');\n\n if (await fs.pathExists(featureDir)) {\n log.error('Search feature already exists at src/features/search/');\n return;\n }\n\n const ctx = createRollbackContext();\n\n try {\n const files: Record<string, string> = {\n 'src/features/search/types.ts': types(),\n 'src/features/search/validation/schemas.ts': schemas(),\n 'src/features/search/server/postgres.ts': postgresProvider(),\n 'src/features/search/server/index.ts': serverIndex(),\n 'src/features/search/hooks/use-search.ts': useSearchHook(),\n 'src/features/search/components/SearchInput.tsx': searchInput(),\n 'src/features/search/components/index.ts': componentIndex(),\n 'src/features/search/index.ts': featureIndex(),\n 'src/app/api/protected/search/route.ts': searchRoute(),\n };\n\n let count = 0;\n for (const [filePath, content] of Object.entries(files)) {\n const fullPath = path.join(projectRoot, filePath);\n ctx.trackCreatedFile(fullPath);\n await fs.ensureDir(path.dirname(fullPath));\n await fs.writeFile(fullPath, content);\n count++;\n }\n\n await setConfigFlag(projectRoot, ctx);\n await ctx.commit();\n\n log.success(`Generated search feature with ${count} files`);\n log.blank();\n log.step('src/features/search/ — types, validation, server logic, hooks, components');\n log.step('src/app/api/protected/search/ — authenticated search endpoint');\n log.blank();\n log.warn('Search uses Postgres full-text search by default (no extra setup).');\n log.blank();\n log.step('For Algolia: yarn add algoliasearch + set ALGOLIA_APP_ID, ALGOLIA_API_KEY env vars');\n log.step('For Meilisearch: yarn add meilisearch + set MEILISEARCH_HOST, MEILISEARCH_API_KEY env vars');\n log.blank();\n log.step('Add a tsvector column via raw migration for models you want to search');\n log.step('Use the useSearch hook or SearchInput component in your pages');\n log.blank();\n } catch (error) {\n await ctx.rollback();\n throw error;\n }\n}\n\nasync function setConfigFlag(projectRoot: string, ctx: { trackModifiedFile: (p: string) => Promise<void> }): Promise<void> {\n const configPath = path.join(projectRoot, 'src', 'config', 'app.config.ts');\n if (!(await fs.pathExists(configPath))) return;\n\n await ctx.trackModifiedFile(configPath);\n const content = await fs.readFile(configPath, 'utf-8');\n const updated = content.replace(/search:\\s*false/, 'search: true');\n await fs.writeFile(configPath, updated);\n}\n\nfunction types(): string {\n return `${STAMP}\n\nexport interface SearchResult<T = Record<string, unknown>> {\n id: string;\n score: number;\n data: T;\n}\n\nexport interface SearchOptions {\n model: string;\n page?: number;\n limit?: number;\n}\n\nexport interface SearchProvider {\n search<T = Record<string, unknown>>(query: string, options: SearchOptions): Promise<SearchResult<T>[]>;\n index(model: string, id: string, data: Record<string, unknown>): Promise<void>;\n remove(model: string, id: string): Promise<void>;\n}\n`;\n}\n\nfunction schemas(): string {\n return `${STAMP}\nimport { z } from 'zod';\n\nexport const searchParamsSchema = z.object({\n q: z.string().min(1).max(500),\n model: z.string().min(1).max(100),\n page: z.coerce.number().int().positive().default(1),\n limit: z.coerce.number().int().min(1).max(100).default(20),\n});\n\nexport type SearchParams = z.infer<typeof searchParamsSchema>;\n`;\n}\n\nfunction postgresProvider(): string {\n return `${STAMP}\nimport 'server-only';\n\nimport { prisma } from '@/lib/prisma';\nimport type { SearchResult, SearchOptions, SearchProvider } from '../types';\n\nfunction sanitizeQuery(raw: string): string {\n return raw\n .replace(/[^\\\\w\\\\s]/g, '')\n .trim()\n .split(/\\\\s+/)\n .filter(Boolean)\n .join(' & ');\n}\n\nasync function searchPostgres<T = Record<string, unknown>>(\n query: string,\n options: SearchOptions,\n): Promise<SearchResult<T>[]> {\n const sanitized = sanitizeQuery(query);\n if (!sanitized) return [];\n\n const { model, page = 1, limit = 20 } = options;\n const offset = (page - 1) * limit;\n\n const results = await prisma.$queryRaw<Array<{ id: string; rank: number; data: unknown }>>\\`\n SELECT\n id,\n ts_rank(search_vector, plainto_tsquery('english', \\${sanitized})) AS rank,\n row_to_json(t.*) AS data\n FROM \\${prisma.$queryRawUnsafe(\\`\"\\${model}\"\\`)} t\n WHERE search_vector @@ plainto_tsquery('english', \\${sanitized})\n ORDER BY rank DESC\n LIMIT \\${limit}\n OFFSET \\${offset}\n \\`;\n\n return results.map((row) => ({\n id: row.id,\n score: row.rank,\n data: row.data as T,\n }));\n}\n\nexport const postgresSearchProvider: SearchProvider = {\n async search<T = Record<string, unknown>>(query: string, options: SearchOptions) {\n return searchPostgres<T>(query, options);\n },\n\n async index(_model: string, _id: string, _data: Record<string, unknown>) {\n // Postgres tsvector columns are maintained via triggers — no-op\n },\n\n async remove(_model: string, _id: string) {\n // Postgres handles this via cascading deletes — no-op\n },\n};\n`;\n}\n\nfunction serverIndex(): string {\n return `${STAMP}\nimport 'server-only';\n\nimport { appConfig } from '@/config/app.config';\nimport type { SearchProvider } from '../types';\nimport { postgresSearchProvider } from './postgres';\n\nexport async function getSearchProvider(): Promise<SearchProvider> {\n const provider: string = appConfig.services.search.provider;\n\n switch (provider) {\n case 'algolia':\n throw new Error('Algolia provider not installed. Run: yarn add algoliasearch');\n case 'meilisearch':\n throw new Error('Meilisearch provider not installed. Run: yarn add meilisearch');\n case 'postgres':\n case 'local':\n case 'none':\n default:\n return postgresSearchProvider;\n }\n}\n`;\n}\n\nfunction useSearchHook(): string {\n return `${STAMP}\n'use client';\n\nimport { useState, useEffect, useRef, useCallback } from 'react';\nimport type { SearchResult } from '../types';\n\ninterface UseSearchOptions {\n model: string;\n debounceMs?: number;\n limit?: number;\n}\n\ninterface UseSearchReturn<T> {\n query: string;\n setQuery: (q: string) => void;\n results: SearchResult<T>[];\n isLoading: boolean;\n page: number;\n setPage: (p: number) => void;\n error: string | null;\n}\n\nexport function useSearch<T = Record<string, unknown>>(\n options: UseSearchOptions,\n): UseSearchReturn<T> {\n const { model, debounceMs = 300, limit = 20 } = options;\n\n const [query, setQuery] = useState('');\n const [results, setResults] = useState<SearchResult<T>[]>([]);\n const [isLoading, setIsLoading] = useState(false);\n const [page, setPage] = useState(1);\n const [error, setError] = useState<string | null>(null);\n const abortRef = useRef<AbortController | null>(null);\n\n const fetchResults = useCallback(\n async (q: string, p: number) => {\n if (!q.trim()) {\n setResults([]);\n setIsLoading(false);\n return;\n }\n\n abortRef.current?.abort();\n const controller = new AbortController();\n abortRef.current = controller;\n\n setIsLoading(true);\n setError(null);\n\n try {\n const params = new URLSearchParams({\n q,\n model,\n page: String(p),\n limit: String(limit),\n });\n\n const response = await fetch(\\`/api/protected/search?\\${params}\\`, {\n signal: controller.signal,\n });\n\n if (!response.ok) {\n const body = await response.json().catch(() => ({}));\n throw new Error(body.error || 'Search request failed');\n }\n\n const data = await response.json();\n setResults(data.results ?? []);\n } catch (err) {\n if (err instanceof DOMException && err.name === 'AbortError') return;\n setError(err instanceof Error ? err.message : 'Search failed');\n setResults([]);\n } finally {\n if (!controller.signal.aborted) {\n setIsLoading(false);\n }\n }\n },\n [model, limit],\n );\n\n useEffect(() => {\n const timer = setTimeout(() => {\n fetchResults(query, page);\n }, debounceMs);\n\n return () => clearTimeout(timer);\n }, [query, page, debounceMs, fetchResults]);\n\n useEffect(() => {\n setPage(1);\n }, [query]);\n\n return { query, setQuery, results, isLoading, page, setPage, error };\n}\n`;\n}\n\nfunction searchInput(): string {\n return `${STAMP}\n'use client';\n\ninterface SearchInputProps {\n value: string;\n onQueryChange: (query: string) => void;\n placeholder?: string;\n autoFocus?: boolean;\n className?: string;\n}\n\nexport function SearchInput({\n value,\n onQueryChange,\n placeholder = 'Search...',\n autoFocus = false,\n className = '',\n}: SearchInputProps) {\n return (\n <div className={\\`relative \\${className}\\`}>\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n strokeWidth={1.5}\n stroke=\"currentColor\"\n className=\"pointer-events-none absolute left-3 top-1/2 size-5 -translate-y-1/2 text-text-muted\"\n aria-hidden=\"true\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"m21 21-5.197-5.197m0 0A7.5 7.5 0 1 0 5.196 5.196a7.5 7.5 0 0 0 10.607 10.607Z\"\n />\n </svg>\n <input\n type=\"search\"\n value={value}\n onChange={(e) => onQueryChange(e.target.value)}\n placeholder={placeholder}\n autoFocus={autoFocus}\n className=\"w-full rounded-xl border border-border-default bg-surface-card py-2.5 pl-10 pr-4 text-sm text-text-primary placeholder:text-text-muted transition-colors focus:border-brand-primary focus:outline-none focus:ring-2 focus:ring-brand-primary/20\"\n />\n </div>\n );\n}\n`;\n}\n\nfunction componentIndex(): string {\n return `${STAMP}\nexport { SearchInput } from './SearchInput';\n`;\n}\n\nfunction featureIndex(): string {\n return `${STAMP}\nexport type { SearchResult, SearchOptions, SearchProvider } from './types';\nexport { searchParamsSchema } from './validation/schemas';\nexport type { SearchParams } from './validation/schemas';\nexport { SearchInput } from './components';\nexport { useSearch } from './hooks/use-search';\n`;\n}\n\nfunction searchRoute(): string {\n return `${STAMP}\nimport { NextRequest, NextResponse } from 'next/server';\nimport { withAuthNoParams, handleApiError } from '@/lib/mars';\nimport { searchParamsSchema } from '@/features/search/validation/schemas';\nimport { getSearchProvider } from '@/features/search/server';\n\nexport const GET = withAuthNoParams(async (request) => {\n try {\n const url = new URL(request.url);\n const raw = Object.fromEntries(url.searchParams);\n\n const parsed = searchParamsSchema.safeParse(raw);\n if (!parsed.success) {\n return NextResponse.json(\n { error: 'Invalid search parameters', details: parsed.error.flatten().fieldErrors },\n { status: 400 },\n );\n }\n\n const { q, model, page, limit } = parsed.data;\n const provider = await getSearchProvider();\n const results = await provider.search(q, { model, page, limit });\n\n return NextResponse.json({ results, page, limit });\n } catch (error) {\n return handleApiError(error, { endpoint: '/api/protected/search' });\n }\n});\n`;\n}\n","import fs from 'fs-extra';\nimport path from 'node:path';\nimport { log } from '../../utils/logger.js';\nimport { createRollbackContext } from '../../utils/rollback.js';\n\nconst GENERATOR_VERSION = '0.1.0';\nconst STAMP = `// @mars-generated realtime@${GENERATOR_VERSION}`;\n\nexport async function generateRealtime(projectRoot: string): Promise<void> {\n const featureDir = path.join(projectRoot, 'src', 'features', 'realtime');\n\n if (await fs.pathExists(featureDir)) {\n log.error('Realtime feature already exists at src/features/realtime/');\n return;\n }\n\n const ctx = createRollbackContext();\n\n try {\n const files: Record<string, string> = {\n 'src/features/realtime/types.ts': types(),\n 'src/features/realtime/server/index.ts': serverIndex(),\n 'src/features/realtime/server/sse.ts': sseProvider(),\n 'src/features/realtime/hooks/use-event-source.ts': useEventSourceHook(),\n 'src/features/realtime/hooks/index.ts': hooksIndex(),\n 'src/features/realtime/index.ts': featureIndex(),\n 'src/app/api/protected/realtime/stream/route.ts': sseStreamRoute(),\n };\n\n let count = 0;\n for (const [filePath, content] of Object.entries(files)) {\n const fullPath = path.join(projectRoot, filePath);\n ctx.trackCreatedFile(fullPath);\n await fs.ensureDir(path.dirname(fullPath));\n await fs.writeFile(fullPath, content);\n count++;\n }\n\n await setConfigFlag(projectRoot, ctx);\n await ctx.commit();\n\n log.success(`Generated realtime feature with ${count} files`);\n log.blank();\n log.step('src/features/realtime/ — types, server provider, SSE client hook');\n log.step('src/app/api/protected/realtime/stream/ — authenticated SSE endpoint');\n log.blank();\n log.info('Realtime uses Server-Sent Events by default (no external services)');\n log.warn('SSE has a ~30s timeout on serverless (Vercel) — use Pusher or Ably for production');\n log.blank();\n log.step('For Pusher: yarn add pusher pusher-js + set PUSHER_* env vars');\n log.step('For Ably: yarn add ably + set ABLY_API_KEY env var');\n log.blank();\n log.info('Use publish(channel, event, data) from server code to send events');\n log.info('Use useEventSource hook to listen for events in client components');\n log.blank();\n } catch (error) {\n await ctx.rollback();\n throw error;\n }\n}\n\nasync function setConfigFlag(projectRoot: string, ctx: { trackModifiedFile: (p: string) => Promise<void> }): Promise<void> {\n const configPath = path.join(projectRoot, 'src', 'config', 'app.config.ts');\n if (!(await fs.pathExists(configPath))) return;\n\n await ctx.trackModifiedFile(configPath);\n const content = await fs.readFile(configPath, 'utf-8');\n const updated = content.replace(/realtime:\\s*false/, 'realtime: true');\n await fs.writeFile(configPath, updated);\n}\n\nfunction types(): string {\n return `${STAMP}\n\nexport interface RealtimeProvider {\n publish(channel: string, event: string, data: unknown): Promise<void>;\n authorizeChannel?(channel: string, userId: string): Promise<boolean>;\n}\n\nexport interface RealtimeEvent<T = unknown> {\n channel: string;\n event: string;\n data: T;\n timestamp: number;\n}\n\nexport type RealtimeProviderType = 'sse' | 'pusher' | 'ably';\n`;\n}\n\nfunction serverIndex(): string {\n return `${STAMP}\nimport 'server-only';\n\nimport { appConfig } from '@/config/app.config';\nimport type { RealtimeProvider } from '../types';\n\nlet cachedProvider: RealtimeProvider | null = null;\n\nexport async function getRealtimeProvider(): Promise<RealtimeProvider> {\n if (cachedProvider) return cachedProvider;\n\n const providerType: string = appConfig.services.realtime.provider;\n\n switch (providerType) {\n case 'pusher': {\n throw new Error(\n 'Pusher provider not installed. Run: yarn add pusher pusher-js',\n );\n }\n case 'ably': {\n throw new Error(\n 'Ably provider not installed. Run: yarn add ably',\n );\n }\n default: {\n const { SSEProvider } = await import('./sse');\n cachedProvider = new SSEProvider();\n return cachedProvider;\n }\n }\n}\n\nexport async function publish(\n channel: string,\n event: string,\n data: unknown,\n): Promise<void> {\n const provider = await getRealtimeProvider();\n await provider.publish(channel, event, data);\n}\n`;\n}\n\nfunction sseProvider(): string {\n return `${STAMP}\nimport 'server-only';\n\nimport type { RealtimeProvider, RealtimeEvent } from '../types';\n\ntype Subscriber = (event: RealtimeEvent) => void;\n\nconst subscribers = new Map<string, Set<Subscriber>>();\n\nexport class SSEProvider implements RealtimeProvider {\n async publish(channel: string, event: string, data: unknown): Promise<void> {\n const channelSubs = subscribers.get(channel);\n if (!channelSubs || channelSubs.size === 0) return;\n\n const realtimeEvent: RealtimeEvent = {\n channel,\n event,\n data,\n timestamp: Date.now(),\n };\n\n for (const callback of channelSubs) {\n try {\n callback(realtimeEvent);\n } catch {\n // Subscriber errors should not break publish\n }\n }\n }\n}\n\nexport function subscribe(\n channel: string,\n callback: Subscriber,\n): () => void {\n if (!subscribers.has(channel)) {\n subscribers.set(channel, new Set());\n }\n\n const channelSubs = subscribers.get(channel)!;\n channelSubs.add(callback);\n\n return () => {\n channelSubs.delete(callback);\n if (channelSubs.size === 0) {\n subscribers.delete(channel);\n }\n };\n}\n`;\n}\n\nfunction useEventSourceHook(): string {\n return `${STAMP}\n'use client';\n\nimport { useEffect, useRef, useState, useCallback } from 'react';\n\ninterface UseEventSourceOptions {\n channel: string;\n events?: string[];\n onEvent: (event: string, data: unknown) => void;\n enabled?: boolean;\n}\n\nconst MIN_RETRY_MS = 1000;\nconst MAX_RETRY_MS = 30000;\n\nexport function useEventSource({\n channel,\n events,\n onEvent,\n enabled = true,\n}: UseEventSourceOptions) {\n const [connected, setConnected] = useState(false);\n const retryDelay = useRef(MIN_RETRY_MS);\n const retryTimer = useRef<ReturnType<typeof setTimeout> | null>(null);\n const eventSourceRef = useRef<EventSource | null>(null);\n const onEventRef = useRef(onEvent);\n onEventRef.current = onEvent;\n\n const connect = useCallback(() => {\n if (eventSourceRef.current) {\n eventSourceRef.current.close();\n }\n\n const params = new URLSearchParams({ channel });\n if (events && events.length > 0) {\n params.set('events', events.join(','));\n }\n\n const es = new EventSource(\\`/api/protected/realtime/stream?\\${params}\\`);\n eventSourceRef.current = es;\n\n es.onopen = () => {\n setConnected(true);\n retryDelay.current = MIN_RETRY_MS;\n };\n\n es.onmessage = (msg) => {\n try {\n const parsed = JSON.parse(msg.data);\n onEventRef.current(parsed.event, parsed.data);\n } catch {\n // Malformed messages are silently dropped\n }\n };\n\n es.onerror = () => {\n setConnected(false);\n es.close();\n eventSourceRef.current = null;\n\n retryTimer.current = setTimeout(() => {\n retryDelay.current = Math.min(retryDelay.current * 2, MAX_RETRY_MS);\n connect();\n }, retryDelay.current);\n };\n }, [channel, events]);\n\n useEffect(() => {\n if (!enabled) {\n eventSourceRef.current?.close();\n eventSourceRef.current = null;\n setConnected(false);\n return;\n }\n\n connect();\n\n return () => {\n if (retryTimer.current) clearTimeout(retryTimer.current);\n eventSourceRef.current?.close();\n eventSourceRef.current = null;\n setConnected(false);\n };\n }, [enabled, connect]);\n\n return { connected };\n}\n`;\n}\n\nfunction hooksIndex(): string {\n return `${STAMP}\nexport { useEventSource } from './use-event-source';\n`;\n}\n\nfunction featureIndex(): string {\n return `${STAMP}\nexport type {\n RealtimeProvider,\n RealtimeEvent,\n RealtimeProviderType,\n} from './types';\n\nexport { useEventSource } from './hooks';\n`;\n}\n\nfunction sseStreamRoute(): string {\n return `${STAMP}\nimport { NextResponse } from 'next/server';\nimport { withAuthNoParams } from '@/lib/mars';\nimport { subscribe } from '@/features/realtime/server/sse';\n\nexport const dynamic = 'force-dynamic';\n\nexport const GET = withAuthNoParams(async (request) => {\n const channel = request.nextUrl.searchParams.get('channel');\n if (!channel) {\n return NextResponse.json(\n { error: 'Missing channel parameter' },\n { status: 400 },\n );\n }\n\n const eventsParam = request.nextUrl.searchParams.get('events');\n const allowedEvents = eventsParam ? eventsParam.split(',') : null;\n\n const stream = new ReadableStream({\n start(controller) {\n const encoder = new TextEncoder();\n\n const keepAlive = setInterval(() => {\n try {\n controller.enqueue(encoder.encode(': keepalive\\\\n\\\\n'));\n } catch {\n clearInterval(keepAlive);\n }\n }, 15000);\n\n const unsubscribe = subscribe(channel, (event) => {\n if (allowedEvents && !allowedEvents.includes(event.event)) return;\n\n const payload = JSON.stringify({\n event: event.event,\n data: event.data,\n timestamp: event.timestamp,\n });\n\n try {\n controller.enqueue(encoder.encode(\\`data: \\${payload}\\\\n\\\\n\\`));\n } catch {\n clearInterval(keepAlive);\n unsubscribe();\n }\n });\n\n request.signal.addEventListener('abort', () => {\n clearInterval(keepAlive);\n unsubscribe();\n try {\n controller.close();\n } catch {\n // Stream already closed\n }\n });\n },\n });\n\n return new NextResponse(stream, {\n headers: {\n 'Content-Type': 'text/event-stream',\n 'Cache-Control': 'no-cache, no-transform',\n Connection: 'keep-alive',\n 'X-Accel-Buffering': 'no',\n },\n });\n});\n`;\n}\n","import fs from 'fs-extra';\nimport path from 'node:path';\nimport { log } from '../../utils/logger.js';\nimport { createRollbackContext } from '../../utils/rollback.js';\nimport { addDependencies } from '../../utils/dependencies.js';\n\nconst GENERATOR_VERSION = '0.1.0';\nconst STAMP = `// @mars-generated ai@${GENERATOR_VERSION}`;\n\nexport async function generateAI(projectRoot: string): Promise<void> {\n const featureDir = path.join(projectRoot, 'src', 'features', 'ai');\n\n if (await fs.pathExists(featureDir)) {\n log.error('AI feature already exists at src/features/ai/');\n return;\n }\n\n const ctx = createRollbackContext();\n\n try {\n const files: Record<string, string> = {\n 'src/features/ai/types.ts': types(),\n 'src/features/ai/server/index.ts': serverFactory(),\n 'src/features/ai/server/openai-provider.ts': openaiProvider(),\n 'src/features/ai/server/anthropic-provider.ts': anthropicProvider(),\n 'src/features/ai/validation/schemas.ts': schemas(),\n 'src/features/ai/hooks/use-chat.ts': useChatHook(),\n 'src/features/ai/index.ts': barrelExports(),\n 'src/app/api/protected/ai/chat/route.ts': chatRoute(),\n };\n\n let count = 0;\n for (const [filePath, content] of Object.entries(files)) {\n const fullPath = path.join(projectRoot, filePath);\n ctx.trackCreatedFile(fullPath);\n await fs.ensureDir(path.dirname(fullPath));\n await fs.writeFile(fullPath, content);\n count++;\n }\n\n await addDependencies(projectRoot, {\n openai: '^4.0.0',\n '@anthropic-ai/sdk': '^0.30.0',\n });\n await setConfigFlag(projectRoot, ctx);\n await ctx.commit();\n\n log.success(`Generated AI feature with ${count} files`);\n log.blank();\n log.step('src/features/ai/ — types, provider factory, hooks, validation');\n log.step('src/app/api/protected/ai/chat/ — streaming chat endpoint');\n log.blank();\n log.warn('Next steps:');\n log.step('Set the provider in appConfig.services.ai.provider (\"openai\" or \"anthropic\")');\n log.step('Set OPENAI_API_KEY or ANTHROPIC_API_KEY in .env');\n log.step('Use getAIProvider() from server code for chat/streaming');\n log.step('Use useChat() hook for client-side chat interfaces');\n log.blank();\n } catch (error) {\n await ctx.rollback();\n throw error;\n }\n}\n\nasync function setConfigFlag(projectRoot: string, ctx: { trackModifiedFile: (p: string) => Promise<void> }): Promise<void> {\n const configPath = path.join(projectRoot, 'src', 'config', 'app.config.ts');\n if (!(await fs.pathExists(configPath))) return;\n\n await ctx.trackModifiedFile(configPath);\n const content = await fs.readFile(configPath, 'utf-8');\n const updated = content.replace(/ai:\\s*false/, 'ai: true');\n await fs.writeFile(configPath, updated);\n}\n\nfunction types(): string {\n return `${STAMP}\n\nexport interface ChatMessage {\n role: 'system' | 'user' | 'assistant';\n content: string;\n}\n\nexport interface ChatParams {\n messages: ChatMessage[];\n model?: string;\n temperature?: number;\n maxTokens?: number;\n jsonMode?: boolean;\n}\n\nexport interface ChatResponse {\n content: string;\n usage: {\n promptTokens: number;\n completionTokens: number;\n totalTokens: number;\n };\n finishReason: string;\n}\n\nexport interface AIProvider {\n chat(params: ChatParams): Promise<ChatResponse>;\n stream(params: ChatParams): ReadableStream<Uint8Array>;\n}\n`;\n}\n\nfunction serverFactory(): string {\n return `${STAMP}\nimport 'server-only';\n\nimport { appConfig } from '@/config/app.config';\nimport type { AIProvider } from '../types';\n\nlet cachedProvider: AIProvider | null = null;\n\nexport async function getAIProvider(): Promise<AIProvider> {\n if (cachedProvider) return cachedProvider;\n\n const providerName: string = appConfig.services.ai.provider;\n\n switch (providerName) {\n case 'anthropic': {\n const { createAnthropicProvider } = await import('./anthropic-provider');\n cachedProvider = createAnthropicProvider();\n break;\n }\n case 'openai':\n default: {\n const { createOpenAIProvider } = await import('./openai-provider');\n cachedProvider = createOpenAIProvider();\n break;\n }\n }\n\n return cachedProvider;\n}\n`;\n}\n\nfunction openaiProvider(): string {\n return `${STAMP}\nimport 'server-only';\n\nimport OpenAI from 'openai';\nimport type { AIProvider, ChatParams, ChatResponse } from '../types';\n\nlet client: OpenAI | null = null;\n\nfunction getClient(): OpenAI {\n if (client) return client;\n\n const apiKey = process.env.OPENAI_API_KEY;\n if (!apiKey) {\n throw new Error(\n 'OPENAI_API_KEY is not set. Add it to your .env file to use the OpenAI provider.',\n );\n }\n\n client = new OpenAI({ apiKey });\n return client;\n}\n\nfunction getDefaultModel(): string {\n return process.env.OPENAI_MODEL || 'gpt-4o';\n}\n\nexport function createOpenAIProvider(): AIProvider {\n return { chat, stream };\n}\n\nasync function chat(params: ChatParams): Promise<ChatResponse> {\n const openai = getClient();\n\n const response = await openai.chat.completions.create({\n model: params.model || getDefaultModel(),\n messages: params.messages.map((m) => ({ role: m.role, content: m.content })),\n temperature: params.temperature,\n max_tokens: params.maxTokens,\n ...(params.jsonMode && { response_format: { type: 'json_object' } }),\n });\n\n const choice = response.choices[0];\n\n return {\n content: choice.message.content || '',\n usage: {\n promptTokens: response.usage?.prompt_tokens ?? 0,\n completionTokens: response.usage?.completion_tokens ?? 0,\n totalTokens: response.usage?.total_tokens ?? 0,\n },\n finishReason: choice.finish_reason || 'stop',\n };\n}\n\nfunction stream(params: ChatParams): ReadableStream<Uint8Array> {\n const encoder = new TextEncoder();\n\n return new ReadableStream({\n async start(controller) {\n try {\n const openai = getClient();\n\n const response = await openai.chat.completions.create({\n model: params.model || getDefaultModel(),\n messages: params.messages.map((m) => ({ role: m.role, content: m.content })),\n temperature: params.temperature,\n max_tokens: params.maxTokens,\n stream: true,\n });\n\n for await (const chunk of response) {\n const delta = chunk.choices[0]?.delta?.content;\n if (delta) {\n controller.enqueue(encoder.encode(delta));\n }\n }\n\n controller.close();\n } catch (error) {\n controller.error(error);\n }\n },\n });\n}\n`;\n}\n\nfunction anthropicProvider(): string {\n return `${STAMP}\nimport 'server-only';\n\nimport Anthropic from '@anthropic-ai/sdk';\nimport type { AIProvider, ChatParams, ChatResponse, ChatMessage } from '../types';\n\nlet client: Anthropic | null = null;\n\nfunction getClient(): Anthropic {\n if (client) return client;\n\n const apiKey = process.env.ANTHROPIC_API_KEY;\n if (!apiKey) {\n throw new Error(\n 'ANTHROPIC_API_KEY is not set. Add it to your .env file to use the Anthropic provider.',\n );\n }\n\n client = new Anthropic({ apiKey });\n return client;\n}\n\nfunction getDefaultModel(): string {\n return process.env.ANTHROPIC_MODEL || 'claude-sonnet-4-20250514';\n}\n\nfunction extractSystemMessage(messages: ChatMessage[]): {\n system: string | undefined;\n conversationMessages: ChatMessage[];\n} {\n const systemMessages = messages.filter((m) => m.role === 'system');\n const conversationMessages = messages.filter((m) => m.role !== 'system');\n const system = systemMessages.length > 0\n ? systemMessages.map((m) => m.content).join('\\\\n\\\\n')\n : undefined;\n\n return { system, conversationMessages };\n}\n\nexport function createAnthropicProvider(): AIProvider {\n return { chat, stream };\n}\n\nasync function chat(params: ChatParams): Promise<ChatResponse> {\n const anthropic = getClient();\n const { system, conversationMessages } = extractSystemMessage(params.messages);\n\n const response = await anthropic.messages.create({\n model: params.model || getDefaultModel(),\n max_tokens: params.maxTokens || 4096,\n messages: conversationMessages.map((m) => ({\n role: m.role as 'user' | 'assistant',\n content: m.content,\n })),\n ...(system && { system }),\n ...(params.temperature !== undefined && { temperature: params.temperature }),\n });\n\n const textBlock = response.content.find((block) => block.type === 'text');\n\n return {\n content: textBlock?.text || '',\n usage: {\n promptTokens: response.usage.input_tokens,\n completionTokens: response.usage.output_tokens,\n totalTokens: response.usage.input_tokens + response.usage.output_tokens,\n },\n finishReason: response.stop_reason || 'end_turn',\n };\n}\n\nfunction stream(params: ChatParams): ReadableStream<Uint8Array> {\n const encoder = new TextEncoder();\n\n return new ReadableStream({\n async start(controller) {\n try {\n const anthropic = getClient();\n const { system, conversationMessages } = extractSystemMessage(params.messages);\n\n const response = anthropic.messages.stream({\n model: params.model || getDefaultModel(),\n max_tokens: params.maxTokens || 4096,\n messages: conversationMessages.map((m) => ({\n role: m.role as 'user' | 'assistant',\n content: m.content,\n })),\n ...(system && { system }),\n ...(params.temperature !== undefined && { temperature: params.temperature }),\n });\n\n for await (const event of response) {\n if (\n event.type === 'content_block_delta' &&\n event.delta.type === 'text_delta'\n ) {\n controller.enqueue(encoder.encode(event.delta.text));\n }\n }\n\n controller.close();\n } catch (error) {\n controller.error(error);\n }\n },\n });\n}\n`;\n}\n\nfunction schemas(): string {\n return `${STAMP}\nimport { z } from 'zod';\n\nexport const chatSchema = z.object({\n messages: z.array(\n z.object({\n role: z.enum(['system', 'user', 'assistant']),\n content: z.string().min(1).max(32_000),\n }),\n ).min(1).max(100),\n stream: z.boolean().default(true),\n});\n\nexport type ChatInput = z.infer<typeof chatSchema>;\n`;\n}\n\nfunction useChatHook(): string {\n return `${STAMP}\n'use client';\n\nimport { useState, useCallback, useRef } from 'react';\nimport type { ChatMessage } from '../types';\n\ninterface UseChatOptions {\n apiUrl?: string;\n}\n\ninterface UseChatReturn {\n messages: ChatMessage[];\n isLoading: boolean;\n error: string | null;\n send: (content: string) => Promise<void>;\n reset: () => void;\n}\n\nexport function useChat(options: UseChatOptions = {}): UseChatReturn {\n const { apiUrl = '/api/protected/ai/chat' } = options;\n const [messages, setMessages] = useState<ChatMessage[]>([]);\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const abortRef = useRef<AbortController | null>(null);\n\n const send = useCallback(async (content: string) => {\n setError(null);\n setIsLoading(true);\n\n const userMessage: ChatMessage = { role: 'user', content };\n setMessages((prev) => [...prev, userMessage]);\n\n const assistantMessage: ChatMessage = { role: 'assistant', content: '' };\n setMessages((prev) => [...prev, assistantMessage]);\n\n abortRef.current = new AbortController();\n\n try {\n const response = await fetch(apiUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n messages: [...messages, userMessage],\n stream: true,\n }),\n signal: abortRef.current.signal,\n });\n\n if (!response.ok) {\n const errorBody = await response.json().catch(() => null);\n throw new Error(errorBody?.error || \\`Request failed with status \\${response.status}\\`);\n }\n\n if (!response.body) {\n throw new Error('No response body received');\n }\n\n const reader = response.body.getReader();\n const decoder = new TextDecoder();\n let assembled = '';\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n assembled += decoder.decode(value, { stream: true });\n\n setMessages((prev) => {\n const updated = [...prev];\n updated[updated.length - 1] = { role: 'assistant', content: assembled };\n return updated;\n });\n }\n } catch (err) {\n if (err instanceof DOMException && err.name === 'AbortError') return;\n\n const message = err instanceof Error ? err.message : 'An unexpected error occurred';\n setError(message);\n\n setMessages((prev) => prev.slice(0, -1));\n } finally {\n setIsLoading(false);\n abortRef.current = null;\n }\n }, [apiUrl, messages]);\n\n const reset = useCallback(() => {\n abortRef.current?.abort();\n setMessages([]);\n setError(null);\n setIsLoading(false);\n }, []);\n\n return { messages, isLoading, error, send, reset };\n}\n`;\n}\n\nfunction barrelExports(): string {\n return `${STAMP}\nexport type { ChatMessage, ChatParams, ChatResponse, AIProvider } from './types';\nexport { chatSchema, type ChatInput } from './validation/schemas';\nexport { useChat } from './hooks/use-chat';\n`;\n}\n\nfunction chatRoute(): string {\n return `${STAMP}\nimport { NextResponse } from 'next/server';\nimport { handleApiError, withAuthNoParams } from '@/lib/mars';\nimport { getAIProvider } from '@/features/ai/server';\nimport { checkRateLimit, RATE_LIMITS } from '@mars-stack/core/rate-limit';\nimport { getClientIP } from '@mars-stack/core/rate-limit';\nimport { chatSchema } from '@/features/ai/validation/schemas';\n\nexport const POST = withAuthNoParams(async (request) => {\n try {\n const ip = getClientIP(request) ?? request.session.userId;\n await checkRateLimit(ip, { ...RATE_LIMITS.api, identifier: 'ai-chat' });\n\n const body = await request.json();\n const { messages, stream } = chatSchema.parse(body);\n const provider = await getAIProvider();\n\n if (stream) {\n const readableStream = provider.stream({ messages });\n return new NextResponse(readableStream, {\n headers: {\n 'Content-Type': 'text/plain; charset=utf-8',\n 'Transfer-Encoding': 'chunked',\n 'Cache-Control': 'no-cache',\n },\n });\n }\n\n const response = await provider.chat({ messages });\n return NextResponse.json(response);\n } catch (error) {\n return handleApiError(error, { endpoint: '/api/protected/ai/chat' });\n }\n});\n`;\n}\n","import fs from 'fs-extra';\nimport path from 'node:path';\nimport { log } from '../../utils/logger.js';\nimport { createRollbackContext } from '../../utils/rollback.js';\n\nconst GENERATOR_VERSION = '0.1.0';\nconst STAMP = `// @mars-generated cookie-consent@${GENERATOR_VERSION}`;\n\nexport async function generateCookieConsent(projectRoot: string): Promise<void> {\n const featureDir = path.join(projectRoot, 'src', 'features', 'cookie-consent');\n\n if (await fs.pathExists(featureDir)) {\n log.error('Cookie consent feature already exists at src/features/cookie-consent/');\n return;\n }\n\n const ctx = createRollbackContext();\n\n try {\n const files: Record<string, string> = {\n 'src/features/cookie-consent/types.ts': types(),\n 'src/features/cookie-consent/hooks/use-consent.ts': useConsent(),\n 'src/features/cookie-consent/components/CookieConsentBanner.tsx': cookieConsentBanner(),\n 'src/features/cookie-consent/components/CookiePreferencesDialog.tsx': cookiePreferencesDialog(),\n 'src/features/cookie-consent/components/index.ts': componentsIndex(),\n 'src/features/cookie-consent/index.ts': featureIndex(),\n };\n\n let count = 0;\n for (const [filePath, content] of Object.entries(files)) {\n const fullPath = path.join(projectRoot, filePath);\n ctx.trackCreatedFile(fullPath);\n await fs.ensureDir(path.dirname(fullPath));\n await fs.writeFile(fullPath, content);\n count++;\n }\n\n await setConfigFlag(projectRoot, ctx);\n await ctx.commit();\n\n log.success(`Generated cookie consent feature with ${count} files`);\n log.blank();\n log.step('src/features/cookie-consent/types.ts — ConsentStatus, ConsentPreferences');\n log.step('src/features/cookie-consent/hooks/use-consent.ts — useConsent hook');\n log.step('src/features/cookie-consent/components/CookieConsentBanner.tsx — banner');\n log.step('src/features/cookie-consent/components/CookiePreferencesDialog.tsx — preferences modal');\n log.blank();\n log.warn('Complete setup:');\n log.step('Add <CookieConsentBanner /> to your root layout');\n log.step('Optionally add <CookiePreferencesDialog /> for granular consent management');\n log.step('Check consent status with useConsent() before loading tracking scripts');\n log.blank();\n } catch (error) {\n await ctx.rollback();\n throw error;\n }\n}\n\nasync function setConfigFlag(projectRoot: string, ctx: { trackModifiedFile: (p: string) => Promise<void> }): Promise<void> {\n const configPath = path.join(projectRoot, 'src', 'config', 'app.config.ts');\n if (!(await fs.pathExists(configPath))) return;\n\n await ctx.trackModifiedFile(configPath);\n const content = await fs.readFile(configPath, 'utf-8');\n const updated = content.replace(/cookieConsent:\\s*false/, 'cookieConsent: true');\n await fs.writeFile(configPath, updated);\n}\n\nfunction types(): string {\n return `${STAMP}\n\nexport type ConsentStatus = 'granted' | 'denied' | 'pending';\n\nexport interface ConsentPreferences {\n analytics: boolean;\n marketing: boolean;\n functional: boolean;\n}\n`;\n}\n\nfunction useConsent(): string {\n return `${STAMP}\n'use client';\n\nimport { useCallback, useEffect, useState } from 'react';\nimport type { ConsentPreferences, ConsentStatus } from '../types';\n\nconst STORAGE_KEY = 'mars-cookie-consent';\n\nconst DEFAULT_PREFERENCES: ConsentPreferences = {\n analytics: false,\n marketing: false,\n functional: false,\n};\n\nconst ALL_GRANTED: ConsentPreferences = {\n analytics: true,\n marketing: true,\n functional: true,\n};\n\ninterface StoredConsent {\n status: ConsentStatus;\n preferences: ConsentPreferences;\n}\n\nfunction readStored(): StoredConsent | null {\n if (typeof window === 'undefined') return null;\n try {\n const raw = localStorage.getItem(STORAGE_KEY);\n if (!raw) return null;\n const parsed = JSON.parse(raw) as StoredConsent;\n if (\n parsed &&\n typeof parsed.status === 'string' &&\n parsed.status !== 'pending' &&\n parsed.preferences &&\n typeof parsed.preferences.analytics === 'boolean' &&\n typeof parsed.preferences.marketing === 'boolean' &&\n typeof parsed.preferences.functional === 'boolean'\n ) {\n return parsed;\n }\n } catch {\n // ignore\n }\n return null;\n}\n\nfunction writeStored(data: StoredConsent): void {\n if (typeof window === 'undefined') return;\n try {\n localStorage.setItem(STORAGE_KEY, JSON.stringify(data));\n } catch {\n // ignore\n }\n}\n\nexport function useConsent() {\n const [status, setStatus] = useState<ConsentStatus>('pending');\n const [preferences, setPreferencesState] = useState<ConsentPreferences>(DEFAULT_PREFERENCES);\n const [mounted, setMounted] = useState(false);\n\n useEffect(() => {\n const stored = readStored();\n if (stored) {\n setStatus(stored.status);\n setPreferencesState(stored.preferences);\n }\n setMounted(true);\n }, []);\n\n const accept = useCallback(() => {\n const data: StoredConsent = { status: 'granted', preferences: ALL_GRANTED };\n writeStored(data);\n setStatus('granted');\n setPreferencesState(ALL_GRANTED);\n }, []);\n\n const decline = useCallback(() => {\n const data: StoredConsent = { status: 'denied', preferences: DEFAULT_PREFERENCES };\n writeStored(data);\n setStatus('denied');\n setPreferencesState(DEFAULT_PREFERENCES);\n }, []);\n\n const updatePreferences = useCallback((next: Partial<ConsentPreferences>) => {\n const merged: ConsentPreferences = { ...DEFAULT_PREFERENCES, ...next };\n const data: StoredConsent = { status: 'granted', preferences: merged };\n writeStored(data);\n setStatus('granted');\n setPreferencesState(merged);\n }, []);\n\n return { status, preferences, mounted, accept, decline, updatePreferences };\n}\n`;\n}\n\nfunction cookieConsentBanner(): string {\n return `${STAMP}\n'use client';\n\nimport { useConsent } from '../hooks/use-consent';\nimport { Button } from '@mars-stack/ui';\n\nexport function CookieConsentBanner() {\n const { status, mounted, accept, decline } = useConsent();\n\n if (!mounted || status !== 'pending') return null;\n\n return (\n <div\n role=\"dialog\"\n aria-labelledby=\"cookie-consent-title\"\n aria-describedby=\"cookie-consent-description\"\n className=\"fixed bottom-0 left-0 right-0 z-50 border-t border-border-default bg-surface-card p-4 shadow-lg sm:p-6\"\n >\n <div className=\"mx-auto flex max-w-4xl flex-col gap-4 sm:flex-row sm:items-center sm:justify-between\">\n <div className=\"flex-1\">\n <h2 id=\"cookie-consent-title\" className=\"text-base font-semibold text-text-primary\">\n Cookie usage\n </h2>\n <p id=\"cookie-consent-description\" className=\"mt-1 text-sm text-text-secondary\">\n We use cookies to improve your experience, analyze traffic, and personalize content. You can accept all or\n decline optional cookies.\n </p>\n </div>\n <div className=\"flex shrink-0 flex-col gap-2 sm:flex-row sm:items-center\">\n <Button variant=\"secondary\" size=\"sm\" onClick={decline}>\n Decline\n </Button>\n <Button variant=\"primary\" size=\"sm\" onClick={accept}>\n Accept\n </Button>\n </div>\n </div>\n </div>\n );\n}\n`;\n}\n\nfunction cookiePreferencesDialog(): string {\n return `${STAMP}\n'use client';\n\nimport { useState, useEffect } from 'react';\nimport { Modal, Button } from '@mars-stack/ui';\nimport type { ConsentPreferences } from '../types';\n\ninterface CookiePreferencesDialogProps {\n open: boolean;\n onClose: () => void;\n currentPreferences: ConsentPreferences;\n onSave: (preferences: ConsentPreferences) => void;\n}\n\nfunction PreferenceRow({\n label,\n description,\n checked,\n onChange,\n}: {\n label: string;\n description: string;\n checked: boolean;\n onChange: (checked: boolean) => void;\n}) {\n return (\n <div className=\"flex items-start justify-between gap-4 py-3\">\n <div>\n <p className=\"text-sm font-medium text-text-primary\">{label}</p>\n <p className=\"mt-0.5 text-xs text-text-secondary\">{description}</p>\n </div>\n <label className=\"relative inline-flex shrink-0 cursor-pointer items-center\">\n <input\n type=\"checkbox\"\n checked={checked}\n onChange={(e) => onChange(e.target.checked)}\n className=\"peer sr-only\"\n role=\"switch\"\n />\n <div className=\"h-6 w-11 rounded-full bg-surface-secondary transition-colors peer-checked:bg-brand-primary\" />\n <div className=\"absolute left-1 top-1 h-4 w-4 rounded-full bg-surface-primary shadow-sm transition-transform peer-checked:translate-x-5\" />\n </label>\n </div>\n );\n}\n\nexport function CookiePreferencesDialog({ open, onClose, currentPreferences, onSave }: CookiePreferencesDialogProps) {\n const [preferences, setPreferences] = useState<ConsentPreferences>(currentPreferences);\n\n useEffect(() => {\n if (open) {\n setPreferences(currentPreferences);\n }\n }, [open, currentPreferences]);\n\n const handleSave = () => {\n onSave(preferences);\n onClose();\n };\n\n return (\n <Modal open={open} onClose={onClose} title=\"Cookie preferences\">\n <div className=\"space-y-1\">\n <p className=\"text-sm text-text-secondary\">\n Choose which categories of cookies you want to allow.\n </p>\n <div className=\"mt-4 divide-y divide-border-default\">\n <PreferenceRow\n label=\"Functional\"\n description=\"Essential for the site to work\"\n checked={preferences.functional}\n onChange={(v) => setPreferences((p) => ({ ...p, functional: v }))}\n />\n <PreferenceRow\n label=\"Analytics\"\n description=\"Help us understand how visitors use the site\"\n checked={preferences.analytics}\n onChange={(v) => setPreferences((p) => ({ ...p, analytics: v }))}\n />\n <PreferenceRow\n label=\"Marketing\"\n description=\"Used for personalized ads and campaigns\"\n checked={preferences.marketing}\n onChange={(v) => setPreferences((p) => ({ ...p, marketing: v }))}\n />\n </div>\n <div className=\"mt-6 flex justify-end gap-2\">\n <Button variant=\"subtle\" size=\"sm\" onClick={onClose}>\n Cancel\n </Button>\n <Button variant=\"primary\" size=\"sm\" onClick={handleSave}>\n Save\n </Button>\n </div>\n </div>\n </Modal>\n );\n}\n`;\n}\n\nfunction componentsIndex(): string {\n return `${STAMP}\nexport { CookieConsentBanner } from './CookieConsentBanner';\nexport { CookiePreferencesDialog } from './CookiePreferencesDialog';\n`;\n}\n\nfunction featureIndex(): string {\n return `${STAMP}\nexport type { ConsentStatus, ConsentPreferences } from './types';\nexport { useConsent } from './hooks/use-consent';\nexport { CookieConsentBanner, CookiePreferencesDialog } from './components';\n`;\n}\n","import fs from 'fs-extra';\nimport path from 'node:path';\nimport { log } from '../../utils/logger.js';\nimport { createRollbackContext } from '../../utils/rollback.js';\n\nconst GENERATOR_VERSION = '0.1.0';\nconst STAMP = `// @mars-generated coming-soon@${GENERATOR_VERSION}`;\n\nexport async function generateComingSoon(projectRoot: string): Promise<void> {\n const featureDir = path.join(projectRoot, 'src', 'features', 'coming-soon');\n\n if (await fs.pathExists(featureDir)) {\n log.error('Coming soon feature already exists at src/features/coming-soon/');\n return;\n }\n\n const ctx = createRollbackContext();\n\n try {\n const files: Record<string, string> = {\n 'src/features/coming-soon/types.ts': types(),\n 'src/features/coming-soon/validation/schemas.ts': schemas(),\n 'src/features/coming-soon/components/ComingSoonPage.tsx': comingSoonPage(),\n 'src/features/coming-soon/components/index.ts': componentIndex(),\n 'src/features/coming-soon/index.ts': barrelExports(),\n 'src/app/coming-soon/page.tsx': pageRoute(),\n 'src/app/api/waitlist/route.ts': waitlistRoute(),\n };\n\n let count = 0;\n for (const [filePath, content] of Object.entries(files)) {\n const fullPath = path.join(projectRoot, filePath);\n ctx.trackCreatedFile(fullPath);\n await fs.ensureDir(path.dirname(fullPath));\n await fs.writeFile(fullPath, content);\n count++;\n }\n\n await setConfigFlag(projectRoot, ctx);\n await ctx.commit();\n\n log.success(`Generated coming soon feature with ${count} files`);\n log.blank();\n log.step('src/features/coming-soon/ — types, validation, components');\n log.step('src/app/coming-soon/ — landing page');\n log.step('src/app/api/waitlist/ — waitlist signup endpoint');\n log.blank();\n log.step('Visit /coming-soon to see the page');\n log.step('Wire up the waitlist API to your preferred email service');\n log.step('To use as the default landing page, update your middleware or root redirect');\n log.blank();\n } catch (error) {\n await ctx.rollback();\n throw error;\n }\n}\n\nasync function setConfigFlag(\n projectRoot: string,\n ctx: { trackModifiedFile: (p: string) => Promise<void> },\n): Promise<void> {\n const configPath = path.join(projectRoot, 'src', 'config', 'app.config.ts');\n if (!(await fs.pathExists(configPath))) return;\n\n await ctx.trackModifiedFile(configPath);\n const content = await fs.readFile(configPath, 'utf-8');\n const updated = content.replace(/comingSoon:\\s*false/, 'comingSoon: true');\n await fs.writeFile(configPath, updated);\n}\n\nfunction types(): string {\n return `${STAMP}\n\nexport interface WaitlistEntry {\n email: string;\n createdAt: Date;\n}\n`;\n}\n\nfunction schemas(): string {\n return `${STAMP}\nimport { z } from 'zod';\n\nexport const waitlistSchema = z.object({\n email: z.string().email('Please enter a valid email address'),\n});\n`;\n}\n\nfunction comingSoonPage(): string {\n return `${STAMP}\n'use client';\n\nimport { useState } from 'react';\nimport { appConfig } from '@/config/app.config';\n\nexport function ComingSoonPage() {\n const [email, setEmail] = useState('');\n const [submitted, setSubmitted] = useState(false);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n async function handleSubmit(e: React.FormEvent<HTMLFormElement>) {\n e.preventDefault();\n setError(null);\n setLoading(true);\n\n try {\n const res = await fetch('/api/waitlist', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ email }),\n });\n\n const data = await res.json();\n\n if (!res.ok) {\n setError(data.error ?? 'Something went wrong');\n setLoading(false);\n return;\n }\n\n setSubmitted(true);\n setEmail('');\n } catch {\n setError('Failed to join the waitlist');\n } finally {\n setLoading(false);\n }\n }\n\n return (\n <div className=\"relative min-h-screen bg-surface-background bg-gradient-to-br from-surface-background via-surface-card/30 to-surface-background\">\n <div className=\"flex min-h-screen flex-col items-center justify-center px-4 py-16 sm:px-6 lg:px-8\">\n <div className=\"mx-auto max-w-2xl text-center\">\n <h1 className=\"text-5xl font-bold tracking-tight text-text-primary sm:text-6xl md:text-7xl\">\n {appConfig.name}\n </h1>\n <h2 className=\"mt-6 text-3xl font-semibold text-text-primary sm:text-4xl\">\n Coming Soon\n </h2>\n <p className=\"mt-4 text-lg text-text-secondary sm:text-xl\">\n {appConfig.tagline || appConfig.description}\n </p>\n\n <div className=\"mt-12\">\n {submitted ? (\n <p className=\"rounded-xl border border-border-default bg-surface-card px-6 py-4 text-text-primary\">\n Thanks for joining! We&apos;ll notify you when we launch.\n </p>\n ) : (\n <form onSubmit={handleSubmit} className=\"flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-center\">\n <input\n type=\"email\"\n value={email}\n onChange={(e) => setEmail(e.target.value)}\n placeholder=\"Enter your email\"\n required\n className=\"w-full rounded-lg border border-border-default bg-surface-card px-4 py-3 text-text-primary placeholder:text-text-muted focus:border-brand-primary focus:outline-none focus:ring-2 focus:ring-brand-primary/20 sm:w-72\"\n disabled={loading}\n />\n <button\n type=\"submit\"\n disabled={loading}\n className=\"shrink-0 rounded-lg bg-brand-primary px-6 py-3 font-medium text-text-on-brand transition-colors hover:opacity-90 disabled:opacity-50\"\n >\n {loading ? 'Joining…' : 'Join waitlist'}\n </button>\n </form>\n )}\n {error && (\n <p className=\"mt-3 text-sm text-text-error\" role=\"alert\">\n {error}\n </p>\n )}\n </div>\n </div>\n </div>\n </div>\n );\n}\n`;\n}\n\nfunction componentIndex(): string {\n return `${STAMP}\nexport { ComingSoonPage } from './ComingSoonPage';\n`;\n}\n\nfunction barrelExports(): string {\n return `${STAMP}\nexport { ComingSoonPage } from './components';\nexport type { WaitlistEntry } from './types';\n`;\n}\n\nfunction pageRoute(): string {\n return `${STAMP}\nimport type { Metadata } from 'next';\nimport { ComingSoonPage } from '@/features/coming-soon';\n\nexport const metadata: Metadata = {\n title: 'Coming Soon',\n};\n\nexport default function ComingSoonRoute() {\n return <ComingSoonPage />;\n}\n`;\n}\n\nfunction waitlistRoute(): string {\n return `${STAMP}\nimport { NextResponse } from 'next/server';\nimport { waitlistSchema } from '@/features/coming-soon/validation/schemas';\n\nexport async function POST(request: Request) {\n try {\n const body = await request.json();\n const parsed = waitlistSchema.safeParse(body);\n\n if (!parsed.success) {\n return NextResponse.json(\n { error: parsed.error.issues[0]?.message ?? 'Invalid input' },\n { status: 400 },\n );\n }\n\n const { email } = parsed.data;\n\n // Stub: log to console (local-first). Wire up to your email service for production.\n console.log('[waitlist] New signup:', email);\n\n return NextResponse.json({ success: true });\n } catch {\n return NextResponse.json(\n { error: 'Invalid request body' },\n { status: 400 },\n );\n }\n}\n`;\n}\n","import fs from 'fs-extra';\nimport path from 'node:path';\nimport { log } from '../../utils/logger.js';\nimport { createRollbackContext } from '../../utils/rollback.js';\nimport { addDependencies } from '../../utils/dependencies.js';\n\nconst GENERATOR_VERSION = '0.1.0';\nconst STAMP = `// @mars-generated sentry@${GENERATOR_VERSION}`;\n\nexport async function generateSentry(projectRoot: string): Promise<void> {\n const featureDir = path.join(projectRoot, 'src', 'features', 'sentry');\n\n if (await fs.pathExists(featureDir)) {\n log.error('Sentry feature already exists at src/features/sentry/');\n return;\n }\n\n const ctx = createRollbackContext();\n\n try {\n const files: Record<string, string> = {\n 'src/features/sentry/types.ts': types(),\n 'src/features/sentry/client-init.ts': clientInit(),\n 'src/features/sentry/server-init.ts': serverInit(),\n 'src/features/sentry/components/ErrorBoundary.tsx': errorBoundary(),\n 'src/features/sentry/components/index.ts': componentsIndex(),\n 'src/features/sentry/index.ts': barrelExports(),\n };\n\n let count = 0;\n for (const [filePath, content] of Object.entries(files)) {\n const fullPath = path.join(projectRoot, filePath);\n ctx.trackCreatedFile(fullPath);\n await fs.ensureDir(path.dirname(fullPath));\n await fs.writeFile(fullPath, content);\n count++;\n }\n\n await addDependencies(projectRoot, { '@sentry/nextjs': '^8.0.0' });\n await setConfigFlag(projectRoot, ctx);\n await ctx.commit();\n\n log.success(`Generated sentry feature with ${count} files`);\n log.blank();\n log.step('src/features/sentry/ — types, client-init, server-init, ErrorBoundary');\n log.blank();\n log.warn('Optional: run npx @sentry/wizard@latest -i nextjs for full setup');\n log.blank();\n log.warn('Next steps:');\n log.step('Set NEXT_PUBLIC_SENTRY_DSN and SENTRY_DSN environment variables');\n log.step('Wrap pages or layouts with <ErrorBoundary> for graceful error handling');\n log.step('Import client-init and server-init in your instrumentation files');\n log.blank();\n } catch (error) {\n await ctx.rollback();\n throw error;\n }\n}\n\nasync function setConfigFlag(projectRoot: string, ctx: { trackModifiedFile: (p: string) => Promise<void> }): Promise<void> {\n const configPath = path.join(projectRoot, 'src', 'config', 'app.config.ts');\n if (!(await fs.pathExists(configPath))) return;\n\n await ctx.trackModifiedFile(configPath);\n const content = await fs.readFile(configPath, 'utf-8');\n const updated = content.replace(/sentry:\\s*false/, 'sentry: true');\n await fs.writeFile(configPath, updated);\n}\n\nfunction types(): string {\n return `${STAMP}\n\nexport interface SentryConfig {\n dsn: string;\n environment: string;\n tracesSampleRate: number;\n enabled: boolean;\n}\n`;\n}\n\nfunction clientInit(): string {\n return `${STAMP}\nimport * as Sentry from '@sentry/nextjs';\n\nconst dsn = process.env.NEXT_PUBLIC_SENTRY_DSN;\n\nif (dsn) {\n Sentry.init({\n dsn,\n environment: process.env.NODE_ENV ?? 'development',\n tracesSampleRate: process.env.NODE_ENV === 'development' ? 1.0 : 0.1,\n enabled: !!dsn,\n });\n}\n`;\n}\n\nfunction serverInit(): string {\n return `${STAMP}\nimport 'server-only';\nimport * as Sentry from '@sentry/nextjs';\n\nconst dsn = process.env.SENTRY_DSN;\n\nif (dsn) {\n Sentry.init({\n dsn,\n environment: process.env.NODE_ENV ?? 'development',\n tracesSampleRate: process.env.NODE_ENV === 'development' ? 1.0 : 0.1,\n enabled: !!dsn,\n });\n}\n`;\n}\n\nfunction errorBoundary(): string {\n return `${STAMP}\n'use client';\n\nimport { Component, type ErrorInfo, type ReactNode } from 'react';\nimport * as Sentry from '@sentry/nextjs';\n\ninterface ErrorBoundaryProps {\n children: ReactNode;\n fallback?: ReactNode | ((error: Error, reset: () => void) => ReactNode);\n}\n\ninterface ErrorBoundaryState {\n hasError: boolean;\n error: Error | null;\n}\n\nexport class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {\n constructor(props: ErrorBoundaryProps) {\n super(props);\n this.state = { hasError: false, error: null };\n }\n\n static getDerivedStateFromError(error: Error): ErrorBoundaryState {\n return { hasError: true, error };\n }\n\n componentDidCatch(error: Error, errorInfo: ErrorInfo): void {\n Sentry.captureException(error, { extra: { componentStack: errorInfo.componentStack } });\n }\n\n reset = (): void => {\n this.setState({ hasError: false, error: null });\n };\n\n render(): ReactNode {\n if (this.state.hasError && this.state.error) {\n if (typeof this.props.fallback === 'function') {\n return this.props.fallback(this.state.error, this.reset);\n }\n if (this.props.fallback) {\n return this.props.fallback;\n }\n return <DefaultErrorFallback error={this.state.error} reset={this.reset} />;\n }\n return this.props.children;\n }\n}\n\nfunction DefaultErrorFallback({ error, reset }: { error: Error; reset: () => void }) {\n return (\n <div className=\"flex min-h-[300px] flex-col items-center justify-center gap-4 p-6\">\n <div className=\"rounded-xl border border-border-default bg-surface-card p-6 text-center\">\n <h2 className=\"mb-2 text-lg font-semibold text-text-primary\">Something went wrong</h2>\n <p className=\"mb-4 text-sm text-text-secondary\">\n {error.message || 'An unexpected error occurred.'}\n </p>\n <button\n type=\"button\"\n onClick={reset}\n className=\"rounded-lg bg-brand-primary px-4 py-2 text-sm font-medium text-text-inverse transition-colors hover:bg-brand-primary-hover focus:outline-none focus:ring-2 focus:ring-brand-primary focus:ring-offset-2\"\n >\n Try Again\n </button>\n </div>\n </div>\n );\n}\n`;\n}\n\nfunction componentsIndex(): string {\n return `${STAMP}\nexport { ErrorBoundary } from './ErrorBoundary';\n`;\n}\n\nfunction barrelExports(): string {\n return `${STAMP}\n\nexport type { SentryConfig } from './types';\nexport { ErrorBoundary } from './components';\n`;\n}\n","import fs from 'fs-extra';\nimport path from 'node:path';\nimport { log } from '../../utils/logger.js';\nimport { createRollbackContext } from '../../utils/rollback.js';\n\nconst GENERATOR_VERSION = '0.1.0';\nconst STAMP = `// @mars-generated feature-flags@${GENERATOR_VERSION}`;\n\nexport async function generateFeatureFlags(projectRoot: string): Promise<void> {\n const featureDir = path.join(projectRoot, 'src', 'features', 'feature-flags');\n\n if (await fs.pathExists(featureDir)) {\n log.error('Feature flags feature already exists at src/features/feature-flags/');\n return;\n }\n\n const ctx = createRollbackContext();\n\n try {\n const files: Record<string, string> = {\n 'src/features/feature-flags/types.ts': types(),\n 'src/features/feature-flags/server/local-provider.ts': localProvider(),\n 'src/features/feature-flags/server/index.ts': serverIndex(),\n 'src/features/feature-flags/hooks/use-feature-flag.ts': useFeatureFlag(),\n 'src/features/feature-flags/components/FeatureGate.tsx': featureGate(),\n 'src/features/feature-flags/components/index.ts': componentsIndex(),\n 'src/features/feature-flags/index.ts': featureIndex(),\n 'src/config/feature-flags.json': featureFlagsJson(),\n 'src/app/api/protected/feature-flags/route.ts': apiRoute(),\n };\n\n let count = 0;\n for (const [filePath, content] of Object.entries(files)) {\n const fullPath = path.join(projectRoot, filePath);\n ctx.trackCreatedFile(fullPath);\n await fs.ensureDir(path.dirname(fullPath));\n await fs.writeFile(fullPath, content);\n count++;\n }\n\n await setConfigFlag(projectRoot, ctx);\n await ctx.commit();\n\n log.success(`Generated feature flags feature with ${count} files`);\n log.blank();\n log.step('Feature flags use a local JSON provider by default');\n log.step('Edit src/config/feature-flags.json to define flags');\n log.step('Use getFlag(\\'my-flag\\', false) in server code');\n log.step('Use useFeatureFlag(\\'my-flag\\', false) in client code');\n log.step('Use <FeatureGate flag=\"my-flag\"> for conditional rendering');\n log.step('For LaunchDarkly/PostHog, install their SDK and update the provider');\n log.blank();\n } catch (error) {\n await ctx.rollback();\n throw error;\n }\n}\n\nasync function setConfigFlag(projectRoot: string, ctx: { trackModifiedFile: (p: string) => Promise<void> }): Promise<void> {\n const configPath = path.join(projectRoot, 'src', 'config', 'app.config.ts');\n if (!(await fs.pathExists(configPath))) return;\n\n await ctx.trackModifiedFile(configPath);\n const content = await fs.readFile(configPath, 'utf-8');\n const updated = content.replace(/featureFlags:\\s*false/, 'featureFlags: true');\n await fs.writeFile(configPath, updated);\n}\n\nfunction types(): string {\n return `${STAMP}\n\nexport type FeatureFlagProvider = 'local' | 'launchdarkly' | 'posthog';\n\nexport type FeatureFlagValue = boolean | string | number;\n\nexport interface FeatureFlagContext {\n userId?: string;\n email?: string;\n custom?: Record<string, string | number | boolean>;\n}\n`;\n}\n\nfunction localProvider(): string {\n return `${STAMP}\nimport 'server-only';\n\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport type { FeatureFlagValue } from '../types';\n\nconst CONFIG_PATH = path.join(process.cwd(), 'src', 'config', 'feature-flags.json');\n\ninterface FlagsConfig {\n flags: Record<string, FeatureFlagValue>;\n}\n\nfunction loadFlags(): Record<string, FeatureFlagValue> {\n try {\n if (fs.existsSync(CONFIG_PATH)) {\n const raw = fs.readFileSync(CONFIG_PATH, 'utf-8');\n const parsed: FlagsConfig = JSON.parse(raw);\n return parsed.flags ?? {};\n }\n } catch {\n // Fallback to empty config\n }\n return {};\n}\n\nexport function getLocalFlag(flagKey: string, defaultValue: FeatureFlagValue): FeatureFlagValue {\n const flags = loadFlags();\n return flagKey in flags ? flags[flagKey] : defaultValue;\n}\n`;\n}\n\nfunction serverIndex(): string {\n return `${STAMP}\nimport 'server-only';\n\nimport type { FeatureFlagValue, FeatureFlagContext } from '../types';\nimport { getLocalFlag } from './local-provider';\n\nexport interface FlagProvider {\n getFlag(key: string, defaultValue: FeatureFlagValue, context?: FeatureFlagContext): FeatureFlagValue;\n}\n\nfunction getLocalProvider(): FlagProvider {\n return {\n getFlag(key, defaultValue) {\n return getLocalFlag(key, defaultValue);\n },\n };\n}\n\nlet cachedProvider: FlagProvider | null = null;\n\nfunction getProvider(): FlagProvider {\n if (!cachedProvider) {\n cachedProvider = getLocalProvider();\n }\n return cachedProvider;\n}\n\nexport function getFlag(\n flagKey: string,\n defaultValue: FeatureFlagValue,\n context?: FeatureFlagContext,\n): FeatureFlagValue {\n const provider = getProvider();\n return provider.getFlag(flagKey, defaultValue, context);\n}\n`;\n}\n\nfunction useFeatureFlag(): string {\n return `${STAMP}\n'use client';\n\nimport { useState, useEffect } from 'react';\nimport type { FeatureFlagValue } from '../types';\n\nconst cache = new Map<string, FeatureFlagValue>();\n\nasync function fetchFlag(flagKey: string): Promise<FeatureFlagValue> {\n const cached = cache.get(flagKey);\n if (cached !== undefined) {\n return cached;\n }\n\n const res = await fetch(\\`/api/protected/feature-flags?key=\\${encodeURIComponent(flagKey)}\\`);\n if (!res.ok) {\n throw new Error(\\`Failed to fetch flag \\${flagKey}\\`);\n }\n const json = await res.json();\n const value = json.value as FeatureFlagValue;\n cache.set(flagKey, value);\n return value;\n}\n\nexport function useFeatureFlag(flagKey: string, defaultValue: FeatureFlagValue): FeatureFlagValue | undefined {\n const [value, setValue] = useState<FeatureFlagValue | undefined>(() => cache.get(flagKey) ?? undefined);\n const [isLoading, setIsLoading] = useState(() => !cache.has(flagKey));\n\n useEffect(() => {\n let cancelled = false;\n\n if (cache.has(flagKey)) {\n setValue(cache.get(flagKey));\n setIsLoading(false);\n return;\n }\n\n fetchFlag(flagKey).then((v) => {\n if (!cancelled) {\n setValue(v);\n setIsLoading(false);\n }\n }).catch(() => {\n if (!cancelled) {\n setValue(defaultValue);\n setIsLoading(false);\n }\n });\n\n return () => {\n cancelled = true;\n };\n }, [flagKey, defaultValue]);\n\n return isLoading ? undefined : (value ?? defaultValue);\n}\n`;\n}\n\nfunction featureGate(): string {\n return `${STAMP}\n'use client';\n\nimport { useFeatureFlag } from '../hooks/use-feature-flag';\n\ninterface FeatureGateProps {\n flag: string;\n fallback?: React.ReactNode;\n children: React.ReactNode;\n defaultValue?: boolean;\n}\n\nexport function FeatureGate({ flag, fallback = null, children, defaultValue = false }: FeatureGateProps) {\n const value = useFeatureFlag(flag, defaultValue);\n\n if (value === undefined) {\n return null;\n }\n\n const enabled = value === true || (typeof value === 'string' && value.toLowerCase() === 'true') || (typeof value === 'number' && value !== 0);\n\n return enabled ? <>{children}</> : <>{fallback}</>;\n}\n`;\n}\n\nfunction componentsIndex(): string {\n return `${STAMP}\nexport { FeatureGate } from './FeatureGate';\n`;\n}\n\nfunction featureIndex(): string {\n return `${STAMP}\nexport { getFlag } from './server';\nexport { useFeatureFlag } from './hooks/use-feature-flag';\nexport { FeatureGate } from './components';\nexport type { FeatureFlagProvider, FeatureFlagValue, FeatureFlagContext } from './types';\n`;\n}\n\nfunction featureFlagsJson(): string {\n return `{\n \"flags\": {}\n}\n`;\n}\n\nfunction apiRoute(): string {\n return `${STAMP}\nimport { NextRequest, NextResponse } from 'next/server';\nimport { z } from 'zod';\nimport { withAuthNoParams, handleApiError } from '@/lib/mars';\nimport { getFlag } from '@/features/feature-flags/server';\n\nconst querySchema = z.object({\n key: z.string().min(1, 'Flag key is required'),\n});\n\nexport const GET = withAuthNoParams(async (request) => {\n try {\n const url = new URL(request.url);\n const parsed = querySchema.safeParse({ key: url.searchParams.get('key') });\n\n if (!parsed.success) {\n return NextResponse.json(\n { error: 'Invalid parameters', details: parsed.error.flatten().fieldErrors },\n { status: 400 },\n );\n }\n\n const { key } = parsed.data;\n const value = getFlag(key, false);\n\n return NextResponse.json({ value });\n } catch (error) {\n return handleApiError(error, { endpoint: '/api/protected/feature-flags' });\n }\n});\n`;\n}\n","import { Command } from 'commander';\nimport { createCommand } from './commands/create.js';\nimport { doctorCommand } from './commands/doctor.js';\nimport { addFeatureCommand, addPageCommand, addModelCommand, addComponentCommand, addEmailCommand } from './commands/add.js';\nimport { configureCommand } from './commands/configure.js';\nimport { deployCommand } from './commands/deploy.js';\nimport { upgradeCommand } from './commands/upgrade.js';\nimport { generateBlog } from './generators/features/blog.js';\nimport { generateDarkMode } from './generators/features/dark-mode.js';\nimport { generateNotifications } from './generators/features/notifications.js';\nimport { generateAnalytics } from './generators/features/analytics.js';\nimport { generateCommandPalette } from './generators/features/command-palette.js';\nimport { generateOnboarding } from './generators/features/onboarding.js';\nimport { generateSearch } from './generators/features/search.js';\nimport { generateRealtime } from './generators/features/realtime.js';\nimport { generateAI } from './generators/features/ai.js';\nimport { generateCookieConsent } from './generators/features/cookie-consent.js';\nimport { generateComingSoon } from './generators/features/coming-soon.js';\nimport { generateSentry } from './generators/features/sentry.js';\nimport { generateFeatureFlags } from './generators/features/feature-flags.js';\nimport { enableTelemetry, disableTelemetry } from './utils/telemetry.js';\nimport { log } from './utils/logger.js';\n\nconst program = new Command();\n\nprogram\n .name('mars')\n .description('MARS CLI: scaffold, configure, and maintain SaaS apps')\n .version('0.1.0')\n .option('-v, --verbose', 'Enable verbose output for debugging');\n\nexport function isVerbose(): boolean {\n return program.opts().verbose === true;\n}\n\nprogram\n .command('create')\n .description('Create a new MARS project')\n .argument('[name]', 'Project name (kebab-case)')\n .option('--defaults', 'Skip prompts, use default configuration')\n .action(async (name?: string, options?: { defaults?: boolean }) => {\n await createCommand(name, options);\n });\n\nconst add = program\n .command('add')\n .description('Add a feature, page, model, component, or email template to your project');\n\nadd\n .command('feature')\n .description('Scaffold a new feature module')\n .argument('<name>', 'Feature name (e.g., billing, blog, notifications)')\n .action(async (name: string) => {\n await addFeatureCommand(name);\n });\n\nadd\n .command('page')\n .description('Create a new page')\n .argument('<path>', 'Route path (e.g., pricing, blog/[slug])')\n .option('-p, --protected', 'Create in (protected) route group', false)\n .action(async (routePath: string, options: { protected?: boolean }) => {\n await addPageCommand(routePath, options);\n });\n\nadd\n .command('model')\n .description('Create a new Prisma model')\n .argument('<name>', 'Model name in PascalCase (e.g., Product, Invoice)')\n .action(async (name: string) => {\n await addModelCommand(name);\n });\n\nadd\n .command('component')\n .description('Create a new UI component')\n .argument('<name>', 'Component name in PascalCase (e.g., Toggle, DataGrid)')\n .option('-t, --type <type>', 'Component type: primitive or pattern', 'primitive')\n .action(async (name: string, options: { type?: string }) => {\n await addComponentCommand(name, options);\n });\n\nadd\n .command('email')\n .description('Create a new email template')\n .argument('<name>', 'Template name in kebab-case (e.g., invoice, team-invite)')\n .action(async (name: string) => {\n await addEmailCommand(name);\n });\n\nconst generate = program\n .command('generate')\n .description('Generate a feature with full scaffolding (pages, components, server logic, config)');\n\ngenerate\n .command('blog')\n .description('Add an MDX-based blog with listing, post pages, RSS feed, and SEO')\n .action(async () => {\n await generateBlog(process.cwd());\n });\n\ngenerate\n .command('dark-mode')\n .description('Add dark mode with ThemeProvider, theme toggle, system preference detection, and FOUC prevention')\n .action(async () => {\n await generateDarkMode(process.cwd());\n });\n\ngenerate\n .command('notifications')\n .description('Add in-app notifications with Prisma model, API routes, bell component, and polling hook')\n .action(async () => {\n await generateNotifications(process.cwd());\n });\n\ngenerate\n .command('analytics')\n .description('Add analytics with Vercel/PostHog/Google providers, consent banner, and unified tracking API')\n .action(async () => {\n await generateAnalytics(process.cwd());\n });\n\ngenerate\n .command('command-palette')\n .description('Add a Cmd+K command palette with fuzzy search, action registry, and keyboard navigation')\n .action(async () => {\n await generateCommandPalette(process.cwd());\n });\n\ngenerate\n .command('onboarding')\n .description('Add multi-step user onboarding with progress tracking, skip/complete, and redirect logic')\n .action(async () => {\n await generateOnboarding(process.cwd());\n });\n\ngenerate\n .command('search')\n .description('Add search with Postgres full-text, Algolia, or Meilisearch providers and debounced hook')\n .action(async () => {\n await generateSearch(process.cwd());\n });\n\ngenerate\n .command('realtime')\n .description('Add realtime updates with SSE (default), Pusher, or Ably providers and client hooks')\n .action(async () => {\n await generateRealtime(process.cwd());\n });\n\ngenerate\n .command('ai')\n .description('Add AI integration with OpenAI/Anthropic providers, streaming chat API, and useChat hook')\n .action(async () => {\n await generateAI(process.cwd());\n });\n\ngenerate\n .command('cookie-consent')\n .description('Add a cookie consent banner with preferences dialog and useConsent hook')\n .action(async () => {\n await generateCookieConsent(process.cwd());\n });\n\ngenerate\n .command('coming-soon')\n .description('Add a coming soon landing page with waitlist signup')\n .action(async () => {\n await generateComingSoon(process.cwd());\n });\n\ngenerate\n .command('sentry')\n .description('Add Sentry error tracking with client/server init and ErrorBoundary component')\n .action(async () => {\n await generateSentry(process.cwd());\n });\n\ngenerate\n .command('feature-flags')\n .description('Add feature flags with local JSON provider, server getFlag, client hook, and FeatureGate component')\n .action(async () => {\n await generateFeatureFlags(process.cwd());\n });\n\nprogram\n .command('configure')\n .description('Configure a service provider (email, payments, storage, etc.)')\n .argument('[service]', 'Service to configure (email, payments, storage, analytics, monitoring, auth)')\n .action(async (service?: string) => {\n await configureCommand(service);\n });\n\nprogram\n .command('deploy')\n .description('Deploy your project to Vercel')\n .action(async () => {\n await deployCommand();\n });\n\nprogram\n .command('doctor')\n .description('Check your development environment')\n .option('--upgrade-check', 'Check if Mars packages have updates available')\n .action(async (options: { upgradeCheck?: boolean }) => {\n await doctorCommand(options);\n });\n\nupgradeCommand(program);\n\nprogram\n .command('telemetry')\n .description('Manage anonymous usage telemetry')\n .argument('<action>', 'enable or disable')\n .action((action: string) => {\n if (action === 'enable') {\n enableTelemetry();\n log.success('Telemetry enabled. Thank you for helping improve Mars!');\n } else if (action === 'disable') {\n disableTelemetry();\n log.success('Telemetry disabled.');\n } else {\n log.error('Usage: mars telemetry <enable|disable>');\n }\n });\n\nprogram.parse();\n","import fs from 'fs-extra';\nimport path from 'path';\nimport os from 'os';\nimport ora from 'ora';\nimport pc from 'picocolors';\nimport prompts from 'prompts';\nimport { log } from '../utils/logger.js';\nimport { resolveProjectPath } from '../utils/template.js';\nimport { promptProjectInfo, getDefaultProjectInfo } from '../prompts/project-info.js';\nimport { promptFeatures, getDefaultFeatures } from '../prompts/features.js';\nimport { promptServices, getDefaultServices } from '../prompts/services.js';\nimport { promptTheme, getDefaultTheme } from '../prompts/theme.js';\nimport { scaffoldProject } from '../generators/scaffold.js';\nimport { generateSelectedFeatures } from '../generators/generate-selected.js';\nimport { enableTelemetry, trackEvent } from '../utils/telemetry.js';\nimport type { ProjectConfig, FeatureFlags, ServiceConfig, ThemeConfig } from '../types.js';\n\nconst RC_PATH = path.join(os.homedir(), '.marsrc');\n\nconst PROJECT_NAME_REGEX = /^[a-z0-9][a-z0-9-]*[a-z0-9]$/;\nconst MAX_PROJECT_NAME_LENGTH = 214;\n\nexport async function createCommand(\n projectName?: string,\n options?: { defaults?: boolean },\n): Promise<void> {\n const useDefaults = options?.defaults === true;\n\n log.banner();\n\n if (projectName) {\n if (!PROJECT_NAME_REGEX.test(projectName) && projectName.length > 1) {\n log.error('Project name must be lowercase letters, numbers, and hyphens only.');\n return;\n }\n if (projectName.length > MAX_PROJECT_NAME_LENGTH) {\n log.error(`Project name is too long (max ${MAX_PROJECT_NAME_LENGTH} characters).`);\n return;\n }\n if (projectName.includes('..') || projectName.includes('/') || projectName.includes('\\\\')) {\n log.error('Project name cannot contain path traversal characters.');\n return;\n }\n }\n\n if (useDefaults && !projectName) {\n log.error('Project name is required when using --defaults.');\n return;\n }\n\n const projectInfo = useDefaults\n ? getDefaultProjectInfo(projectName!)\n : await promptProjectInfo(projectName);\n if (!projectInfo) return;\n\n const targetDir = resolveProjectPath(projectInfo.name);\n if (await fs.pathExists(targetDir)) {\n const entries = await fs.readdir(targetDir);\n if (entries.length > 0) {\n log.error(`Directory \"${projectInfo.name}\" already exists and is not empty.`);\n return;\n }\n }\n\n const features: FeatureFlags = useDefaults\n ? getDefaultFeatures()\n : (await promptFeatures() as FeatureFlags);\n if (!features) return;\n\n const services: ServiceConfig = useDefaults\n ? getDefaultServices(features)\n : (await promptServices(features) as ServiceConfig);\n if (!services) return;\n\n const theme: ThemeConfig = useDefaults\n ? getDefaultTheme()\n : (await promptTheme() as ThemeConfig);\n if (!theme) return;\n\n const config: ProjectConfig = {\n ...projectInfo,\n features,\n services,\n theme,\n };\n\n log.blank();\n log.title('Summary');\n log.info(`Project: ${pc.bold(config.displayName)} (${config.name})`);\n log.info(`URL: ${config.url}`);\n log.info(`Features: ${countEnabled(features)} enabled`);\n log.info(`Database: ${services.database.provider}`);\n log.info(`Email: ${services.email.provider}`);\n log.info(`Theme: ${theme.primaryColor}, ${theme.font}, ${theme.designDirection}`);\n log.blank();\n\n if (!useDefaults) {\n const { confirmed } = await prompts(\n {\n type: 'confirm',\n name: 'confirmed',\n message: 'Proceed with scaffolding?',\n initial: true,\n },\n { onCancel: () => process.exit(0) },\n );\n\n if (!confirmed) {\n log.info('Scaffolding cancelled.');\n process.exit(0);\n }\n\n if (!fs.pathExistsSync(RC_PATH)) {\n const { telemetryOptIn } = await prompts(\n {\n type: 'confirm',\n name: 'telemetryOptIn',\n message: 'Help improve Mars by sharing anonymous usage data? This is completely opt-in.',\n initial: false,\n },\n { onCancel: () => {} },\n );\n if (telemetryOptIn) {\n enableTelemetry();\n log.success('Telemetry enabled. Thank you!');\n }\n }\n }\n\n const spinner = ora('Scaffolding project...').start();\n\n try {\n const { fileCount } = await scaffoldProject(targetDir, config);\n spinner.succeed(`Scaffolded ${pc.bold(String(fileCount))} files`);\n\n const generatedFeatures = await generateSelectedFeatures(targetDir, config.features);\n if (generatedFeatures.length > 0) {\n log.success(`Generated ${generatedFeatures.length} additional feature(s): ${generatedFeatures.join(', ')}`);\n }\n\n trackEvent('create', {\n features: Object.keys(features).filter((f) => features[f as keyof FeatureFlags]).join(','),\n });\n\n log.blank();\n log.title('Next Steps');\n log.step(`cd ${projectInfo.name}`);\n log.step('yarn install');\n log.step('yarn dev # starts database + syncs schema + launches dev server');\n log.blank();\n log.success('Your MARS project is ready. Happy building!');\n log.blank();\n } catch (err) {\n spinner.fail('Failed to scaffold project');\n log.error(err instanceof Error ? err.message : String(err));\n\n if (await fs.pathExists(targetDir)) {\n const cleanupSpinner = ora('Cleaning up...').start();\n try {\n await fs.remove(targetDir);\n cleanupSpinner.succeed('Cleaned up partial scaffold');\n } catch {\n cleanupSpinner.warn(`Could not clean up ${targetDir}. You may need to remove it manually.`);\n }\n }\n\n process.exit(1);\n }\n}\n\nfunction countEnabled(flags: Record<string, boolean>): number {\n return Object.values(flags).filter(Boolean).length;\n}\n","import path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport fs from 'fs-extra';\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\n\nexport function getTemplatePath(): string {\n const candidates = [\n // Built bundle: __dirname = packages/cli/dist/\n path.resolve(__dirname, '..', 'template'),\n path.resolve(__dirname, '..', '..', '..', 'template'),\n // Source (vitest): __dirname = packages/cli/src/utils/\n path.resolve(__dirname, '..', '..', '..', '..', 'template'),\n ];\n\n for (const candidate of candidates) {\n if (fs.existsSync(candidate)) {\n return candidate;\n }\n }\n\n throw new Error(\n 'Template directory not found. If installed from npm, ensure the package includes the template/ directory.',\n );\n}\n\nexport function resolveProjectPath(projectName: string): string {\n return path.resolve(process.cwd(), projectName);\n}\n","import prompts from 'prompts';\nimport { log } from '../utils/logger.js';\n\nexport interface ProjectInfoAnswers {\n name: string;\n displayName: string;\n description: string;\n url: string;\n supportEmail: string;\n}\n\nfunction toDisplayName(kebab: string): string {\n return kebab\n .split('-')\n .map((w) => w.charAt(0).toUpperCase() + w.slice(1))\n .join(' ');\n}\n\nexport function getDefaultProjectInfo(name: string): ProjectInfoAnswers {\n return {\n name,\n displayName: toDisplayName(name),\n description: 'A SaaS application built with MARS',\n url: `https://${name}.com`,\n supportEmail: `support@${name}.com`,\n };\n}\n\nfunction toKebabCase(str: string): string {\n return str\n .replace(/([a-z])([A-Z])/g, '$1-$2')\n .replace(/[\\s_]+/g, '-')\n .replace(/[^a-z0-9-]/gi, '')\n .toLowerCase();\n}\n\nexport async function promptProjectInfo(\n initialName?: string,\n): Promise<ProjectInfoAnswers | null> {\n log.title('Project Setup');\n\n const answers = await prompts(\n [\n {\n type: initialName ? null : 'text',\n name: 'name',\n message: 'Project name (kebab-case):',\n initial: 'my-app',\n validate: (val: string) =>\n /^[a-z0-9-]+$/.test(val) || 'Must be lowercase letters, numbers, and hyphens only',\n },\n {\n type: 'text',\n name: 'displayName',\n message: 'Display name:',\n initial: (prev: string) => toDisplayName(initialName || prev),\n },\n {\n type: 'text',\n name: 'description',\n message: 'Short description:',\n initial: 'A SaaS application built with MARS',\n },\n {\n type: 'text',\n name: 'url',\n message: 'Production URL:',\n initial: (prev: string, values: Record<string, string>) =>\n `https://${initialName || values.name}.com`,\n },\n {\n type: 'text',\n name: 'supportEmail',\n message: 'Support email:',\n initial: (prev: string, values: Record<string, string>) =>\n `support@${initialName || values.name}.com`,\n },\n ],\n {\n onCancel: () => {\n log.error('Setup cancelled.');\n return false;\n },\n },\n );\n\n if (!answers.displayName) return null;\n\n return {\n name: initialName || toKebabCase(answers.name),\n displayName: answers.displayName,\n description: answers.description,\n url: answers.url,\n supportEmail: answers.supportEmail,\n };\n}\n","import prompts from 'prompts';\nimport { log } from '../utils/logger.js';\nimport type { FeatureFlags } from '../types.js';\n\nconst FEATURE_GROUPS = [\n {\n title: 'Authentication & Users',\n features: [\n { name: 'auth', label: 'Email/password auth', default: true },\n { name: 'googleOAuth', label: 'Google OAuth', default: false },\n { name: 'emailVerification', label: 'Email verification', default: true },\n { name: 'magicLinks', label: 'Magic link login', default: false },\n { name: 'twoFactor', label: 'Two-factor auth', default: false },\n { name: 'admin', label: 'Admin role & panel', default: true },\n ],\n },\n {\n title: 'App Features',\n features: [\n { name: 'darkMode', label: 'Dark mode', default: false },\n { name: 'notifications', label: 'Notifications', default: false },\n { name: 'onboarding', label: 'Onboarding flow', default: false },\n { name: 'billing', label: 'Billing / subscriptions', default: false },\n { name: 'blog', label: 'Blog / content', default: false },\n { name: 'fileUpload', label: 'File uploads', default: false },\n { name: 'search', label: 'Search', default: false },\n { name: 'realtime', label: 'Realtime updates', default: false },\n { name: 'commandPalette', label: 'Command palette (⌘K)', default: false },\n { name: 'ai', label: 'AI integration', default: false },\n ],\n },\n {\n title: 'Infrastructure',\n features: [\n { name: 'seo', label: 'SEO & JSON-LD', default: true },\n { name: 'cookieConsent', label: 'Cookie consent', default: true },\n { name: 'analytics', label: 'Analytics', default: false },\n { name: 'sentry', label: 'Error monitoring', default: false },\n { name: 'featureFlags', label: 'Feature flags', default: false },\n ],\n },\n {\n title: 'Architecture',\n features: [\n { name: 'multiTenancy', label: 'Multi-tenancy', default: false },\n { name: 'teams', label: 'Teams / orgs', default: false },\n { name: 'comingSoon', label: 'Coming soon mode', default: false },\n ],\n },\n];\n\nexport function getDefaultFeatures(): FeatureFlags {\n const flags: Record<string, boolean> = {};\n for (const group of FEATURE_GROUPS) {\n for (const feature of group.features) {\n flags[feature.name] = feature.default;\n }\n }\n return flags as unknown as FeatureFlags;\n}\n\nexport async function promptFeatures(): Promise<FeatureFlags | null> {\n log.title('Feature Selection');\n log.info('Select the features you want to include:');\n log.blank();\n\n const flags: Record<string, boolean> = {};\n\n for (const group of FEATURE_GROUPS) {\n const choices = group.features.map((f) => ({\n title: f.label,\n value: f.name,\n selected: f.default,\n }));\n\n const response = await prompts(\n {\n type: 'multiselect',\n name: 'selected',\n message: group.title,\n choices,\n hint: '- Space to toggle, Enter to confirm',\n instructions: false,\n },\n {\n onCancel: () => {\n log.error('Setup cancelled.');\n return false;\n },\n },\n );\n\n if (!response.selected) return null;\n\n for (const feature of group.features) {\n flags[feature.name] = (response.selected as string[]).includes(feature.name);\n }\n }\n\n return flags as unknown as FeatureFlags;\n}\n","import prompts from 'prompts';\nimport { log } from '../utils/logger.js';\nimport type { FeatureFlags, ServiceConfig } from '../types.js';\n\ninterface ServiceQuestion {\n key: keyof ServiceConfig;\n message: string;\n choices: Array<{ title: string; value: string }>;\n condition?: (features: FeatureFlags) => boolean;\n defaultValue: string;\n}\n\nconst SERVICE_QUESTIONS: ServiceQuestion[] = [\n {\n key: 'database',\n message: 'Database provider:',\n choices: [\n { title: 'Local (Docker Postgres)', value: 'local' },\n { title: 'Vercel Postgres', value: 'vercel' },\n { title: 'Supabase', value: 'supabase' },\n ],\n defaultValue: 'local',\n },\n {\n key: 'email',\n message: 'Email provider:',\n choices: [\n { title: 'Console (dev only)', value: 'console' },\n { title: 'SendGrid', value: 'sendgrid' },\n { title: 'Resend', value: 'resend' },\n ],\n defaultValue: 'console',\n },\n {\n key: 'storage',\n message: 'File storage:',\n condition: (f) => f.fileUpload,\n choices: [\n { title: 'Local filesystem', value: 'local' },\n { title: 'Vercel Blob', value: 'vercel' },\n { title: 'AWS S3', value: 's3' },\n ],\n defaultValue: 'local',\n },\n {\n key: 'payments',\n message: 'Payment provider:',\n condition: (f) => f.billing,\n choices: [\n { title: 'None', value: 'none' },\n { title: 'Stripe', value: 'stripe' },\n ],\n defaultValue: 'none',\n },\n {\n key: 'analytics',\n message: 'Analytics provider:',\n condition: (f) => f.analytics,\n choices: [\n { title: 'None', value: 'none' },\n { title: 'Vercel Analytics', value: 'vercel' },\n { title: 'PostHog', value: 'posthog' },\n { title: 'Google Analytics', value: 'google' },\n ],\n defaultValue: 'none',\n },\n {\n key: 'monitoring',\n message: 'Error monitoring:',\n condition: (f) => f.sentry,\n choices: [\n { title: 'None', value: 'none' },\n { title: 'Sentry', value: 'sentry' },\n ],\n defaultValue: 'none',\n },\n {\n key: 'ai',\n message: 'AI provider:',\n condition: (f) => f.ai,\n choices: [\n { title: 'None', value: 'none' },\n { title: 'OpenAI', value: 'openai' },\n { title: 'Anthropic', value: 'anthropic' },\n ],\n defaultValue: 'none',\n },\n {\n key: 'search',\n message: 'Search provider:',\n condition: (f) => f.search,\n choices: [\n { title: 'None', value: 'none' },\n { title: 'Postgres full-text', value: 'postgres' },\n { title: 'Algolia', value: 'algolia' },\n { title: 'Meilisearch', value: 'meilisearch' },\n ],\n defaultValue: 'none',\n },\n {\n key: 'realtime',\n message: 'Realtime provider:',\n condition: (f) => f.realtime,\n choices: [\n { title: 'None', value: 'none' },\n { title: 'Server-Sent Events', value: 'sse' },\n { title: 'Pusher', value: 'pusher' },\n { title: 'Ably', value: 'ably' },\n ],\n defaultValue: 'none',\n },\n {\n key: 'jobs',\n message: 'Background jobs:',\n choices: [\n { title: 'None', value: 'none' },\n { title: 'Database-backed', value: 'db' },\n { title: 'Inngest', value: 'inngest' },\n { title: 'Trigger.dev', value: 'trigger' },\n ],\n defaultValue: 'none',\n },\n];\n\nexport function getDefaultServices(_features: FeatureFlags): ServiceConfig {\n const config: Record<string, { provider: string }> = {};\n for (const q of SERVICE_QUESTIONS) {\n config[q.key] = { provider: q.defaultValue };\n }\n return config as unknown as ServiceConfig;\n}\n\nexport async function promptServices(features: FeatureFlags): Promise<ServiceConfig | null> {\n log.title('Service Providers');\n log.info('Choose providers for each service:');\n log.blank();\n\n const config: Record<string, { provider: string }> = {};\n\n for (const q of SERVICE_QUESTIONS) {\n if (q.condition && !q.condition(features)) {\n config[q.key] = { provider: q.defaultValue };\n continue;\n }\n\n const response = await prompts(\n {\n type: 'select',\n name: 'provider',\n message: q.message,\n choices: q.choices,\n initial: q.choices.findIndex((c) => c.value === q.defaultValue),\n },\n {\n onCancel: () => {\n log.error('Setup cancelled.');\n return false;\n },\n },\n );\n\n if (response.provider === undefined) return null;\n\n config[q.key] = { provider: response.provider };\n }\n\n return config as unknown as ServiceConfig;\n}\n","import prompts from 'prompts';\nimport { log } from '../utils/logger.js';\nimport type { ThemeConfig } from '../types.js';\n\nconst COLOR_PRESETS = [\n { title: 'Blue (default)', value: 'blue-600' },\n { title: 'Indigo', value: 'indigo-600' },\n { title: 'Violet', value: 'violet-600' },\n { title: 'Emerald', value: 'emerald-600' },\n { title: 'Rose', value: 'rose-600' },\n { title: 'Amber', value: 'amber-600' },\n { title: 'Cyan', value: 'cyan-600' },\n { title: 'Slate', value: 'slate-600' },\n];\n\nconst FONT_CHOICES = [\n { title: 'Inter (clean, modern)', value: 'Inter' },\n { title: 'DM Sans (friendly)', value: 'DM Sans' },\n { title: 'Plus Jakarta Sans (professional)', value: 'Plus Jakarta Sans' },\n { title: 'Outfit (geometric)', value: 'Outfit' },\n { title: 'Space Grotesk (technical)', value: 'Space Grotesk' },\n { title: 'System default', value: 'system-ui' },\n];\n\nconst DESIGN_DIRECTIONS = [\n { title: 'Modern SaaS (default)', value: 'modern-saas' },\n { title: 'Minimal', value: 'minimal' },\n { title: 'Enterprise', value: 'enterprise' },\n { title: 'Creative', value: 'creative' },\n { title: 'Dashboard', value: 'dashboard' },\n];\n\nexport function getDefaultTheme(): ThemeConfig {\n return {\n primaryColor: COLOR_PRESETS[0].value,\n secondaryColor: 'amber-400',\n font: FONT_CHOICES[0].value,\n designDirection: DESIGN_DIRECTIONS[0].value as ThemeConfig['designDirection'],\n };\n}\n\nexport async function promptTheme(): Promise<ThemeConfig | null> {\n log.title('Theme & Design');\n\n const response = await prompts(\n [\n {\n type: 'select',\n name: 'primaryColor',\n message: 'Primary brand color:',\n choices: COLOR_PRESETS,\n initial: 0,\n },\n {\n type: 'select',\n name: 'font',\n message: 'Font family:',\n choices: FONT_CHOICES,\n initial: 0,\n },\n {\n type: 'select',\n name: 'designDirection',\n message: 'Design direction:',\n choices: DESIGN_DIRECTIONS,\n initial: 0,\n },\n ],\n {\n onCancel: () => {\n log.error('Setup cancelled.');\n return false;\n },\n },\n );\n\n if (response.primaryColor === undefined) return null;\n\n return {\n primaryColor: response.primaryColor,\n secondaryColor: 'amber-400',\n font: response.font,\n designDirection: response.designDirection,\n };\n}\n","import fs from 'fs-extra';\nimport path from 'node:path';\nimport type { FeatureFlags, ProjectConfig } from '../types.js';\nimport { log } from '../utils/logger.js';\nimport { getTemplatePath } from '../utils/template.js';\nimport { generateAppConfig } from './app-config.js';\nimport { generateEnvFile, generateEnvExample } from './env.js';\n\nconst IGNORED_DIRS = ['node_modules', '.next', '.turbo', 'dist', '.git'];\nconst IGNORED_FILES = [\n '.env',\n '.env.local',\n '.env.development',\n '.env.test',\n 'yarn.lock',\n 'next-env.d.ts',\n];\n\nasync function copyTemplateFiles(templateDir: string, targetDir: string): Promise<number> {\n let fileCount = 0;\n\n async function walkAndCopy(src: string, dest: string) {\n const entries = await fs.readdir(src, { withFileTypes: true });\n\n for (const entry of entries) {\n const srcPath = path.join(src, entry.name);\n const destPath = path.join(dest, entry.name);\n\n if (entry.isDirectory()) {\n if (IGNORED_DIRS.includes(entry.name)) continue;\n await fs.ensureDir(destPath);\n await walkAndCopy(srcPath, destPath);\n } else {\n if (IGNORED_FILES.includes(entry.name)) continue;\n await fs.copy(srcPath, destPath);\n fileCount++;\n }\n }\n }\n\n await walkAndCopy(templateDir, targetDir);\n return fileCount;\n}\n\n/**\n * Resolve the semver range for a @mars-stack/* package by reading its actual version.\n * Looks in the monorepo packages/ directory first, then falls back to the version\n * already declared in the template's package.json.\n */\nexport function resolveMarsPackageRange(packageName: string, templateDir: string): string {\n const shortName = packageName.replace('@mars-stack/', '');\n\n const candidates = [\n path.resolve(templateDir, '..', 'packages', shortName, 'package.json'),\n path.resolve(templateDir, '..', '..', 'packages', shortName, 'package.json'),\n ];\n\n for (const candidate of candidates) {\n if (fs.existsSync(candidate)) {\n const pkg = fs.readJsonSync(candidate) as { version?: string };\n if (typeof pkg.version === 'string') {\n const [major, minor] = pkg.version.split('.');\n return `^${major}.${minor}.0`;\n }\n }\n }\n\n const templatePkg = fs.readJsonSync(path.join(templateDir, 'package.json')) as {\n dependencies?: Record<string, string>;\n };\n const existing = templatePkg.dependencies?.[packageName];\n if (existing && existing !== '*') {\n if (/^[\\^~>=]/.test(existing)) return existing;\n const parts = existing.split('.');\n if (parts.length >= 2) return `^${parts[0]}.${parts[1]}.0`;\n }\n\n return '>=0.1.0';\n}\n\nfunction generatePackageJson(config: ProjectConfig): string {\n const templateDir = getTemplatePath();\n const templatePkg = path.join(templateDir, 'package.json');\n const pkg = fs.readJsonSync(templatePkg);\n\n pkg.name = config.name;\n pkg.version = '0.1.0';\n pkg.private = true;\n pkg.description = config.description;\n pkg.mars = true;\n\n delete pkg.workspaces;\n\n if (pkg.dependencies?.['@mars-stack/core']) {\n pkg.dependencies['@mars-stack/core'] = resolveMarsPackageRange('@mars-stack/core', templateDir);\n }\n if (pkg.dependencies?.['@mars-stack/ui']) {\n pkg.dependencies['@mars-stack/ui'] = resolveMarsPackageRange('@mars-stack/ui', templateDir);\n }\n\n return JSON.stringify(pkg, null, 2) + '\\n';\n}\n\nfunction escapeYamlValue(value: string): string {\n if (/[:\\$\\*\\&\\#\\[\\]\\{\\}\\|>!%@`]/.test(value) || value.includes('\"')) {\n return `\"${value.replace(/\\\\/g, '\\\\\\\\').replace(/\"/g, '\\\\\"')}\"`;\n }\n return value;\n}\n\nfunction generateDockerCompose(config: ProjectConfig): string {\n const dbName = escapeYamlValue(`${config.name}_dev`);\n const dbUser = escapeYamlValue(config.name);\n const dbPass = escapeYamlValue(config.name);\n\n return `# Optional: use Docker instead of the embedded database (prisma dev).\n# Start with: docker compose up -d\nservices:\n postgres:\n image: postgres:16-alpine\n ports:\n - '5432:5432'\n environment:\n POSTGRES_DB: ${dbName}\n POSTGRES_USER: ${dbUser}\n POSTGRES_PASSWORD: ${dbPass}\n volumes:\n - postgres_data:/var/lib/postgresql/data\n healthcheck:\n test: ['CMD-SHELL', 'pg_isready -U ${dbUser} -d ${dbName}']\n interval: 5s\n timeout: 5s\n retries: 5\n\n redis:\n image: redis:7-alpine\n ports:\n - '6379:6379'\n healthcheck:\n test: ['CMD', 'redis-cli', 'ping']\n interval: 5s\n timeout: 5s\n retries: 5\n\nvolumes:\n postgres_data:\n`;\n}\n\nconst FONT_IMPORTS: Record<string, { importName: string; importFrom: string }> = {\n 'Inter': { importName: 'Inter', importFrom: 'Inter' },\n 'DM Sans': { importName: 'DM_Sans', importFrom: 'DM_Sans' },\n 'Plus Jakarta Sans': { importName: 'Plus_Jakarta_Sans', importFrom: 'Plus_Jakarta_Sans' },\n 'Outfit': { importName: 'Outfit', importFrom: 'Outfit' },\n 'Space Grotesk': { importName: 'Space_Grotesk', importFrom: 'Space_Grotesk' },\n 'system-ui': { importName: '', importFrom: '' },\n};\n\nfunction generateLayout(config: ProjectConfig): string {\n const fontKey = config.theme.font;\n const fontConfig = FONT_IMPORTS[fontKey] || FONT_IMPORTS['Inter'];\n\n if (!fontConfig.importName) {\n return `import type { Metadata } from 'next';\nimport '@/styles/globals.css';\nimport { appConfig } from '@/config/app.config';\nimport { Providers } from './providers';\n\nexport const metadata: Metadata = {\n title: {\n default: appConfig.name,\n template: \\`%s | \\${appConfig.name}\\`,\n },\n description: appConfig.description,\n metadataBase: new URL(appConfig.url),\n};\n\nexport default function RootLayout({ children }: { children: React.ReactNode }) {\n return (\n <html lang=\"en\" suppressHydrationWarning>\n <body className=\"bg-surface-background text-text-primary antialiased font-sans\">\n <Providers>{children}</Providers>\n </body>\n </html>\n );\n}\n`;\n }\n\n return `import type { Metadata } from 'next';\nimport { ${fontConfig.importFrom} } from 'next/font/google';\nimport '@/styles/globals.css';\nimport { appConfig } from '@/config/app.config';\nimport { Providers } from './providers';\n\nconst font = ${fontConfig.importFrom}({\n subsets: ['latin'],\n variable: '--font-sans',\n});\n\nexport const metadata: Metadata = {\n title: {\n default: appConfig.name,\n template: \\`%s | \\${appConfig.name}\\`,\n },\n description: appConfig.description,\n metadataBase: new URL(appConfig.url),\n};\n\nexport default function RootLayout({ children }: { children: React.ReactNode }) {\n return (\n <html lang=\"en\" className={font.variable} suppressHydrationWarning>\n <body className=\"bg-surface-background text-text-primary antialiased\">\n <Providers>{children}</Providers>\n </body>\n </html>\n );\n}\n`;\n}\n\nfunction generateGitignore(): string {\n return `# dependencies\nnode_modules/\n.pnp\n.pnp.js\n\n# next.js\n.next/\nout/\n\n# testing\ncoverage/\n\n# build\ndist/\n*.tsbuildinfo\n\n# env\n.env\n.env.local\n.env.development\n.env.development.local\n.env.test\n\n# local database\n.mars/\n\n# misc\n.DS_Store\n*.pem\n\n# debug\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n\n# turbo\n.turbo\n\n# vercel\n.vercel\n\n# prisma\nprisma/migrations/\n`;\n}\n\nconst FEATURE_DIRECTORY_MAP: Record<string, string[]> = {\n admin: [\n 'src/app/(protected)/admin',\n 'src/app/api/protected/admin',\n ],\n billing: [\n 'src/features/billing',\n 'src/app/api/protected/billing',\n 'src/app/api/webhooks/stripe',\n 'prisma/schema/subscription.prisma',\n ],\n fileUpload: [\n 'src/features/uploads',\n 'src/app/api/protected/files',\n 'prisma/schema/file.prisma',\n ],\n};\n\nconst USER_RELATION_MAP: Record<string, string> = {\n billing: 'subscription',\n fileUpload: 'files',\n};\n\nexport async function pruneDisabledFeatures(\n features: FeatureFlags,\n targetDir: string,\n): Promise<void> {\n const relationsToRemove: string[] = [];\n\n for (const [feature, paths] of Object.entries(FEATURE_DIRECTORY_MAP)) {\n const flagValue = features[feature as keyof FeatureFlags];\n if (flagValue !== false) continue;\n\n for (const relativePath of paths) {\n const fullPath = path.join(targetDir, relativePath);\n if (await fs.pathExists(fullPath)) {\n await fs.remove(fullPath);\n log.step(`Pruned disabled feature path: ${relativePath}`);\n }\n }\n\n if (USER_RELATION_MAP[feature]) {\n relationsToRemove.push(USER_RELATION_MAP[feature]);\n }\n }\n\n if (relationsToRemove.length > 0) {\n const authPath = path.join(targetDir, 'prisma', 'schema', 'auth.prisma');\n if (await fs.pathExists(authPath)) {\n let content = await fs.readFile(authPath, 'utf-8');\n for (const field of relationsToRemove) {\n content = content.replace(new RegExp(`\\\\s*${field}\\\\s+\\\\S+.*\\\\n`, 'g'), '\\n');\n }\n await fs.writeFile(authPath, content);\n }\n }\n}\n\nexport async function scaffoldProject(\n targetDir: string,\n config: ProjectConfig,\n): Promise<{ fileCount: number }> {\n const templateDir = getTemplatePath();\n\n if (!(await fs.pathExists(templateDir))) {\n throw new Error(`Template directory not found: ${templateDir}`);\n }\n\n await fs.ensureDir(targetDir);\n\n const fileCount = await copyTemplateFiles(templateDir, targetDir);\n\n await pruneDisabledFeatures(config.features, targetDir);\n\n await fs.writeFile(path.join(targetDir, 'package.json'), generatePackageJson(config));\n\n await fs.writeFile(\n path.join(targetDir, 'src', 'config', 'app.config.ts'),\n generateAppConfig(config),\n );\n\n await fs.writeFile(path.join(targetDir, 'docker-compose.yml'), generateDockerCompose(config));\n\n await fs.writeFile(path.join(targetDir, 'src', 'app', 'layout.tsx'), generateLayout(config));\n\n await fs.writeFile(path.join(targetDir, '.env'), generateEnvFile(config));\n await fs.writeFile(path.join(targetDir, '.env.example'), generateEnvExample(config));\n await fs.writeFile(path.join(targetDir, '.gitignore'), generateGitignore());\n\n await patchGlobalsCssForScaffoldedProject(targetDir);\n\n return { fileCount };\n}\n\n/** Fix @source path: scaffolded projects have node_modules at project root, not three levels up. */\nasync function patchGlobalsCssForScaffoldedProject(targetDir: string): Promise<void> {\n const globalsPath = path.join(targetDir, 'src', 'styles', 'globals.css');\n if (!(await fs.pathExists(globalsPath))) return;\n\n let content = await fs.readFile(globalsPath, 'utf-8');\n content = content.replace(\n '@source \"../../../node_modules/@mars-stack/ui/dist/**/*.js\";',\n '@source \"../../node_modules/@mars-stack/ui/dist/**/*.js\";',\n );\n await fs.writeFile(globalsPath, content);\n}\n","import type { ProjectConfig, FeatureFlags } from '../types.js';\n\nfunction escapeQuotes(value: string): string {\n return value.replace(/\\\\/g, '\\\\\\\\').replace(/'/g, \"\\\\'\");\n}\n\nconst SCAFFOLDED_FEATURES: Set<keyof FeatureFlags> = new Set([\n 'auth',\n 'emailVerification',\n 'admin',\n 'billing',\n 'fileUpload',\n 'seo',\n]);\n\nexport function generateAppConfig(config: ProjectConfig): string {\n const featureEntries = Object.entries(config.features)\n .map(([key, val]) => {\n const hasCode = SCAFFOLDED_FEATURES.has(key as keyof FeatureFlags);\n return ` ${key}: ${hasCode ? val : false},`;\n })\n .join('\\n');\n\n const serviceEntries = Object.entries(config.services)\n .map(([key, svc]) => {\n const provider = (svc as { provider: string }).provider;\n return ` ${key}: { provider: '${escapeQuotes(provider)}' },`;\n })\n .join('\\n');\n\n return `export const appConfig = {\n name: '${escapeQuotes(config.displayName)}',\n tagline: '${escapeQuotes(config.description)}',\n description: '${escapeQuotes(config.description)}',\n url: '${escapeQuotes(config.url)}',\n support: { email: '${escapeQuotes(config.supportEmail)}', phone: '' },\n social: {\n twitter: '',\n tiktok: '',\n linkedin: '',\n github: '',\n instagram: '',\n },\n legal: {\n companyName: '',\n registrationNumber: '',\n address: '',\n },\n theme: {\n primaryColor: '${config.theme.primaryColor}' as string,\n secondaryColor: '${config.theme.secondaryColor}' as string,\n font: '${config.theme.font}' as string,\n designDirection: '${config.theme.designDirection}' as\n | 'modern-saas'\n | 'minimal'\n | 'enterprise'\n | 'creative'\n | 'dashboard',\n },\n features: {\n${featureEntries}\n },\n services: {\n${serviceEntries}\n },\n} as const;\n\nexport type AppConfig = typeof appConfig;\n`;\n}\n","import crypto from 'node:crypto';\nimport type { ProjectConfig } from '../types.js';\n\nfunction generateSecret(): string {\n return crypto.randomBytes(32).toString('hex');\n}\n\nexport function generateEnvFile(config: ProjectConfig): string {\n const lines: string[] = [\n '# Generated by MARS CLI',\n `# Project: ${config.displayName}`,\n '',\n '# === Core ===',\n 'APP_URL=http://localhost:3000',\n '# DATABASE_URL is auto-configured by `yarn dev` (embedded Postgres via prisma dev).',\n '# Uncomment and set manually to use a cloud database (Neon, Supabase, etc.):',\n `# DATABASE_URL=\"postgresql://user:password@host:5432/${config.name}_dev\"`,\n '',\n '# === Auth ===',\n `JWT_SECRET=\"${generateSecret()}\"`,\n '',\n ];\n\n if (config.features.googleOAuth) {\n lines.push('# === Google OAuth ===');\n lines.push('GOOGLE_CLIENT_ID=');\n lines.push('GOOGLE_CLIENT_SECRET=');\n lines.push('');\n }\n\n if (config.services.email.provider === 'sendgrid') {\n lines.push('# === SendGrid ===');\n lines.push('SENDGRID_API_KEY=');\n lines.push(`SENDGRID_FROM_EMAIL=${config.supportEmail}`);\n lines.push('');\n } else if (config.services.email.provider === 'resend') {\n lines.push('# === Resend ===');\n lines.push('RESEND_API_KEY=');\n lines.push(`RESEND_FROM_EMAIL=${config.supportEmail}`);\n lines.push('');\n }\n\n if (config.services.payments.provider === 'stripe') {\n lines.push('# === Stripe ===');\n lines.push('STRIPE_SECRET_KEY=');\n lines.push('NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=');\n lines.push('STRIPE_WEBHOOK_SECRET=');\n lines.push('');\n }\n\n if (config.services.analytics.provider === 'posthog') {\n lines.push('# === PostHog ===');\n lines.push('NEXT_PUBLIC_POSTHOG_KEY=');\n lines.push('NEXT_PUBLIC_POSTHOG_HOST=');\n lines.push('');\n } else if (config.services.analytics.provider === 'google') {\n lines.push('# === Google Analytics ===');\n lines.push('NEXT_PUBLIC_GA_MEASUREMENT_ID=');\n lines.push('');\n }\n\n if (config.services.monitoring.provider === 'sentry') {\n lines.push('# === Sentry ===');\n lines.push('SENTRY_DSN=');\n lines.push('SENTRY_AUTH_TOKEN=');\n lines.push('');\n }\n\n if (config.services.ai.provider === 'openai') {\n lines.push('# === OpenAI ===');\n lines.push('OPENAI_API_KEY=');\n lines.push('');\n } else if (config.services.ai.provider === 'anthropic') {\n lines.push('# === Anthropic ===');\n lines.push('ANTHROPIC_API_KEY=');\n lines.push('');\n }\n\n if (config.services.search.provider === 'algolia') {\n lines.push('# === Algolia ===');\n lines.push('ALGOLIA_APP_ID=');\n lines.push('ALGOLIA_ADMIN_KEY=');\n lines.push('NEXT_PUBLIC_ALGOLIA_SEARCH_KEY=');\n lines.push('');\n }\n\n if (config.services.realtime.provider === 'pusher') {\n lines.push('# === Pusher ===');\n lines.push('PUSHER_APP_ID=');\n lines.push('PUSHER_KEY=');\n lines.push('PUSHER_SECRET=');\n lines.push('PUSHER_CLUSTER=');\n lines.push('');\n } else if (config.services.realtime.provider === 'ably') {\n lines.push('# === Ably ===');\n lines.push('ABLY_API_KEY=');\n lines.push('');\n }\n\n if (config.services.storage.provider === 'vercel') {\n lines.push('# === Vercel Blob ===');\n lines.push('BLOB_READ_WRITE_TOKEN=');\n lines.push('');\n } else if (config.services.storage.provider === 's3') {\n lines.push('# === AWS S3 ===');\n lines.push('AWS_ACCESS_KEY_ID=');\n lines.push('AWS_SECRET_ACCESS_KEY=');\n lines.push('AWS_REGION=');\n lines.push('S3_BUCKET_NAME=');\n lines.push('');\n }\n\n lines.push('# === Rate Limiting (Upstash) ===');\n lines.push('UPSTASH_REDIS_REST_URL=');\n lines.push('UPSTASH_REDIS_REST_TOKEN=');\n lines.push('');\n\n return lines.join('\\n');\n}\n\nexport function generateEnvExample(config: ProjectConfig): string {\n const envContent = generateEnvFile(config);\n return envContent.replace(\n /^JWT_SECRET=\"[^\"]*\"$/m,\n 'JWT_SECRET=\"your-secret-here-min-32-characters-long\"'\n );\n}\n","import type { FeatureFlags } from '../types.js';\nimport { log } from '../utils/logger.js';\n\ntype GeneratorFn = (projectRoot: string) => Promise<void>;\n\ninterface FeatureGenerator {\n key: keyof FeatureFlags;\n name: string;\n generate: () => Promise<{ default?: GeneratorFn } & Record<string, GeneratorFn>>;\n}\n\nconst TEMPLATE_FEATURES: Set<keyof FeatureFlags> = new Set([\n 'auth',\n 'emailVerification',\n 'admin',\n 'billing',\n 'fileUpload',\n 'seo',\n]);\n\nconst GENERATOR_REGISTRY: FeatureGenerator[] = [\n {\n key: 'blog',\n name: 'blog',\n generate: () => import('./features/blog.js'),\n },\n {\n key: 'darkMode',\n name: 'dark-mode',\n generate: () => import('./features/dark-mode.js'),\n },\n {\n key: 'notifications',\n name: 'notifications',\n generate: () => import('./features/notifications.js'),\n },\n {\n key: 'analytics',\n name: 'analytics',\n generate: () => import('./features/analytics.js'),\n },\n {\n key: 'commandPalette',\n name: 'command-palette',\n generate: () => import('./features/command-palette.js'),\n },\n {\n key: 'onboarding',\n name: 'onboarding',\n generate: () => import('./features/onboarding.js'),\n },\n {\n key: 'search',\n name: 'search',\n generate: () => import('./features/search.js'),\n },\n {\n key: 'realtime',\n name: 'realtime',\n generate: () => import('./features/realtime.js'),\n },\n {\n key: 'ai',\n name: 'ai',\n generate: () => import('./features/ai.js'),\n },\n {\n key: 'cookieConsent',\n name: 'cookie-consent',\n generate: () => import('./features/cookie-consent.js'),\n },\n {\n key: 'comingSoon',\n name: 'coming-soon',\n generate: () => import('./features/coming-soon.js'),\n },\n {\n key: 'sentry',\n name: 'sentry',\n generate: () => import('./features/sentry.js'),\n },\n {\n key: 'featureFlags',\n name: 'feature-flags',\n generate: () => import('./features/feature-flags.js'),\n },\n];\n\nconst GENERATOR_FUNCTION_MAP: Record<string, string> = {\n blog: 'generateBlog',\n 'dark-mode': 'generateDarkMode',\n notifications: 'generateNotifications',\n analytics: 'generateAnalytics',\n 'command-palette': 'generateCommandPalette',\n onboarding: 'generateOnboarding',\n search: 'generateSearch',\n realtime: 'generateRealtime',\n ai: 'generateAI',\n 'cookie-consent': 'generateCookieConsent',\n 'coming-soon': 'generateComingSoon',\n sentry: 'generateSentry',\n 'feature-flags': 'generateFeatureFlags',\n};\n\nexport async function generateSelectedFeatures(\n projectRoot: string,\n features: FeatureFlags,\n): Promise<string[]> {\n const generated: string[] = [];\n\n for (const entry of GENERATOR_REGISTRY) {\n if (!features[entry.key]) continue;\n if (TEMPLATE_FEATURES.has(entry.key)) continue;\n\n try {\n const mod = await entry.generate();\n const fnName = GENERATOR_FUNCTION_MAP[entry.name];\n const fn = fnName ? (mod as Record<string, GeneratorFn>)[fnName] : undefined;\n\n if (fn) {\n await fn(projectRoot);\n generated.push(entry.name);\n }\n } catch (error) {\n log.warn(`Failed to generate ${entry.name}: ${error instanceof Error ? error.message : String(error)}`);\n }\n }\n\n return generated;\n}\n","import fs from 'fs-extra';\nimport path from 'path';\nimport os from 'os';\n\nconst RC_PATH = path.join(os.homedir(), '.marsrc');\n\ninterface TelemetryConfig {\n enabled: boolean;\n anonymousId: string;\n}\n\n/**\n * Checks whether the user has opted in to anonymous telemetry.\n *\n * @returns True if telemetry is explicitly enabled in ~/.marsrc\n * @example\n * if (isTelemetryEnabled()) trackEvent('create');\n */\nexport function isTelemetryEnabled(): boolean {\n try {\n const config = fs.readJsonSync(RC_PATH) as TelemetryConfig;\n return config.enabled === true;\n } catch {\n return false;\n }\n}\n\n/**\n * Enables anonymous telemetry by writing `enabled: true` to ~/.marsrc.\n *\n * @example\n * enableTelemetry();\n */\nexport function enableTelemetry(): void {\n const config = loadOrCreateConfig();\n config.enabled = true;\n fs.writeJsonSync(RC_PATH, config, { spaces: 2 });\n}\n\n/**\n * Disables anonymous telemetry by writing `enabled: false` to ~/.marsrc.\n *\n * @example\n * disableTelemetry();\n */\nexport function disableTelemetry(): void {\n const config = loadOrCreateConfig();\n config.enabled = false;\n fs.writeJsonSync(RC_PATH, config, { spaces: 2 });\n}\n\nfunction loadOrCreateConfig(): TelemetryConfig {\n try {\n return fs.readJsonSync(RC_PATH) as TelemetryConfig;\n } catch {\n return { enabled: false, anonymousId: crypto.randomUUID() };\n }\n}\n\n/**\n * Records an anonymous telemetry event to a local log file.\n * No-ops silently when telemetry is disabled. Never collects PII,\n * project names, file contents, or environment variables.\n *\n * @param event - The event name (e.g. 'create', 'add', 'deploy')\n * @param properties - Optional key-value metadata (feature flags, subcommand type, etc.)\n * @example\n * trackEvent('create', { features: 'auth,blog' });\n */\nexport function trackEvent(\n event: string,\n properties?: Record<string, string | number | boolean>,\n): void {\n if (!isTelemetryEnabled()) return;\n\n const config = loadOrCreateConfig();\n const payload = {\n event,\n anonymousId: config.anonymousId,\n properties: {\n ...properties,\n cliVersion: process.env.npm_package_version ?? 'unknown',\n nodeVersion: process.version,\n os: process.platform,\n arch: process.arch,\n },\n timestamp: new Date().toISOString(),\n };\n\n const logPath = path.join(os.homedir(), '.mars-telemetry.log');\n fs.appendFile(logPath, JSON.stringify(payload) + '\\n').catch(() => {});\n}\n","import fs from 'fs-extra';\nimport path from 'node:path';\nimport { execSync } from 'node:child_process';\nimport { log } from '../utils/logger.js';\n\ninterface Check {\n name: string;\n check: () => boolean | string;\n}\n\ninterface DoctorOptions {\n upgradeCheck?: boolean;\n}\n\ninterface NpmRegistryResponse {\n version: string;\n name: string;\n}\n\nfunction commandExists(cmd: string): boolean {\n try {\n execSync(`which ${cmd}`, { stdio: 'pipe' });\n return true;\n } catch {\n return false;\n }\n}\n\nfunction getVersion(cmd: string): string {\n try {\n return execSync(`${cmd} --version`, { stdio: 'pipe' }).toString().trim().split('\\n')[0];\n } catch {\n return 'not found';\n }\n}\n\nasync function checkForUpgrades(): Promise<void> {\n log.blank();\n log.title('Upgrade Check');\n\n const packageJsonPath = path.join(process.cwd(), 'package.json');\n if (!fs.pathExistsSync(packageJsonPath)) {\n log.warn('No package.json found — skipping upgrade check.');\n return;\n }\n\n const packageJson = fs.readJsonSync(packageJsonPath) as Record<string, unknown>;\n const deps = (packageJson.dependencies ?? {}) as Record<string, string>;\n const devDeps = (packageJson.devDependencies ?? {}) as Record<string, string>;\n\n const currentRaw = deps['@mars-stack/core'] ?? devDeps['@mars-stack/core'];\n if (!currentRaw) {\n log.warn('@mars-stack/core not found in dependencies — skipping upgrade check.');\n return;\n }\n\n const currentVersion = currentRaw.replace(/^[\\^~]/, '');\n log.info(`Current @mars-stack/core version: ${currentVersion}`);\n\n log.step('Fetching latest version from npm...');\n\n let latestVersion: string;\n try {\n const response = await fetch('https://registry.npmjs.org/@mars-stack/core/latest');\n if (!response.ok) {\n log.warn(`npm registry returned status ${response.status}. Skipping upgrade check.`);\n return;\n }\n const data = (await response.json()) as NpmRegistryResponse;\n latestVersion = data.version;\n } catch (error: unknown) {\n const message = error instanceof Error ? error.message : 'Unknown error';\n log.warn(`Could not reach npm registry: ${message}`);\n log.warn('Check your network connection and try again.');\n return;\n }\n\n log.info(`Latest @mars-stack/core version: ${latestVersion}`);\n log.blank();\n\n if (currentVersion === latestVersion) {\n log.success('@mars-stack/core is up to date.');\n } else {\n log.warn(`Upgrade available: ${currentVersion} → ${latestVersion}`);\n log.info('Changelog: https://github.com/greaveselliott/mars/blob/main/CHANGELOG.md');\n log.info('Run `mars upgrade` to update all Mars packages.');\n }\n}\n\nexport async function doctorCommand(options?: DoctorOptions): Promise<void> {\n log.title('MARS Doctor');\n log.info('Checking your development environment...\\n');\n\n const checks: Check[] = [\n {\n name: 'Node.js (>=20)',\n check: () => {\n const version = process.version;\n const major = parseInt(version.slice(1).split('.')[0], 10);\n return major >= 20 ? `${version}` : `${version} (requires >=20)`;\n },\n },\n {\n name: 'Yarn',\n check: () => (commandExists('yarn') ? getVersion('yarn') : false),\n },\n {\n name: 'Docker',\n check: () => (commandExists('docker') ? getVersion('docker') : false),\n },\n {\n name: 'Git',\n check: () => (commandExists('git') ? getVersion('git') : false),\n },\n {\n name: 'package.json exists',\n check: () => fs.pathExistsSync(path.join(process.cwd(), 'package.json')),\n },\n {\n name: '.env file exists',\n check: () => fs.pathExistsSync(path.join(process.cwd(), '.env')),\n },\n {\n name: 'Prisma schema exists',\n check: () =>\n fs.pathExistsSync(path.join(process.cwd(), 'prisma', 'schema')) ||\n fs.pathExistsSync(path.join(process.cwd(), 'prisma', 'schema.prisma')),\n },\n {\n name: 'node_modules installed',\n check: () => fs.pathExistsSync(path.join(process.cwd(), 'node_modules')),\n },\n {\n name: 'DATABASE_URL set',\n check: () => {\n try {\n const envContent = fs.readFileSync(path.join(process.cwd(), '.env'), 'utf-8');\n const match = envContent.match(/^DATABASE_URL=(.+)$/m);\n return match ? match[1] !== '' : false;\n } catch {\n return false;\n }\n },\n },\n {\n name: 'JWT_SECRET set',\n check: () => {\n try {\n const envContent = fs.readFileSync(path.join(process.cwd(), '.env'), 'utf-8');\n const match = envContent.match(/^JWT_SECRET=(.+)$/m);\n if (!match || !match[1]) return false;\n return match[1].length >= 32\n ? true\n : 'set but too short (need >=32 chars)';\n } catch {\n return false;\n }\n },\n },\n ];\n\n let passed = 0;\n let failed = 0;\n let warned = 0;\n\n for (const { name, check } of checks) {\n const result = check();\n\n if (result === true) {\n log.success(name);\n passed++;\n } else if (result === false) {\n log.error(name);\n failed++;\n } else if (typeof result === 'string' && !result.includes('requires') && !result.includes('too short')) {\n log.success(`${name}: ${result}`);\n passed++;\n } else {\n log.warn(`${name}: ${result}`);\n warned++;\n }\n }\n\n log.blank();\n log.info(`${passed} passed, ${warned} warnings, ${failed} failed`);\n\n if (failed > 0) {\n log.blank();\n log.warn('Fix the issues above before running your project.');\n } else {\n log.blank();\n log.success('Your environment looks good!');\n }\n\n if (options?.upgradeCheck) {\n await checkForUpgrades();\n }\n}\n","import fs from 'fs-extra';\nimport path from 'node:path';\nimport pc from 'picocolors';\nimport { log } from '../utils/logger.js';\nimport { appendToDbSchema, updateQualityScore } from '../utils/doc-updater.js';\nimport { createRollbackContext } from '../utils/rollback.js';\nimport { trackEvent } from '../utils/telemetry.js';\n\nfunction ensureInProject(): string {\n const cwd = process.cwd();\n const configPath = path.join(cwd, 'src', 'config', 'app.config.ts');\n if (!fs.pathExistsSync(configPath)) {\n log.error('Not inside a MARS project. Run this command from the project root.');\n process.exit(1);\n }\n return cwd;\n}\n\nfunction toKebab(str: string): string {\n return str\n .replace(/([a-z])([A-Z])/g, '$1-$2')\n .replace(/[\\s_]+/g, '-')\n .toLowerCase();\n}\n\nfunction toPascal(str: string): string {\n return str\n .replace(/(^|[-_\\s])(\\w)/g, (_, _sep, c) => c.toUpperCase());\n}\n\nfunction toCamel(str: string): string {\n const pascal = toPascal(str);\n return pascal.charAt(0).toLowerCase() + pascal.slice(1);\n}\n\nfunction pluralize(word: string): string {\n if (word.endsWith('s') || word.endsWith('x') || word.endsWith('z') || word.endsWith('ch') || word.endsWith('sh')) {\n return word + 'es';\n }\n if (word.endsWith('y') && !/[aeiou]y$/i.test(word)) {\n return word.slice(0, -1) + 'ies';\n }\n return word + 's';\n}\n\nfunction stripBrackets(segment: string): string {\n return segment.replace(/[\\[\\]]/g, '');\n}\n\nexport async function addFeatureCommand(name: string): Promise<void> {\n const root = ensureInProject();\n const kebab = toKebab(name);\n const pascal = toPascal(name);\n const camel = toCamel(name);\n const featureDir = path.join(root, 'src', 'features', kebab);\n\n if (await fs.pathExists(featureDir)) {\n log.error(`Feature \"${kebab}\" already exists at src/features/${kebab}/`);\n return;\n }\n\n const files: Record<string, string> = {\n 'server/index.ts': `import 'server-only';\n\nimport { prisma } from '@/lib/prisma';\nimport type { Create${pascal}Input, Update${pascal}Input } from '../validation/schemas';\n\nexport async function findAll${pluralize(pascal)}ForUser(userId: string) {\n return prisma.${camel}.findMany({\n where: { userId },\n orderBy: { createdAt: 'desc' },\n });\n}\n\nexport async function find${pascal}ById(id: string) {\n return prisma.${camel}.findUnique({ where: { id } });\n}\n\nexport async function create${pascal}(userId: string, data: Create${pascal}Input) {\n return prisma.${camel}.create({\n data: { ...data, userId },\n });\n}\n\nexport async function update${pascal}(id: string, data: Update${pascal}Input) {\n return prisma.${camel}.update({ where: { id }, data });\n}\n\nexport async function delete${pascal}(id: string) {\n return prisma.${camel}.delete({ where: { id } });\n}\n`,\n 'validation/schemas.ts': `import { z } from 'zod';\n\nexport const ${camel}Schemas = {\n create: z.object({\n name: z.string().min(1, 'Name is required').max(100),\n }),\n update: z.object({\n name: z.string().min(1).max(100).optional(),\n }),\n};\n\nexport type Create${pascal}Input = z.infer<typeof ${camel}Schemas.create>;\nexport type Update${pascal}Input = z.infer<typeof ${camel}Schemas.update>;\n`,\n 'types.ts': `export interface ${pascal} {\n id: string;\n name: string;\n userId: string;\n createdAt: Date;\n updatedAt: Date;\n}\n`,\n 'components/.gitkeep': '',\n 'hooks/.gitkeep': '',\n };\n\n const ctx = createRollbackContext();\n\n try {\n ctx.trackCreatedFile(featureDir);\n\n let count = 0;\n for (const [filePath, content] of Object.entries(files)) {\n const fullPath = path.join(featureDir, filePath);\n await fs.ensureDir(path.dirname(fullPath));\n await fs.writeFile(fullPath, content);\n count++;\n }\n\n await ctx.commit();\n\n log.success(`Created feature ${pc.bold(kebab)} with ${count} files`);\n trackEvent('add', { type: 'feature' });\n log.blank();\n log.step(`Add a Prisma model: ${pc.dim(`mars add model ${pascal}`)}`);\n log.step(`Add API routes: ${pc.dim(`mars add page ${kebab} --protected`)}`);\n log.blank();\n\n updateQualityScore(root, pascal, 'D').catch(() => {});\n } catch (error) {\n await ctx.rollback();\n throw error;\n }\n}\n\nexport async function addPageCommand(routePath: string, options: { protected?: boolean }): Promise<void> {\n const root = ensureInProject();\n const cleanPath = routePath.startsWith('/') ? routePath.slice(1) : routePath;\n const group = options.protected ? '(protected)' : '(public)';\n const pageDir = path.join(root, 'src', 'app', group, cleanPath);\n\n if (await fs.pathExists(path.join(pageDir, 'page.tsx'))) {\n log.error(`Page already exists at src/app/${group}/${cleanPath}/page.tsx`);\n return;\n }\n\n const lastSegment = cleanPath.split('/').pop() || 'page';\n const pageName = toPascal(stripBrackets(lastSegment));\n\n const pageContent = `import { Card, CardHeader, CardBody } from '@mars-stack/ui';\nimport type { Metadata } from 'next';\n\nexport const metadata: Metadata = {\n title: '${pageName}',\n};\n\nexport default function ${pageName}Page() {\n return (\n <div className=\"mx-auto max-w-4xl space-y-6 p-6\">\n <div>\n <h1 className=\"text-4xl font-bold text-text-primary mb-4\">${pageName}</h1>\n <p className=\"text-base text-text-secondary mb-4\">\n Description goes here.\n </p>\n </div>\n\n <Card>\n <CardHeader>\n <h2 className=\"text-lg font-semibold text-text-primary\">${pageName}</h2>\n </CardHeader>\n <CardBody>\n {/* Content */}\n </CardBody>\n </Card>\n </div>\n );\n}\n`;\n\n const loadingContent = `import { Spinner } from '@mars-stack/ui';\n\nexport default function Loading() {\n return (\n <div className=\"flex min-h-[50vh] items-center justify-center\">\n <Spinner size=\"lg\" />\n </div>\n );\n}\n`;\n\n const ctx = createRollbackContext();\n\n try {\n ctx.trackCreatedFile(pageDir);\n await fs.ensureDir(pageDir);\n await fs.writeFile(path.join(pageDir, 'page.tsx'), pageContent);\n await fs.writeFile(path.join(pageDir, 'loading.tsx'), loadingContent);\n\n await ctx.commit();\n\n log.success(`Created page at ${pc.bold(`src/app/${group}/${cleanPath}/`)}`);\n trackEvent('add', { type: 'page' });\n log.step(`page.tsx`);\n log.step(`loading.tsx`);\n log.blank();\n } catch (error) {\n await ctx.rollback();\n throw error;\n }\n}\n\nexport async function addModelCommand(name: string): Promise<void> {\n const root = ensureInProject();\n const pascal = toPascal(name);\n const camel = toCamel(name);\n const kebab = toKebab(name);\n const schemaDir = path.join(root, 'prisma', 'schema');\n const schemaFile = path.join(schemaDir, `${kebab}.prisma`);\n\n if (await fs.pathExists(schemaFile)) {\n log.error(`Schema file already exists: prisma/schema/${kebab}.prisma`);\n return;\n }\n\n const content = `model ${pascal} {\n id String @id @default(cuid())\n name String\n userId String\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@index([userId])\n}\n`;\n\n const ctx = createRollbackContext();\n\n try {\n ctx.trackCreatedFile(schemaFile);\n await fs.ensureDir(schemaDir);\n await fs.writeFile(schemaFile, content);\n\n await ctx.commit();\n\n log.success(`Created model ${pc.bold(pascal)} at prisma/schema/${kebab}.prisma`);\n trackEvent('add', { type: 'model' });\n log.blank();\n log.warn(`Remember to:`);\n log.step(`Add the reverse relation to the User model in prisma/schema/auth.prisma`);\n log.step(`Run ${pc.dim('yarn db:push')} to sync the database`);\n log.blank();\n\n const defaultFields = ['id', 'name', 'userId', 'createdAt', 'updatedAt'];\n appendToDbSchema(root, pascal, defaultFields).catch(() => {});\n } catch (error) {\n await ctx.rollback();\n throw error;\n }\n}\n\nexport async function addEmailCommand(name: string): Promise<void> {\n const root = ensureInProject();\n const kebab = toKebab(name);\n const pascal = toPascal(name);\n const camel = toCamel(name);\n const templatesDir = path.join(root, 'src', 'lib', 'core', 'email', 'templates');\n const filePath = path.join(templatesDir, `${kebab}-email.ts`);\n\n if (await fs.pathExists(filePath)) {\n log.error(`Email template already exists: src/lib/core/email/templates/${kebab}-email.ts`);\n return;\n }\n\n const functionName = `${camel}EmailHtml`;\n\n const content = `import { emailLayout, emailButton } from './base-layout';\n\ninterface ${pascal}EmailOptions {\n appName: string;\n actionUrl: string;\n userName?: string;\n}\n\nexport function ${functionName}({ appName, actionUrl, userName }: ${pascal}EmailOptions): { html: string; text: string } {\n const greeting = userName ? \\`Hi \\${userName},\\` : 'Hi there,';\n\n const content = \\`\n <h1 style=\"margin: 0 0 16px 0; font-size: 24px; font-weight: 700; color: #111827;\">${pascal}</h1>\n <p style=\"margin: 0 0 8px 0;\">\\${greeting}</p>\n <p style=\"margin: 0 0 8px 0;\">Add your email content here.</p>\n \\${emailButton(actionUrl, 'Take Action')}\n <p style=\"margin: 0; font-size: 14px; color: #6b7280;\">If the button doesn't work, copy and paste this link into your browser:</p>\n <p style=\"margin: 0; font-size: 14px; word-break: break-all; color: #6366f1;\">\\${actionUrl}</p>\\`;\n\n const html = emailLayout({\n appName,\n previewText: \\`${pascal} notification from \\${appName}\\`,\n content,\n });\n\n const text = [\n '${pascal}',\n '',\n \\`\\${greeting}\\`,\n '',\n 'Add your email content here.',\n '',\n actionUrl,\n ].join('\\\\n');\n\n return { html, text };\n}\n`;\n\n const ctx = createRollbackContext();\n const indexPath = path.join(templatesDir, 'index.ts');\n\n try {\n ctx.trackCreatedFile(filePath);\n if (await fs.pathExists(indexPath)) {\n await ctx.trackModifiedFile(indexPath);\n } else {\n ctx.trackCreatedFile(indexPath);\n }\n\n await fs.ensureDir(templatesDir);\n await fs.writeFile(filePath, content);\n\n const exportLine = `export { ${functionName} } from './${kebab}-email';\\n`;\n\n if (await fs.pathExists(indexPath)) {\n const existing = await fs.readFile(indexPath, 'utf-8');\n if (!existing.includes(functionName)) {\n await fs.appendFile(indexPath, exportLine);\n }\n } else {\n await fs.writeFile(indexPath, exportLine);\n }\n\n await ctx.commit();\n\n log.success(`Created email template ${pc.bold(kebab)} at src/lib/core/email/templates/${kebab}-email.ts`);\n trackEvent('add', { type: 'email' });\n log.blank();\n log.step(`Exported ${pc.dim(functionName)} from templates/index.ts`);\n log.step(`Edit the template and customize the content, subject, and preview text`);\n log.blank();\n } catch (error) {\n await ctx.rollback();\n throw error;\n }\n}\n\nexport async function addComponentCommand(name: string, options: { type?: string }): Promise<void> {\n const root = ensureInProject();\n const pascal = toPascal(name);\n const type = options.type || 'primitive';\n const validTypes = ['primitive', 'pattern'];\n\n if (!validTypes.includes(type)) {\n log.error(`Invalid type \"${type}\". Use: ${validTypes.join(', ')}`);\n return;\n }\n\n const dir = type === 'primitive'\n ? path.join(root, 'src', 'components', 'primitives')\n : path.join(root, 'src', 'components', 'patterns');\n\n await fs.ensureDir(dir);\n const filePath = path.join(dir, `${pascal}.tsx`);\n\n if (await fs.pathExists(filePath)) {\n log.error(`Component already exists: ${pascal}.tsx`);\n return;\n }\n\n const content = type === 'primitive'\n ? `import { clsx } from 'clsx';\nimport { type ComponentPropsWithoutRef, forwardRef } from 'react';\n\nexport interface ${pascal}Props extends ComponentPropsWithoutRef<'div'> {\n variant?: 'default' | 'outlined';\n}\n\nexport const ${pascal} = forwardRef<HTMLDivElement, ${pascal}Props>(\n ({ variant = 'default', className, children, ...rest }, ref) => {\n return (\n <div\n ref={ref}\n className={clsx(\n 'rounded-lg',\n variant === 'default' && 'bg-surface-card text-text-primary',\n variant === 'outlined' && 'border border-border-default text-text-primary',\n className,\n )}\n {...rest}\n >\n {children}\n </div>\n );\n },\n);\n\n${pascal}.displayName = '${pascal}';\n`\n : `import { clsx } from 'clsx';\n\nexport interface ${pascal}Props {\n children: React.ReactNode;\n className?: string;\n}\n\nexport function ${pascal}({ children, className }: ${pascal}Props) {\n return (\n <div className={clsx('', className)}>\n {children}\n </div>\n );\n}\n`;\n\n const ctx = createRollbackContext();\n\n try {\n ctx.trackCreatedFile(filePath);\n await fs.writeFile(filePath, content);\n\n await ctx.commit();\n\n log.success(`Created ${type} component ${pc.bold(pascal)} at ${path.relative(root, filePath)}`);\n trackEvent('add', { type: 'component', componentType: type });\n log.blank();\n log.warn(`Remember to add the export to the barrel file:`);\n log.step(`src/components/${type === 'primitive' ? 'primitives' : 'patterns'}/index.ts`);\n log.blank();\n } catch (error) {\n await ctx.rollback();\n throw error;\n }\n}\n","import fs from 'fs-extra';\nimport path from 'node:path';\n\nexport async function appendToApiRoutes(\n projectDir: string,\n routePath: string,\n method: string,\n authType: string,\n): Promise<void> {\n const filePath = path.join(projectDir, 'docs', 'generated', 'api-routes.md');\n if (!(await fs.pathExists(filePath))) return;\n\n const line = `| \\`${method}\\` | \\`${routePath}\\` | ${authType} |\\n`;\n await fs.appendFile(filePath, line);\n}\n\nexport async function appendToDbSchema(\n projectDir: string,\n modelName: string,\n fields: string[],\n): Promise<void> {\n const filePath = path.join(projectDir, 'docs', 'generated', 'db-schema.md');\n if (!(await fs.pathExists(filePath))) return;\n\n const entry = [\n '',\n `### ${modelName}`,\n '',\n '| Field | Type |',\n '|-------|------|',\n ...fields.map((f) => `| ${f} | |`),\n '',\n ].join('\\n');\n\n await fs.appendFile(filePath, entry);\n}\n\nexport async function updateQualityScore(\n projectDir: string,\n domain: string,\n grade: string,\n): Promise<void> {\n const filePath = path.join(projectDir, 'docs', 'QUALITY_SCORE.md');\n if (!(await fs.pathExists(filePath))) return;\n\n const content = await fs.readFile(filePath, 'utf-8');\n const pattern = new RegExp(`^\\\\|\\\\s*${escapeRegex(domain)}\\\\s*\\\\|`, 'm');\n\n if (pattern.test(content)) {\n const updated = content.replace(pattern, (match) => {\n const parts = match.split('|').map((s) => s.trim());\n parts[2] = ` ${grade} `;\n return parts.join('|');\n });\n await fs.writeFile(filePath, updated);\n } else {\n const row = `| ${domain} | ${grade} | |\\n`;\n await fs.appendFile(filePath, row);\n }\n}\n\nfunction escapeRegex(str: string): string {\n return str.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n","import { execSync } from 'node:child_process';\nimport fs from 'fs-extra';\nimport path from 'node:path';\nimport pc from 'picocolors';\nimport prompts from 'prompts';\nimport { log } from '../utils/logger.js';\n\nfunction ensureInProject(): string {\n const cwd = process.cwd();\n const configPath = path.join(cwd, 'src', 'config', 'app.config.ts');\n if (!fs.pathExistsSync(configPath)) {\n log.error('Not inside a MARS project. Run this command from the project root.');\n process.exit(1);\n }\n return cwd;\n}\n\nconst PROVIDER_DEPENDENCIES: Record<string, string[]> = {\n 'email:sendgrid': ['@sendgrid/mail'],\n 'email:resend': ['resend'],\n 'payments:stripe': ['stripe'],\n 'storage:vercel': ['@vercel/blob'],\n 'storage:s3': ['@aws-sdk/client-s3', '@aws-sdk/s3-request-presigner'],\n};\n\nfunction updateAppConfig(\n projectDir: string,\n serviceKey: string,\n provider: string,\n featureKey?: string,\n): void {\n const configPath = path.join(projectDir, 'src', 'config', 'app.config.ts');\n let content = fs.readFileSync(configPath, 'utf-8');\n\n if (serviceKey === 'auth') {\n const boolValue = provider === 'google' ? 'true' : 'false';\n const featureRegex = new RegExp(`(googleOAuth\\\\s*:\\\\s*)(?:true|false)`);\n content = content.replace(featureRegex, `$1${boolValue}`);\n } else {\n const providerRegex = new RegExp(\n `(${serviceKey}\\\\s*:\\\\s*\\\\{[^}]*provider\\\\s*:\\\\s*)(['\"])[^'\"]*\\\\2`,\n );\n content = content.replace(providerRegex, `$1$2${provider}$2`);\n\n if (featureKey) {\n const featureRegex = new RegExp(`(${featureKey}\\\\s*:\\\\s*)(?:true|false)`);\n content = content.replace(featureRegex, `$1true`);\n }\n }\n\n fs.writeFileSync(configPath, content);\n}\n\nfunction detectPackageManager(projectDir: string): 'yarn' | 'npm' {\n if (fs.existsSync(path.join(projectDir, 'yarn.lock'))) return 'yarn';\n return 'npm';\n}\n\nfunction installDependencies(projectDir: string, deps: string[]): void {\n if (deps.length === 0) return;\n\n const pm = detectPackageManager(projectDir);\n const cmd = pm === 'yarn'\n ? `yarn add ${deps.join(' ')}`\n : `npm install ${deps.join(' ')}`;\n\n execSync(cmd, { cwd: projectDir, stdio: 'pipe' });\n}\n\nconst SERVICE_CONFIGS: Record<string, {\n providers: Array<{ value: string; title: string; envVars: string[] }>;\n configKey: string;\n featureKey?: string;\n}> = {\n email: {\n configKey: 'email',\n providers: [\n { value: 'console', title: 'Console (development only)', envVars: [] },\n { value: 'sendgrid', title: 'SendGrid', envVars: ['SENDGRID_API_KEY', 'SENDGRID_FROM_EMAIL'] },\n { value: 'resend', title: 'Resend', envVars: ['RESEND_API_KEY', 'RESEND_FROM_EMAIL'] },\n ],\n },\n payments: {\n configKey: 'payments',\n featureKey: 'billing',\n providers: [\n { value: 'none', title: 'None', envVars: [] },\n { value: 'stripe', title: 'Stripe', envVars: ['STRIPE_SECRET_KEY', 'STRIPE_WEBHOOK_SECRET', 'NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY'] },\n ],\n },\n storage: {\n configKey: 'storage',\n featureKey: 'fileUpload',\n providers: [\n { value: 'local', title: 'Local filesystem', envVars: [] },\n { value: 'vercel', title: 'Vercel Blob', envVars: ['BLOB_READ_WRITE_TOKEN'] },\n { value: 's3', title: 'AWS S3', envVars: ['AWS_ACCESS_KEY_ID', 'AWS_SECRET_ACCESS_KEY', 'AWS_REGION', 'S3_BUCKET_NAME'] },\n ],\n },\n analytics: {\n configKey: 'analytics',\n featureKey: 'analytics',\n providers: [\n { value: 'none', title: 'None', envVars: [] },\n { value: 'vercel', title: 'Vercel Analytics', envVars: [] },\n { value: 'posthog', title: 'PostHog', envVars: ['NEXT_PUBLIC_POSTHOG_KEY', 'NEXT_PUBLIC_POSTHOG_HOST'] },\n { value: 'google', title: 'Google Analytics', envVars: ['NEXT_PUBLIC_GA_MEASUREMENT_ID'] },\n ],\n },\n monitoring: {\n configKey: 'monitoring',\n featureKey: 'sentry',\n providers: [\n { value: 'none', title: 'None', envVars: [] },\n { value: 'sentry', title: 'Sentry', envVars: ['SENTRY_DSN', 'SENTRY_AUTH_TOKEN'] },\n ],\n },\n auth: {\n configKey: 'auth',\n featureKey: 'googleOAuth',\n providers: [\n { value: 'credentials', title: 'Email + Password only', envVars: [] },\n { value: 'google', title: 'Add Google OAuth', envVars: ['GOOGLE_CLIENT_ID', 'GOOGLE_CLIENT_SECRET'] },\n ],\n },\n};\n\nexport async function configureCommand(service?: string): Promise<void> {\n const root = ensureInProject();\n\n let selectedService = service;\n\n if (!selectedService) {\n const { chosen } = await prompts(\n {\n type: 'select',\n name: 'chosen',\n message: 'Which service do you want to configure?',\n choices: Object.entries(SERVICE_CONFIGS).map(([key]) => ({\n title: key.charAt(0).toUpperCase() + key.slice(1),\n value: key,\n description: `Configure ${key} provider`,\n })),\n },\n { onCancel: () => process.exit(0) },\n );\n selectedService = chosen;\n }\n\n const serviceConfig = SERVICE_CONFIGS[selectedService as string];\n if (!serviceConfig) {\n log.error(`Unknown service \"${selectedService}\". Available: ${Object.keys(SERVICE_CONFIGS).join(', ')}`);\n return;\n }\n\n const { provider } = await prompts(\n {\n type: 'select',\n name: 'provider',\n message: `Choose ${selectedService} provider`,\n choices: serviceConfig.providers.map((p) => ({\n title: p.title,\n value: p.value,\n })),\n },\n { onCancel: () => process.exit(0) },\n );\n\n const selectedProvider = serviceConfig.providers.find((p) => p.value === provider);\n if (!selectedProvider) return;\n\n log.blank();\n\n // 1. Update app.config.ts\n try {\n updateAppConfig(root, serviceConfig.configKey, provider, serviceConfig.featureKey);\n log.success(`Updated ${pc.dim('app.config.ts')} → ${pc.bold(`${serviceConfig.configKey}.provider = '${provider}'`)}`);\n } catch (error: unknown) {\n const message = error instanceof Error ? error.message : String(error);\n log.warn(`Could not update app.config.ts automatically: ${message}`);\n log.step(`Manually set ${pc.bold(`services.${serviceConfig.configKey}.provider`)} to ${pc.bold(`'${provider}'`)} in ${pc.dim('src/config/app.config.ts')}`);\n }\n\n // 2. Write .env placeholders\n if (selectedProvider.envVars.length > 0) {\n const envPath = path.join(root, '.env');\n if (await fs.pathExists(envPath)) {\n const envContent = await fs.readFile(envPath, 'utf-8');\n const missingVars = selectedProvider.envVars.filter(\n (v) => !envContent.includes(v),\n );\n\n if (missingVars.length > 0) {\n const additions = missingVars.map((v) => `${v}=\"\"`).join('\\n');\n await fs.appendFile(envPath, `\\n# ${selectedService} (${provider})\\n${additions}\\n`);\n log.success(`Added ${missingVars.length} env placeholder(s) to ${pc.dim('.env')}`);\n }\n }\n }\n\n // 3. Install SDK dependencies\n const depKey = `${selectedService}:${provider}`;\n const deps = PROVIDER_DEPENDENCIES[depKey];\n if (deps && deps.length > 0) {\n const pm = detectPackageManager(root);\n log.step(`Installing ${pc.bold(deps.join(', '))} via ${pm}…`);\n try {\n installDependencies(root, deps);\n log.success(`Installed ${deps.length} package(s)`);\n } catch (error: unknown) {\n const message = error instanceof Error ? error.message : String(error);\n log.warn(`Package install failed: ${message}`);\n log.step(`Run ${pc.bold(`${pm} add ${deps.join(' ')}`)} manually`);\n }\n }\n\n log.blank();\n log.success(`Configured ${pc.bold(selectedService as string)} → ${pc.bold(selectedProvider.title)}`);\n log.blank();\n}\n","import fs from 'fs-extra';\nimport path from 'node:path';\nimport { execSync } from 'node:child_process';\nimport pc from 'picocolors';\nimport prompts from 'prompts';\nimport { log } from '../utils/logger.js';\nimport { trackEvent } from '../utils/telemetry.js';\n\nfunction ensureInProject(): string {\n const cwd = process.cwd();\n const configPath = path.join(cwd, 'src', 'config', 'app.config.ts');\n if (!fs.pathExistsSync(configPath)) {\n log.error('Not inside a MARS project. Run this command from the project root.');\n process.exit(1);\n }\n return cwd;\n}\n\nfunction commandExists(cmd: string): boolean {\n try {\n execSync(`which ${cmd}`, { stdio: 'pipe' });\n return true;\n } catch {\n return false;\n }\n}\n\nfunction run(cmd: string, cwd: string): string {\n try {\n return execSync(cmd, { cwd, stdio: 'pipe', encoding: 'utf-8' }).trim();\n } catch (error) {\n const err = error as { stderr?: string; message?: string };\n throw new Error(err.stderr || err.message || 'Command failed');\n }\n}\n\nexport async function deployCommand(): Promise<void> {\n const root = ensureInProject();\n\n log.title('Mars Deploy');\n\n // 1. Check vercel CLI\n if (!commandExists('vercel')) {\n log.warn('Vercel CLI not found.');\n const { install } = await prompts({\n type: 'confirm',\n name: 'install',\n message: 'Install Vercel CLI globally?',\n initial: true,\n });\n\n if (install) {\n log.step('Installing Vercel CLI...');\n try {\n execSync('npm i -g vercel', { stdio: 'inherit' });\n log.success('Vercel CLI installed');\n } catch {\n log.error('Failed to install Vercel CLI. Install manually: npm i -g vercel');\n return;\n }\n } else {\n log.error('Vercel CLI is required for deployment.');\n return;\n }\n }\n\n // 2. Link project\n const vercelDir = path.join(root, '.vercel');\n if (!fs.existsSync(vercelDir)) {\n log.step('Linking project to Vercel...');\n try {\n execSync('vercel link', { cwd: root, stdio: 'inherit' });\n } catch {\n log.error('Failed to link project. Make sure you are logged into Vercel.');\n return;\n }\n } else {\n log.success('Project already linked to Vercel');\n }\n\n // 3. Detect configured services from app.config.ts\n log.blank();\n log.title('Environment Variables');\n log.info('The following env vars are required for your configured services:');\n log.blank();\n\n const requiredVars = ['JWT_SECRET', 'DATABASE_URL'];\n log.step(`Core: ${pc.dim(requiredVars.join(', '))}`);\n\n const configPath = path.join(root, 'src', 'config', 'app.config.ts');\n const configContent = await fs.readFile(configPath, 'utf-8');\n\n if (configContent.includes(\"email: { provider: 'sendgrid'\")) {\n log.step(`Email (SendGrid): ${pc.dim('SENDGRID_API_KEY, SENDGRID_FROM_EMAIL')}`);\n } else if (configContent.includes(\"email: { provider: 'resend'\")) {\n log.step(`Email (Resend): ${pc.dim('RESEND_API_KEY, RESEND_FROM_EMAIL')}`);\n }\n\n if (configContent.includes(\"payments: { provider: 'stripe'\")) {\n log.step(`Payments (Stripe): ${pc.dim('STRIPE_SECRET_KEY, NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY, STRIPE_WEBHOOK_SECRET')}`);\n }\n\n if (configContent.includes(\"storage: { provider: 'vercel'\")) {\n log.step(`Storage (Vercel Blob): ${pc.dim('BLOB_READ_WRITE_TOKEN')}`);\n }\n\n log.blank();\n log.info('Set these via the Vercel dashboard or:');\n log.step(`${pc.dim('vercel env add <NAME>')}`);\n\n // 4. Deploy\n log.blank();\n const { deploy } = await prompts({\n type: 'select',\n name: 'deploy',\n message: 'How would you like to deploy?',\n choices: [\n { title: 'Production deploy', value: 'prod' },\n { title: 'Preview deploy', value: 'preview' },\n { title: 'Setup Git integration (auto-deploy on push)', value: 'git' },\n { title: 'Skip deployment for now', value: 'skip' },\n ],\n });\n\n if (deploy === 'skip') {\n log.info('Skipping deployment. Run `mars deploy` again when ready.');\n return;\n }\n\n if (deploy === 'git') {\n log.info('To set up Git integration:');\n log.step('1. Push your code to GitHub/GitLab/Bitbucket');\n log.step('2. Visit https://vercel.com/import to import your repo');\n log.step('3. Vercel will auto-deploy on every push to main');\n return;\n }\n\n const deployCmd = deploy === 'prod' ? 'vercel deploy --prod' : 'vercel deploy';\n log.step(`Running: ${pc.dim(deployCmd)}`);\n log.blank();\n\n try {\n execSync(deployCmd, { cwd: root, stdio: 'inherit' });\n trackEvent('deploy');\n log.blank();\n log.success('Deployment complete!');\n } catch {\n log.error('Deployment failed. Check the output above for details.');\n return;\n }\n\n // 5. Post-deploy check\n log.blank();\n log.title('Post-Deploy Checklist');\n log.step('Verify env vars are set in the Vercel dashboard');\n log.step('Run database migrations: vercel env pull && yarn db:push');\n log.step('Seed the database if needed: yarn db:seed');\n log.step('Test the deployed app: visit the URL above');\n log.blank();\n}\n","import fs from 'fs-extra';\nimport path from 'node:path';\nimport { execSync } from 'node:child_process';\nimport { Command } from 'commander';\nimport { log } from '../utils/logger.js';\n\nconst MARS_PACKAGES = ['@mars-stack/core', '@mars-stack/ui'] as const;\n\nconst CHANGELOG_URL = 'https://github.com/greaveselliott/mars/blob/main/CHANGELOG.md';\n\ninterface NpmRegistryResponse {\n version: string;\n name: string;\n}\n\ninterface PackageVersionInfo {\n name: string;\n current: string | null;\n latest: string | null;\n updateAvailable: boolean;\n}\n\nasync function fetchLatestVersion(packageName: string): Promise<string | null> {\n try {\n const response = await fetch(`https://registry.npmjs.org/${packageName}/latest`);\n if (!response.ok) {\n return null;\n }\n const data = (await response.json()) as NpmRegistryResponse;\n return data.version;\n } catch {\n return null;\n }\n}\n\nfunction readCurrentVersion(\n packageJson: Record<string, unknown>,\n packageName: string,\n): string | null {\n const deps = packageJson.dependencies as Record<string, string> | undefined;\n const devDeps = packageJson.devDependencies as Record<string, string> | undefined;\n const version = deps?.[packageName] ?? devDeps?.[packageName] ?? null;\n return version ? version.replace(/^[\\^~]/, '') : null;\n}\n\nfunction detectPackageManager(projectDir: string): 'yarn' | 'npm' {\n if (fs.pathExistsSync(path.join(projectDir, 'yarn.lock'))) {\n return 'yarn';\n }\n return 'npm';\n}\n\nfunction getInstallCommand(pm: 'yarn' | 'npm'): string {\n return pm === 'yarn' ? 'yarn install' : 'npm install';\n}\n\nasync function gatherVersionInfo(\n packageJson: Record<string, unknown>,\n): Promise<PackageVersionInfo[]> {\n const results: PackageVersionInfo[] = [];\n\n for (const name of MARS_PACKAGES) {\n const current = readCurrentVersion(packageJson, name);\n const latest = await fetchLatestVersion(name);\n const updateAvailable =\n current !== null && latest !== null && current !== latest;\n\n results.push({ name, current, latest, updateAvailable });\n }\n\n return results;\n}\n\nfunction printVersionTable(versions: PackageVersionInfo[]): void {\n const colWidths = { name: 16, current: 12, latest: 12, status: 18 };\n const header = [\n 'Package'.padEnd(colWidths.name),\n 'Current'.padEnd(colWidths.current),\n 'Latest'.padEnd(colWidths.latest),\n 'Status'.padEnd(colWidths.status),\n ].join(' ');\n\n const divider = '-'.repeat(header.length);\n\n log.blank();\n log.info(header);\n log.info(divider);\n\n for (const info of versions) {\n const current = info.current ?? 'not installed';\n const latest = info.latest ?? 'unavailable';\n const status = info.current === null\n ? 'not installed'\n : info.latest === null\n ? 'registry error'\n : info.updateAvailable\n ? 'update available'\n : 'up to date';\n\n log.info(\n [\n info.name.padEnd(colWidths.name),\n current.padEnd(colWidths.current),\n latest.padEnd(colWidths.latest),\n status.padEnd(colWidths.status),\n ].join(' '),\n );\n }\n\n log.blank();\n}\n\nfunction updatePackageJsonVersions(\n packageJsonPath: string,\n packageJson: Record<string, unknown>,\n versions: PackageVersionInfo[],\n): string[] {\n const updated: string[] = [];\n const deps = (packageJson.dependencies ?? {}) as Record<string, string>;\n const devDeps = (packageJson.devDependencies ?? {}) as Record<string, string>;\n\n for (const info of versions) {\n if (!info.updateAvailable || info.latest === null) continue;\n\n if (deps[info.name] !== undefined) {\n const prefix = deps[info.name].match(/^[\\^~]/)?.[0] ?? '^';\n deps[info.name] = `${prefix}${info.latest}`;\n updated.push(`${info.name}: ${info.current} → ${info.latest}`);\n } else if (devDeps[info.name] !== undefined) {\n const prefix = devDeps[info.name].match(/^[\\^~]/)?.[0] ?? '^';\n devDeps[info.name] = `${prefix}${info.latest}`;\n updated.push(`${info.name}: ${info.current} → ${info.latest}`);\n }\n }\n\n if (updated.length > 0) {\n packageJson.dependencies = deps;\n packageJson.devDependencies = devDeps;\n fs.writeJsonSync(packageJsonPath, packageJson, { spaces: 2 });\n }\n\n return updated;\n}\n\nexport function upgradeCommand(program: Command): void {\n program\n .command('upgrade')\n .description(\n 'Upgrade @mars-stack/core, @mars-stack/ui, and @mars-stack/cli to the latest versions',\n )\n .option('--dry-run', 'Show what would be updated without making changes')\n .action(async (options: { dryRun?: boolean }) => {\n log.title('MARS Upgrade');\n\n const projectDir = process.cwd();\n const packageJsonPath = path.join(projectDir, 'package.json');\n\n if (!fs.pathExistsSync(packageJsonPath)) {\n log.error(\n 'No package.json found. Are you in a Mars project directory?',\n );\n process.exitCode = 1;\n return;\n }\n\n const packageJson = fs.readJsonSync(packageJsonPath) as Record<string, unknown>;\n\n const hasMarsPackage = MARS_PACKAGES.some(\n (name) =>\n readCurrentVersion(packageJson, name) !== null,\n );\n\n if (!hasMarsPackage) {\n log.error(\n 'No @mars-stack packages found in dependencies. This does not appear to be a Mars project.',\n );\n process.exitCode = 1;\n return;\n }\n\n log.step('Checking for updates...');\n\n const versions = await gatherVersionInfo(packageJson);\n const registryErrors = versions.filter(\n (v) => v.current !== null && v.latest === null,\n );\n\n if (registryErrors.length > 0) {\n log.warn(\n 'Could not reach the npm registry for some packages. Check your network connection.',\n );\n }\n\n printVersionTable(versions);\n\n const updatesAvailable = versions.some((v) => v.updateAvailable);\n\n if (!updatesAvailable) {\n log.success('All Mars packages are up to date.');\n return;\n }\n\n if (options.dryRun) {\n log.info('Dry run — no changes were made.');\n log.info(`Run ${`mars upgrade`} without --dry-run to apply updates.`);\n return;\n }\n\n log.step('Updating package.json...');\n const updated = updatePackageJsonVersions(\n packageJsonPath,\n packageJson,\n versions,\n );\n\n for (const change of updated) {\n log.success(change);\n }\n\n const pm = detectPackageManager(projectDir);\n const installCmd = getInstallCommand(pm);\n\n log.blank();\n log.step(`Running ${installCmd}...`);\n\n try {\n execSync(installCmd, {\n cwd: projectDir,\n stdio: 'inherit',\n });\n } catch {\n log.error(`${installCmd} failed. You may need to run it manually.`);\n process.exitCode = 1;\n return;\n }\n\n log.blank();\n log.step('Running mars doctor to verify...');\n\n try {\n execSync('npx mars doctor', {\n cwd: projectDir,\n stdio: 'inherit',\n });\n } catch {\n log.warn(\n 'mars doctor reported issues. Review the output above.',\n );\n }\n\n log.blank();\n log.title('Upgrade Summary');\n for (const change of updated) {\n log.success(change);\n }\n log.blank();\n log.info(`Changelog: ${CHANGELOG_URL}`);\n log.info(\n 'Review the changelog for any breaking changes or migration notes.',\n );\n });\n}\n"],"mappings":"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","names":["fs","path","fs","path","fs","path","fs","path","setConfigFlag","STAMP","GENERATOR_VERSION","fs","path","fs","path","types","schemas","serverLogic","componentIndex","setConfigFlag","GENERATOR_VERSION","STAMP","fs","path","types","setConfigFlag","STAMP","GENERATOR_VERSION","fs","path","types","componentIndex","setConfigFlag","STAMP","GENERATOR_VERSION","fs","path","prismaSchema","types","serverLogic","schemas","componentIndex","featureIndex","setConfigFlag","GENERATOR_VERSION","STAMP","fs","path","types","schemas","componentIndex","featureIndex","setConfigFlag","STAMP","GENERATOR_VERSION","fs","path","types","serverIndex","featureIndex","setConfigFlag","STAMP","GENERATOR_VERSION","fs","path","types","schemas","barrelExports","setConfigFlag","STAMP","GENERATOR_VERSION","fs","path","types","featureIndex","setConfigFlag","STAMP","GENERATOR_VERSION","fs","path","types","schemas","componentIndex","barrelExports","setConfigFlag","STAMP","GENERATOR_VERSION","fs","path","types","componentsIndex","barrelExports","setConfigFlag","STAMP","GENERATOR_VERSION","fs","path","types","serverIndex","componentsIndex","featureIndex","setConfigFlag","STAMP","GENERATOR_VERSION","fs","path","os","pc","prompts","prompts","prompts","prompts","fs","path","crypto","fs","path","fs","path","os","RC_PATH","path","os","fs","pc","prompts","fs","path","fs","path","pc","fs","path","path","fs","path","fs","pc","execSync","fs","path","pc","prompts","ensureInProject","fs","path","execSync","pc","prompts","ensureInProject","path","fs","commandExists","execSync","ensureInProject","commandExists","prompts","execSync","path","fs","pc","fs","path","execSync","detectPackageManager","program"]}
1
+ {"version":3,"sources":["../src/utils/logger.ts","../src/utils/rollback.ts","../src/utils/dependencies.ts","../src/generators/features/blog.ts","../src/utils/client-file-patch.ts","../src/generators/features/dark-mode.ts","../src/utils/prisma.ts","../src/generators/features/notifications.ts","../src/generators/features/analytics.ts","../src/generators/features/command-palette.ts","../src/generators/features/onboarding.ts","../src/generators/features/search.ts","../src/generators/features/realtime.ts","../src/generators/features/ai.ts","../src/generators/features/cookie-consent.ts","../src/generators/features/coming-soon.ts","../src/generators/features/sentry.ts","../src/generators/features/feature-flags.ts","../src/index.ts","../src/commands/create.ts","../src/utils/template.ts","../src/prompts/project-info.ts","../src/prompts/features.ts","../src/prompts/services.ts","../src/prompts/theme.ts","../src/generators/scaffold.ts","../src/generators/app-config.ts","../src/generators/env.ts","../src/generators/generate-selected.ts","../src/utils/telemetry.ts","../src/commands/doctor.ts","../src/commands/add.ts","../src/utils/doc-updater.ts","../src/commands/configure.ts","../src/commands/deploy.ts","../src/commands/upgrade.ts"],"sourcesContent":["import pc from 'picocolors';\n\nexport const log = {\n info: (msg: string) => console.log(pc.cyan('ℹ'), msg),\n success: (msg: string) => console.log(pc.green('✔'), msg),\n warn: (msg: string) => console.warn(pc.yellow('⚠'), msg),\n error: (msg: string) => console.error(pc.red('✖'), msg),\n step: (msg: string) => console.log(pc.blue('→'), msg),\n blank: () => console.log(),\n title: (msg: string) => {\n log.blank();\n console.log(pc.bold(pc.magenta(msg)));\n log.blank();\n },\n banner: () => {\n console.log(\n pc.bold(\n pc.magenta(`\n ╔══════════════════════════════════════════╗\n ║ MARS · Modular Architecture for ║\n ║ Rapid SaaS ║\n ╚══════════════════════════════════════════╝`),\n ),\n );\n log.blank();\n },\n};\n","import fs from 'fs-extra';\nimport path from 'node:path';\nimport os from 'node:os';\n\ninterface RollbackManifest {\n filesCreated: string[];\n filesModified: Array<{ path: string; backup: string }>;\n depsInstalled: string[];\n}\n\ninterface RollbackContext {\n trackCreatedFile(filePath: string): void;\n trackModifiedFile(filePath: string): Promise<void>;\n trackInstalledDep(depName: string): void;\n rollback(): Promise<void>;\n commit(): Promise<void>;\n}\n\nexport function createRollbackContext(): RollbackContext {\n const manifest: RollbackManifest = {\n filesCreated: [],\n filesModified: [],\n depsInstalled: [],\n };\n\n const backupDir = path.join(os.tmpdir(), `mars-rollback-${Date.now()}`);\n\n function trackCreatedFile(filePath: string): void {\n manifest.filesCreated.push(filePath);\n }\n\n async function trackModifiedFile(filePath: string): Promise<void> {\n if (!(await fs.pathExists(filePath))) return;\n\n await fs.ensureDir(backupDir);\n const backupPath = path.join(backupDir, `${manifest.filesModified.length}-${path.basename(filePath)}`);\n await fs.copy(filePath, backupPath);\n manifest.filesModified.push({ path: filePath, backup: backupPath });\n }\n\n function trackInstalledDep(depName: string): void {\n manifest.depsInstalled.push(depName);\n }\n\n async function rollback(): Promise<void> {\n for (const filePath of manifest.filesCreated.reverse()) {\n try {\n await fs.remove(filePath);\n } catch {\n // Best-effort cleanup\n }\n }\n\n for (const { path: originalPath, backup } of manifest.filesModified) {\n try {\n await fs.copy(backup, originalPath, { overwrite: true });\n } catch {\n // Best-effort restore\n }\n }\n\n await cleanupBackups();\n }\n\n async function commit(): Promise<void> {\n await cleanupBackups();\n }\n\n async function cleanupBackups(): Promise<void> {\n if (await fs.pathExists(backupDir)) {\n try {\n await fs.remove(backupDir);\n } catch {\n // Non-critical\n }\n }\n }\n\n return {\n trackCreatedFile,\n trackModifiedFile,\n trackInstalledDep,\n rollback,\n commit,\n };\n}\n","import fs from 'fs-extra';\nimport path from 'node:path';\n\nexport async function addDependencies(\n projectRoot: string,\n deps: Record<string, string>,\n dev = false,\n): Promise<void> {\n const pkgPath = path.join(projectRoot, 'package.json');\n if (!(await fs.pathExists(pkgPath))) return;\n\n const pkg = await fs.readJson(pkgPath);\n const key = dev ? 'devDependencies' : 'dependencies';\n pkg[key] = { ...pkg[key], ...deps };\n await fs.writeJson(pkgPath, pkg, { spaces: 2 });\n}\n","import fs from 'fs-extra';\nimport path from 'node:path';\nimport { log } from '../../utils/logger.js';\nimport { createRollbackContext } from '../../utils/rollback.js';\nimport { addDependencies } from '../../utils/dependencies.js';\n\nconst GENERATOR_VERSION = '0.1.0';\nconst STAMP = `// @mars-generated blog@${GENERATOR_VERSION}`;\n\nexport async function generateBlog(projectRoot: string): Promise<void> {\n const featureDir = path.join(projectRoot, 'src', 'features', 'blog');\n\n if (await fs.pathExists(featureDir)) {\n log.error('Blog feature already exists at src/features/blog/');\n return;\n }\n\n const ctx = createRollbackContext();\n\n try {\n const files: Record<string, string> = {\n 'src/features/blog/validation/schemas.ts': schemas(),\n 'src/features/blog/types.ts': types(),\n 'src/features/blog/server/index.ts': serverLogic(),\n 'src/features/blog/components/PostCard.tsx': postCard(),\n 'src/features/blog/components/PostHeader.tsx': postHeader(),\n 'src/features/blog/components/index.ts': componentIndex(),\n 'src/app/blog/page.tsx': blogListingPage(),\n 'src/app/blog/[slug]/page.tsx': blogPostPage(),\n 'src/app/feed.xml/route.ts': rssFeedRoute(),\n 'content/blog/getting-started.mdx': samplePostGettingStarted(),\n 'content/blog/welcome.mdx': samplePostWelcome(),\n };\n\n let count = 0;\n for (const [filePath, content] of Object.entries(files)) {\n const fullPath = path.join(projectRoot, filePath);\n ctx.trackCreatedFile(fullPath);\n await fs.ensureDir(path.dirname(fullPath));\n await fs.writeFile(fullPath, content);\n count++;\n }\n\n await addDependencies(projectRoot, {\n 'gray-matter': '^4.0.0',\n 'reading-time': '^1.5.0',\n '@mdx-js/mdx': '^3.0.0',\n '@mdx-js/react': '^3.0.0',\n 'remark-gfm': '^4.0.0',\n });\n await addDependencies(projectRoot, { '@types/mdx': '^2.0.0' }, true);\n await setConfigFlag(projectRoot, ctx);\n await ctx.commit();\n\n log.success(`Generated blog feature with ${count} files`);\n log.blank();\n log.step('src/features/blog/ — validation, types, server logic, components');\n log.step('src/app/blog/ — listing page and [slug] post page');\n log.step('src/app/feed.xml/ — RSS feed route');\n log.step('content/blog/ — sample MDX posts');\n log.blank();\n } catch (error) {\n await ctx.rollback();\n throw error;\n }\n}\n\nasync function setConfigFlag(projectRoot: string, ctx: { trackModifiedFile: (p: string) => Promise<void> }): Promise<void> {\n const configPath = path.join(projectRoot, 'src', 'config', 'app.config.ts');\n if (!(await fs.pathExists(configPath))) return;\n\n await ctx.trackModifiedFile(configPath);\n const content = await fs.readFile(configPath, 'utf-8');\n const updated = content.replace(/blog:\\s*false/, 'blog: true');\n await fs.writeFile(configPath, updated);\n}\n\nfunction schemas(): string {\n return `${STAMP}\nimport { z } from 'zod';\n\nexport const frontmatterSchema = z.object({\n title: z.string().min(1),\n description: z.string().min(1).max(160),\n date: z.string().refine((val) => !isNaN(Date.parse(val)), 'Invalid date'),\n author: z.string().default('Team'),\n tags: z.array(z.string()).default([]),\n image: z.string().optional(),\n published: z.boolean().default(true),\n});\n\nexport type Frontmatter = z.infer<typeof frontmatterSchema>;\n`;\n}\n\nfunction types(): string {\n return `${STAMP}\nimport type { Frontmatter } from './validation/schemas';\n\nexport interface BlogPost {\n slug: string;\n frontmatter: Frontmatter;\n content: string;\n readingTime: string;\n excerpt: string;\n}\n`;\n}\n\nfunction serverLogic(): string {\n return `${STAMP}\nimport 'server-only';\n\nimport fs from 'fs';\nimport path from 'path';\nimport matter from 'gray-matter';\nimport readingTime from 'reading-time';\nimport { frontmatterSchema } from '../validation/schemas';\nimport type { BlogPost } from '../types';\n\nconst CONTENT_DIR = path.join(process.cwd(), 'content', 'blog');\n\nexport function getAllPosts(): BlogPost[] {\n if (!fs.existsSync(CONTENT_DIR)) return [];\n\n const files = fs.readdirSync(CONTENT_DIR).filter((f) => f.endsWith('.mdx'));\n\n const posts = files\n .map((filename) => {\n const slug = filename.replace(/\\\\.mdx$/, '');\n const filePath = path.join(CONTENT_DIR, filename);\n const raw = fs.readFileSync(filePath, 'utf-8');\n const { data, content } = matter(raw);\n\n const parsed = frontmatterSchema.safeParse(data);\n if (!parsed.success) {\n console.warn(\\`Invalid frontmatter in \\${filename}:\\`, parsed.error.message);\n return null;\n }\n\n if (!parsed.data.published) return null;\n\n const stats = readingTime(content);\n const excerpt = content.replace(/^#+\\\\s.*$/gm, '').trim().slice(0, 200) + '...';\n\n return {\n slug,\n frontmatter: parsed.data,\n content,\n readingTime: stats.text,\n excerpt,\n };\n })\n .filter(Boolean) as BlogPost[];\n\n return posts.sort(\n (a, b) => new Date(b.frontmatter.date).getTime() - new Date(a.frontmatter.date).getTime(),\n );\n}\n\nexport function getPostBySlug(slug: string): BlogPost | null {\n const filePath = path.join(CONTENT_DIR, \\`\\${slug}.mdx\\`);\n\n if (!fs.existsSync(filePath)) return null;\n\n const raw = fs.readFileSync(filePath, 'utf-8');\n const { data, content } = matter(raw);\n\n const parsed = frontmatterSchema.safeParse(data);\n if (!parsed.success) return null;\n\n const stats = readingTime(content);\n const excerpt = content.replace(/^#+\\\\s.*$/gm, '').trim().slice(0, 200) + '...';\n\n return {\n slug,\n frontmatter: parsed.data,\n content,\n readingTime: stats.text,\n excerpt,\n };\n}\n\nexport function generateRSSFeed(posts: BlogPost[], siteUrl: string): string {\n const items = posts\n .map(\n (post) => \\`\n <item>\n <title><![CDATA[\\${post.frontmatter.title}]]></title>\n <link>\\${siteUrl}/blog/\\${post.slug}</link>\n <guid isPermaLink=\"true\">\\${siteUrl}/blog/\\${post.slug}</guid>\n <description><![CDATA[\\${post.frontmatter.description}]]></description>\n <pubDate>\\${new Date(post.frontmatter.date).toUTCString()}</pubDate>\n \\${post.frontmatter.tags.map((tag) => \\`<category>\\${tag}</category>\\`).join('\\\\n ')}\n </item>\\`,\n )\n .join('\\\\n');\n\n return \\`<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<rss version=\"2.0\" xmlns:atom=\"http://www.w3.org/2005/Atom\">\n <channel>\n <title>Blog</title>\n <link>\\${siteUrl}/blog</link>\n <description>Latest posts</description>\n <atom:link href=\"\\${siteUrl}/feed.xml\" rel=\"self\" type=\"application/rss+xml\" />\n \\${items}\n </channel>\n</rss>\\`;\n}\n`;\n}\n\nfunction postCard(): string {\n return `${STAMP}\nimport Link from 'next/link';\nimport type { BlogPost } from '../types';\n\nexport function PostCard({ post }: { post: BlogPost }) {\n const date = new Date(post.frontmatter.date).toLocaleDateString('en-US', {\n year: 'numeric',\n month: 'long',\n day: 'numeric',\n });\n\n return (\n <article className=\"group\">\n <Link href={\\`/blog/\\${post.slug}\\`} className=\"block\">\n <div className=\"rounded-2xl border border-border-default bg-surface-card p-6 transition-all hover:border-brand-primary hover:shadow-md\">\n <div className=\"flex items-center gap-3 text-sm text-text-muted\">\n <time dateTime={post.frontmatter.date}>{date}</time>\n <span aria-hidden=\"true\">&middot;</span>\n <span>{post.readingTime}</span>\n </div>\n <h2 className=\"mt-2 text-xl font-semibold text-text-primary group-hover:text-brand-primary\">\n {post.frontmatter.title}\n </h2>\n <p className=\"mt-2 text-text-secondary\">{post.frontmatter.description}</p>\n {post.frontmatter.tags.length > 0 && (\n <div className=\"mt-3 flex flex-wrap gap-2\">\n {post.frontmatter.tags.map((tag) => (\n <span\n key={tag}\n className=\"rounded-full bg-surface-background px-2.5 py-0.5 text-xs font-medium text-text-secondary\"\n >\n {tag}\n </span>\n ))}\n </div>\n )}\n </div>\n </Link>\n </article>\n );\n}\n`;\n}\n\nfunction postHeader(): string {\n return `${STAMP}\nimport Link from 'next/link';\n\ninterface PostHeaderProps {\n title: string;\n date: string;\n author: string;\n readingTime: string;\n tags: string[];\n}\n\nexport function PostHeader({ title, date, author, readingTime, tags }: PostHeaderProps) {\n const formattedDate = new Date(date).toLocaleDateString('en-US', {\n year: 'numeric',\n month: 'long',\n day: 'numeric',\n });\n\n return (\n <header>\n <Link\n href=\"/blog\"\n className=\"mb-8 inline-flex items-center gap-1.5 text-sm text-text-secondary transition-colors hover:text-text-primary\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" strokeWidth={1.5} stroke=\"currentColor\" className=\"size-4\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M15.75 19.5 8.25 12l7.5-7.5\" />\n </svg>\n Back to blog\n </Link>\n\n <h1 className=\"text-4xl font-bold tracking-tight text-text-primary sm:text-5xl\">\n {title}\n </h1>\n\n <div className=\"mt-4 flex flex-wrap items-center gap-3 text-sm text-text-muted\">\n <span>{author}</span>\n <span aria-hidden=\"true\">&middot;</span>\n <time dateTime={date}>{formattedDate}</time>\n <span aria-hidden=\"true\">&middot;</span>\n <span>{readingTime}</span>\n </div>\n\n {tags.length > 0 && (\n <div className=\"mt-4 flex flex-wrap gap-2\">\n {tags.map((tag) => (\n <span\n key={tag}\n className=\"rounded-full bg-surface-card px-3 py-1 text-xs font-medium text-text-secondary\"\n >\n {tag}\n </span>\n ))}\n </div>\n )}\n </header>\n );\n}\n`;\n}\n\nfunction componentIndex(): string {\n return `${STAMP}\nexport { PostCard } from './PostCard';\nexport { PostHeader } from './PostHeader';\n`;\n}\n\nfunction blogListingPage(): string {\n return `${STAMP}\nimport type { Metadata } from 'next';\nimport Link from 'next/link';\nimport { getAllPosts } from '@/features/blog/server';\nimport { PostCard } from '@/features/blog/components';\nimport { appConfig } from '@/config/app.config';\n\nexport const metadata: Metadata = {\n title: 'Blog',\n description: \\`Latest articles and updates from \\${appConfig.name}\\`,\n};\n\nexport default function BlogPage() {\n const posts = getAllPosts();\n\n return (\n <div className=\"flex min-h-screen flex-col bg-surface-background\">\n <nav className=\"border-b border-border-default bg-surface-card px-6 py-4\">\n <div className=\"mx-auto flex max-w-4xl items-center justify-between\">\n <Link href=\"/\" className=\"text-lg font-semibold text-text-primary\">\n {appConfig.name}\n </Link>\n <Link href=\"/blog\" className=\"text-sm font-medium text-brand-primary\">\n Blog\n </Link>\n </div>\n </nav>\n\n <main className=\"mx-auto w-full max-w-4xl flex-1 px-4 py-12\">\n <h1 className=\"text-4xl font-bold tracking-tight text-text-primary\">Blog</h1>\n <p className=\"mt-2 text-lg text-text-secondary\">Latest articles and updates</p>\n\n <div className=\"mt-10 space-y-6\">\n {posts.length === 0 && (\n <div className=\"rounded-2xl border border-border-default bg-surface-card p-12 text-center\">\n <p className=\"text-text-muted\">No posts yet. Add .mdx files to content/blog/.</p>\n </div>\n )}\n {posts.map((post) => (\n <PostCard key={post.slug} post={post} />\n ))}\n </div>\n </main>\n </div>\n );\n}\n`;\n}\n\nfunction blogPostPage(): string {\n return `${STAMP}\nimport type { Metadata } from 'next';\nimport { notFound } from 'next/navigation';\nimport { compile, run } from '@mdx-js/mdx';\nimport * as runtime from 'react/jsx-runtime';\nimport remarkGfm from 'remark-gfm';\nimport { getAllPosts, getPostBySlug } from '@/features/blog/server';\nimport { PostHeader } from '@/features/blog/components';\n\ninterface PostPageProps {\n params: Promise<{ slug: string }>;\n}\n\nexport async function generateStaticParams() {\n const posts = getAllPosts();\n return posts.map((post) => ({ slug: post.slug }));\n}\n\nexport async function generateMetadata({ params }: PostPageProps): Promise<Metadata> {\n const { slug } = await params;\n const post = getPostBySlug(slug);\n if (!post) return {};\n\n const siteUrl = process.env.APP_URL || 'http://localhost:3000';\n\n return {\n title: post.frontmatter.title,\n description: post.frontmatter.description,\n openGraph: {\n title: post.frontmatter.title,\n description: post.frontmatter.description,\n type: 'article',\n publishedTime: post.frontmatter.date,\n url: \\`\\${siteUrl}/blog/\\${slug}\\`,\n images: post.frontmatter.image ? [{ url: post.frontmatter.image }] : [],\n },\n };\n}\n\nexport default async function PostPage({ params }: PostPageProps) {\n const { slug } = await params;\n const post = getPostBySlug(slug);\n if (!post) notFound();\n\n const siteUrl = process.env.APP_URL || 'http://localhost:3000';\n\n const compiled = await compile(post.content, {\n outputFormat: 'function-body',\n remarkPlugins: [remarkGfm],\n });\n\n const { default: MDXContent } = await run(String(compiled), {\n ...runtime,\n baseUrl: import.meta.url,\n } as Parameters<typeof run>[1]);\n\n const jsonLd = {\n '@context': 'https://schema.org',\n '@type': 'BlogPosting',\n headline: post.frontmatter.title,\n description: post.frontmatter.description,\n datePublished: post.frontmatter.date,\n author: { '@type': 'Person', name: post.frontmatter.author },\n url: \\`\\${siteUrl}/blog/\\${slug}\\`,\n };\n\n return (\n <article className=\"mx-auto max-w-3xl px-4 py-12\">\n <script\n type=\"application/ld+json\"\n dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}\n />\n <PostHeader\n title={post.frontmatter.title}\n date={post.frontmatter.date}\n author={post.frontmatter.author}\n readingTime={post.readingTime}\n tags={post.frontmatter.tags}\n />\n <div className=\"prose prose-neutral dark:prose-invert mt-10 max-w-none prose-headings:text-text-primary prose-p:text-text-secondary prose-a:text-brand-primary prose-strong:text-text-primary prose-code:text-text-primary\">\n <MDXContent />\n </div>\n </article>\n );\n}\n`;\n}\n\nfunction rssFeedRoute(): string {\n return `${STAMP}\nimport { getAllPosts, generateRSSFeed } from '@/features/blog/server';\n\nexport async function GET() {\n const posts = getAllPosts();\n const siteUrl = process.env.APP_URL || 'http://localhost:3000';\n const feed = generateRSSFeed(posts, siteUrl);\n\n return new Response(feed, {\n headers: {\n 'Content-Type': 'application/xml',\n 'Cache-Control': 'public, max-age=3600, s-maxage=3600',\n },\n });\n}\n`;\n}\n\nfunction samplePostGettingStarted(): string {\n return `---\ntitle: \"Getting Started with Your App\"\ndescription: \"A quick guide to setting up and customizing your new application.\"\ndate: \"${new Date().toISOString().split('T')[0]}\"\nauthor: \"Team\"\ntags: [\"getting-started\", \"tutorial\"]\npublished: true\n---\n\n# Getting Started\n\nWelcome to your new application! This guide walks you through the basics.\n\n## Prerequisites\n\nMake sure you have the following installed:\n\n- **Node.js** 20+ (we recommend using nvm)\n- **Yarn** or npm for package management\n\n## Setting Up\n\nInstall dependencies and start the dev server:\n\n\\`\\`\\`bash\nyarn install\nyarn dev\n\\`\\`\\`\n\nYour app will be available at [http://localhost:3000](http://localhost:3000).\n\n## Project Structure\n\n- \\`src/app/\\` — Next.js app router pages\n- \\`src/features/\\` — Feature modules with components, server logic, and validation\n- \\`src/config/\\` — Application configuration\n- \\`src/lib/\\` — Shared utilities and core infrastructure\n\n## Next Steps\n\n- Explore the **dashboard** after signing up\n- Customize your theme in \\`src/config/app.config.ts\\`\n- Add new blog posts by creating \\`.mdx\\` files in \\`content/blog/\\`\n`;\n}\n\nfunction samplePostWelcome(): string {\n const yesterday = new Date(Date.now() - 86400000).toISOString().split('T')[0];\n return `---\ntitle: \"Welcome to the Blog\"\ndescription: \"Your blog is set up and ready for content.\"\ndate: \"${yesterday}\"\nauthor: \"Team\"\ntags: [\"announcement\"]\npublished: true\n---\n\n# Welcome\n\nYour blog is live! This post was generated automatically when the blog feature was added.\n\n## Adding New Posts\n\nCreate \\`.mdx\\` files in the \\`content/blog/\\` directory with YAML frontmatter:\n\n\\`\\`\\`yaml\n---\ntitle: \"My Post Title\"\ndescription: \"A short description (max 160 chars).\"\ndate: \"2026-01-15\"\nauthor: \"Your Name\"\ntags: [\"topic\"]\npublished: true\n---\n\\`\\`\\`\n\nPosts with \\`published: false\\` are excluded from the listing and RSS feed.\n\n## Features\n\n- **MDX support** — Write content with Markdown and JSX components\n- **Frontmatter validation** — Zod schema ensures all posts have valid metadata\n- **RSS feed** — Available at \\`/feed.xml\\`\n- **SEO** — JSON-LD structured data and Open Graph tags on every post\n- **Reading time** — Automatically calculated from content length\n`;\n}\n","/**\n * Utilities for patching existing source files in scaffolded projects.\n * See docs/design-docs/scaffold-testing-strategy.md Decision 6.\n */\n\n/** Matches 'use client' or \"use client\" with optional semicolon at start of file. */\nconst CLIENT_DIRECTIVE = /^['\"]use client['\"];?\\s*\\n/;\n\n/**\n * Inserts a line (e.g. an import) into file content so that any leading\n * `'use client'` (or `\"use client\"`) directive remains the first line.\n * Next.js and Turbopack require the directive to be the very first line;\n * prepending above it breaks the build.\n *\n * Use this whenever a generator patches an existing client component file\n * (e.g. layout.tsx, providers.tsx, (protected)/layout.tsx).\n *\n * @param content - Current file content (may start with 'use client' or not).\n * @param lineToInsert - The line to add, including trailing newline (e.g. `\"import { X } from '...';\\n\"`).\n * @returns Updated content with the line inserted after the directive if present, else at the top.\n */\nexport function insertImportAfterDirectives(content: string, lineToInsert: string): string {\n if (CLIENT_DIRECTIVE.test(content)) {\n return content.replace(/^(['\"]use client['\"];?\\s*\\n)/, `$1${lineToInsert}`);\n }\n return lineToInsert + content;\n}\n","import fs from 'fs-extra';\nimport path from 'node:path';\nimport { insertImportAfterDirectives } from '../../utils/client-file-patch.js';\nimport { log } from '../../utils/logger.js';\nimport { createRollbackContext } from '../../utils/rollback.js';\n\nconst GENERATOR_VERSION = '0.2.0';\nconst STAMP = `// @mars-generated dark-mode@${GENERATOR_VERSION}`;\n\ntype RollbackCtx = { trackModifiedFile: (p: string) => Promise<void> };\n\nexport async function generateDarkMode(projectRoot: string): Promise<void> {\n const featureDir = path.join(projectRoot, 'src', 'features', 'dark-mode');\n\n if (await fs.pathExists(featureDir)) {\n log.error('Dark mode feature already exists at src/features/dark-mode/');\n return;\n }\n\n const ctx = createRollbackContext();\n\n try {\n const files: Record<string, string> = {\n 'src/lib/shared/components/providers/ThemeProvider.tsx': themeProvider(),\n 'src/lib/shared/components/patterns/ThemeToggle.tsx': themeToggle(),\n 'src/lib/shared/components/patterns/ThemeToggleSimple.tsx': themeToggleSimple(),\n 'src/features/dark-mode/theme-script.ts': themeScript(),\n 'src/features/dark-mode/index.ts': barrelExport(),\n };\n\n let count = 0;\n for (const [filePath, content] of Object.entries(files)) {\n const fullPath = path.join(projectRoot, filePath);\n ctx.trackCreatedFile(fullPath);\n await fs.ensureDir(path.dirname(fullPath));\n await fs.writeFile(fullPath, content);\n count++;\n }\n\n await wireLayout(projectRoot, ctx);\n await wireProviders(projectRoot, ctx);\n await wireProtectedNav(projectRoot, ctx);\n await wireTailwindDarkMode(projectRoot, ctx);\n await setConfigFlag(projectRoot, ctx);\n await ctx.commit();\n\n log.success(`Generated and wired dark mode feature (${count} files created)`);\n log.blank();\n log.step('src/lib/shared/components/providers/ThemeProvider.tsx — context, hook, persistence');\n log.step('src/lib/shared/components/patterns/ThemeToggle.tsx — three-option toggle');\n log.step('src/lib/shared/components/patterns/ThemeToggleSimple.tsx — simple sun/moon toggle');\n log.step('src/features/dark-mode/theme-script.ts — FOUC prevention script');\n log.step('src/features/dark-mode/index.ts — barrel exports');\n log.blank();\n log.step('Wired automatically:');\n log.step(' ✓ FOUC-prevention script added to <head> in layout.tsx');\n log.step(' ✓ suppressHydrationWarning on <html>');\n log.step(' ✓ ThemeProvider wrapping app in providers.tsx');\n log.step(' ✓ ThemeToggleSimple added to navigation bar');\n log.step(' ✓ Tailwind dark mode class variant configured in globals.css');\n log.blank();\n } catch (error) {\n await ctx.rollback();\n throw error;\n }\n}\n\nasync function setConfigFlag(projectRoot: string, ctx: RollbackCtx): Promise<void> {\n const configPath = path.join(projectRoot, 'src', 'config', 'app.config.ts');\n if (!(await fs.pathExists(configPath))) return;\n\n await ctx.trackModifiedFile(configPath);\n const content = await fs.readFile(configPath, 'utf-8');\n const updated = content.replace(/darkMode:\\s*false/, 'darkMode: true');\n await fs.writeFile(configPath, updated);\n}\n\nasync function wireLayout(projectRoot: string, ctx: RollbackCtx): Promise<void> {\n const layoutPath = path.join(projectRoot, 'src', 'app', 'layout.tsx');\n if (!(await fs.pathExists(layoutPath))) return;\n\n await ctx.trackModifiedFile(layoutPath);\n let content = await fs.readFile(layoutPath, 'utf-8');\n\n if (!content.includes('getThemeScript')) {\n content = `import { getThemeScript } from '@/features/dark-mode';\\n${content}`;\n }\n\n if (!content.includes('suppressHydrationWarning')) {\n content = content.replace(/<html\\s+lang=\"en\"/, '<html lang=\"en\" suppressHydrationWarning');\n }\n\n if (!content.includes('getThemeScript()')) {\n content = content.replace(\n /(<html[^>]*>)\\s*\\n(\\s*<body)/,\n '$1\\n <head>\\n <script dangerouslySetInnerHTML={{ __html: getThemeScript() }} />\\n </head>\\n$2',\n );\n }\n\n await fs.writeFile(layoutPath, content);\n}\n\nasync function wireProviders(projectRoot: string, ctx: RollbackCtx): Promise<void> {\n const providersPath = path.join(projectRoot, 'src', 'app', 'providers.tsx');\n if (!(await fs.pathExists(providersPath))) return;\n\n await ctx.trackModifiedFile(providersPath);\n let content = await fs.readFile(providersPath, 'utf-8');\n\n if (content.includes('ThemeProvider')) return;\n\n content = insertImportAfterDirectives(\n content,\n `import { ThemeProvider } from '@/features/dark-mode';\\n`,\n );\n\n content = content.replace(\n /return\\s+(?:\\(\\s*)?((?:<\\w+[^>]*>)[\\s\\S]*?\\{children\\}[\\s\\S]*?(?:<\\/\\w+>))\\s*(?:\\)\\s*)?;/,\n (_match, jsx: string) => {\n const wrapped = jsx.replace(\n /(\\{children\\})/,\n '<ThemeProvider>$1</ThemeProvider>',\n );\n return `return (\\n ${wrapped}\\n );`;\n },\n );\n\n await fs.writeFile(providersPath, content);\n}\n\nasync function wireProtectedNav(projectRoot: string, ctx: RollbackCtx): Promise<void> {\n const navPath = path.join(projectRoot, 'src', 'app', '(protected)', 'layout.tsx');\n if (!(await fs.pathExists(navPath))) return;\n\n await ctx.trackModifiedFile(navPath);\n let content = await fs.readFile(navPath, 'utf-8');\n\n if (content.includes('ThemeToggleSimple')) return;\n\n content = insertImportAfterDirectives(\n content,\n `import { ThemeToggleSimple } from '@/features/dark-mode';\\n`,\n );\n\n // Desktop: place toggle inside the hidden md:block div so it's hidden on mobile (avoids duplicate toggle in hamburger menu).\n content = content.replace(\n /(<div className=\"hidden md:block\">)\\s*\\n(\\s*)(<UserMenu \\/>)/,\n '$1\\n$2<ThemeToggleSimple />\\n$2$3',\n );\n\n content = content.replace(\n /(<div className=\"border-t border-border-default px-4 py-3\">\\s*\\n\\s*<UserMenu \\/>)/,\n '$1\\n <div className=\"mt-2\">\\n <ThemeToggleSimple />\\n </div>',\n );\n\n await fs.writeFile(navPath, content);\n}\n\nasync function wireTailwindDarkMode(projectRoot: string, ctx: RollbackCtx): Promise<void> {\n const globalsPath = path.join(projectRoot, 'src', 'styles', 'globals.css');\n if (!(await fs.pathExists(globalsPath))) return;\n\n await ctx.trackModifiedFile(globalsPath);\n let content = await fs.readFile(globalsPath, 'utf-8');\n\n if (content.includes('@custom-variant dark')) return;\n\n content = content.replace(\n /@import 'tailwindcss';/,\n \"@import 'tailwindcss';\\n@custom-variant dark (&:where(.dark, .dark *));\",\n );\n\n await fs.writeFile(globalsPath, content);\n}\n\nfunction themeProvider(): string {\n return `${STAMP}\n'use client';\n\nimport { createContext, useCallback, useContext, useEffect, useMemo, useState } from 'react';\n\nexport type Theme = 'light' | 'dark' | 'system';\n\nexport interface ThemeContextValue {\n theme: Theme;\n resolvedTheme: 'light' | 'dark';\n setTheme: (theme: Theme) => void;\n}\n\nconst STORAGE_KEY = 'mars-theme';\n\nconst ThemeContext = createContext<ThemeContextValue | undefined>(undefined);\n\nfunction getSystemTheme(): 'light' | 'dark' {\n if (typeof window === 'undefined') return 'light';\n return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';\n}\n\nfunction applyTheme(resolved: 'light' | 'dark'): void {\n document.documentElement.classList.toggle('dark', resolved === 'dark');\n}\n\nexport function ThemeProvider({ children }: { children: React.ReactNode }) {\n const [theme, setThemeState] = useState<Theme>(() => {\n if (typeof window === 'undefined') return 'system';\n return (localStorage.getItem(STORAGE_KEY) as Theme) || 'system';\n });\n\n const [systemTheme, setSystemTheme] = useState<'light' | 'dark'>(getSystemTheme);\n\n const resolvedTheme = theme === 'system' ? systemTheme : theme;\n\n const setTheme = useCallback((next: Theme) => {\n setThemeState(next);\n localStorage.setItem(STORAGE_KEY, next);\n }, []);\n\n useEffect(() => {\n applyTheme(resolvedTheme);\n }, [resolvedTheme]);\n\n useEffect(() => {\n const mq = window.matchMedia('(prefers-color-scheme: dark)');\n const handler = (e: MediaQueryListEvent) => setSystemTheme(e.matches ? 'dark' : 'light');\n\n mq.addEventListener('change', handler);\n return () => mq.removeEventListener('change', handler);\n }, []);\n\n const value = useMemo<ThemeContextValue>(\n () => ({ theme, resolvedTheme, setTheme }),\n [theme, resolvedTheme, setTheme],\n );\n\n return <ThemeContext.Provider value={value}>{children}</ThemeContext.Provider>;\n}\n\nexport function useTheme(): ThemeContextValue {\n const ctx = useContext(ThemeContext);\n if (!ctx) throw new Error('useTheme must be used within a ThemeProvider');\n return ctx;\n}\n`;\n}\n\nfunction themeToggle(): string {\n return `${STAMP}\n'use client';\n\nimport { useTheme, type Theme } from '../providers/ThemeProvider';\n\nconst options: Array<{ value: Theme; label: string }> = [\n { value: 'light', label: 'Light' },\n { value: 'system', label: 'System' },\n { value: 'dark', label: 'Dark' },\n];\n\nfunction SunIcon({ className }: { className?: string }) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n strokeWidth={1.5}\n stroke=\"currentColor\"\n className={className}\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M12 3v2.25m6.364.386-1.591 1.591M21 12h-2.25m-.386 6.364-1.591-1.591M12 18.75V21m-4.773-4.227-1.591 1.591M5.25 12H3m4.227-4.773L5.636 5.636M15.75 12a3.75 3.75 0 1 1-7.5 0 3.75 3.75 0 0 1 7.5 0Z\"\n />\n </svg>\n );\n}\n\nfunction MoonIcon({ className }: { className?: string }) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n strokeWidth={1.5}\n stroke=\"currentColor\"\n className={className}\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M21.752 15.002A9.72 9.72 0 0 1 18 15.75c-5.385 0-9.75-4.365-9.75-9.75 0-1.33.266-2.597.748-3.752A9.753 9.753 0 0 0 3 11.25C3 16.635 7.365 21 12.75 21a9.753 9.753 0 0 0 9.002-5.998Z\"\n />\n </svg>\n );\n}\n\nfunction MonitorIcon({ className }: { className?: string }) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n strokeWidth={1.5}\n stroke=\"currentColor\"\n className={className}\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M9 17.25v1.007a3 3 0 0 1-.879 2.122L7.5 21h9l-.621-.621A3 3 0 0 1 15 18.257V17.25m6-12V15a2.25 2.25 0 0 1-2.25 2.25H5.25A2.25 2.25 0 0 1 3 15V5.25A2.25 2.25 0 0 1 5.25 3h13.5A2.25 2.25 0 0 1 21 5.25Z\"\n />\n </svg>\n );\n}\n\nfunction iconForTheme(value: Theme, className: string) {\n switch (value) {\n case 'light':\n return <SunIcon className={className} />;\n case 'dark':\n return <MoonIcon className={className} />;\n case 'system':\n return <MonitorIcon className={className} />;\n }\n}\n\nexport function ThemeToggle() {\n const { theme, setTheme } = useTheme();\n\n return (\n <div className=\"inline-flex items-center gap-1 rounded-full bg-surface-secondary p-1 shadow-sm\">\n {options.map((opt) => {\n const active = theme === opt.value;\n return (\n <button\n key={opt.value}\n type=\"button\"\n onClick={() => setTheme(opt.value)}\n aria-label={\\`Switch to \\${opt.label} theme\\`}\n className={\\`rounded-full p-1.5 transition-colors \\${\n active\n ? 'bg-surface-primary text-content-primary shadow-sm'\n : 'text-content-tertiary hover:text-content-primary'\n }\\`}\n >\n {iconForTheme(opt.value, 'size-4')}\n </button>\n );\n })}\n </div>\n );\n}\n`;\n}\n\nfunction themeToggleSimple(): string {\n return `${STAMP}\n'use client';\n\nimport { useTheme } from '../providers/ThemeProvider';\n\nfunction SunIcon({ className }: { className?: string }) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n strokeWidth={1.5}\n stroke=\"currentColor\"\n className={className}\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M12 3v2.25m6.364.386-1.591 1.591M21 12h-2.25m-.386 6.364-1.591-1.591M12 18.75V21m-4.773-4.227-1.591 1.591M5.25 12H3m4.227-4.773L5.636 5.636M15.75 12a3.75 3.75 0 1 1-7.5 0 3.75 3.75 0 0 1 7.5 0Z\"\n />\n </svg>\n );\n}\n\nfunction MoonIcon({ className }: { className?: string }) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n strokeWidth={1.5}\n stroke=\"currentColor\"\n className={className}\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M21.752 15.002A9.72 9.72 0 0 1 18 15.75c-5.385 0-9.75-4.365-9.75-9.75 0-1.33.266-2.597.748-3.752A9.753 9.753 0 0 0 3 11.25C3 16.635 7.365 21 12.75 21a9.753 9.753 0 0 0 9.002-5.998Z\"\n />\n </svg>\n );\n}\n\nexport function ThemeToggleSimple() {\n const { resolvedTheme, setTheme } = useTheme();\n\n return (\n <button\n type=\"button\"\n onClick={() => setTheme(resolvedTheme === 'dark' ? 'light' : 'dark')}\n aria-label={\\`Switch to \\${resolvedTheme === 'dark' ? 'light' : 'dark'} theme\\`}\n className=\"rounded-full p-2 text-content-primary transition-colors hover:bg-surface-secondary\"\n >\n {resolvedTheme === 'dark' ? (\n <SunIcon className=\"size-5\" />\n ) : (\n <MoonIcon className=\"size-5\" />\n )}\n </button>\n );\n}\n`;\n}\n\nfunction themeScript(): string {\n return `${STAMP}\nexport function getThemeScript(): string {\n return \\`\n (function() {\n try {\n var stored = localStorage.getItem('mars-theme');\n var prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;\n var isDark = stored === 'dark' || (stored !== 'light' && prefersDark);\n document.documentElement.classList.toggle('dark', isDark);\n } catch (e) {}\n })();\n \\`;\n}\n`;\n}\n\nfunction barrelExport(): string {\n return `${STAMP}\nexport { getThemeScript } from './theme-script';\nexport { ThemeProvider, useTheme, type Theme, type ThemeContextValue } from '@/lib/shared/components/providers/ThemeProvider';\nexport { ThemeToggle } from '@/lib/shared/components/patterns/ThemeToggle';\nexport { ThemeToggleSimple } from '@/lib/shared/components/patterns/ThemeToggleSimple';\n`;\n}\n","import fs from 'fs-extra';\nimport path from 'node:path';\n\nexport async function addUserRelation(\n projectRoot: string,\n field: string,\n ctx: { trackModifiedFile: (p: string) => Promise<void> },\n): Promise<void> {\n const authPath = path.join(projectRoot, 'prisma', 'schema', 'auth.prisma');\n if (!(await fs.pathExists(authPath))) return;\n\n await ctx.trackModifiedFile(authPath);\n let content = await fs.readFile(authPath, 'utf-8');\n\n if (content.includes(field)) return;\n\n const insertBefore = ' @@index([email])';\n content = content.replace(insertBefore, ` ${field}\\n\\n${insertBefore}`);\n await fs.writeFile(authPath, content);\n}\n","import fs from 'fs-extra';\nimport path from 'node:path';\nimport { log } from '../../utils/logger.js';\nimport { createRollbackContext } from '../../utils/rollback.js';\nimport { addUserRelation } from '../../utils/prisma.js';\n\nconst GENERATOR_VERSION = '0.1.0';\nconst STAMP = `// @mars-generated notifications@${GENERATOR_VERSION}`;\n\nexport async function generateNotifications(projectRoot: string): Promise<void> {\n const featureDir = path.join(projectRoot, 'src', 'features', 'notifications');\n\n if (await fs.pathExists(featureDir)) {\n log.error('Notifications feature already exists at src/features/notifications/');\n return;\n }\n\n const ctx = createRollbackContext();\n\n try {\n const files: Record<string, string> = {\n 'prisma/schema/notification.prisma': prismaSchema(),\n 'src/features/notifications/types.ts': types(),\n 'src/features/notifications/validation/schemas.ts': schemas(),\n 'src/features/notifications/server/index.ts': serverLogic(),\n 'src/features/notifications/hooks/use-notifications.ts': useNotificationsHook(),\n 'src/features/notifications/components/NotificationBell.tsx': notificationBell(),\n 'src/features/notifications/components/NotificationPanel.tsx': notificationPanel(),\n 'src/features/notifications/components/index.ts': componentIndex(),\n 'src/app/api/protected/notifications/route.ts': listRoute(),\n 'src/app/api/protected/notifications/[id]/read/route.ts': markReadRoute(),\n 'src/app/api/protected/notifications/read-all/route.ts': markAllReadRoute(),\n 'src/app/api/protected/notifications/count/route.ts': countRoute(),\n };\n\n let count = 0;\n for (const [filePath, content] of Object.entries(files)) {\n const fullPath = path.join(projectRoot, filePath);\n ctx.trackCreatedFile(fullPath);\n await fs.ensureDir(path.dirname(fullPath));\n await fs.writeFile(fullPath, content);\n count++;\n }\n\n await addUserRelation(projectRoot, 'notifications Notification[]', ctx);\n await setConfigFlag(projectRoot, ctx);\n await ctx.commit();\n\n log.success(`Generated notifications feature with ${count} files`);\n log.blank();\n log.step('prisma/schema/notification.prisma — Notification model');\n log.step('src/features/notifications/ — types, validation, server logic, hooks, components');\n log.step('src/app/api/protected/notifications/ — CRUD API routes');\n log.blank();\n log.warn('Next steps:');\n log.step('1. Run yarn db:push to sync the Prisma schema');\n log.step('2. Add <NotificationBell /> to your navbar/header');\n log.step('3. Import createNotification from server to trigger notifications from other features:');\n log.step(' import { createNotification } from \"@/features/notifications/server\"');\n log.blank();\n } catch (error) {\n await ctx.rollback();\n throw error;\n }\n}\n\nasync function setConfigFlag(projectRoot: string, ctx: { trackModifiedFile: (p: string) => Promise<void> }): Promise<void> {\n const configPath = path.join(projectRoot, 'src', 'config', 'app.config.ts');\n if (!(await fs.pathExists(configPath))) return;\n\n await ctx.trackModifiedFile(configPath);\n const content = await fs.readFile(configPath, 'utf-8');\n const updated = content.replace(/notifications:\\s*false/, 'notifications: true');\n await fs.writeFile(configPath, updated);\n}\n\nfunction prismaSchema(): string {\n return `// Generated by mars generate notifications (notifications@${GENERATOR_VERSION})\n\nmodel Notification {\n id String @id @default(cuid())\n userId String\n type String\n title String\n body String?\n resourceId String?\n resourceType String?\n read Boolean @default(false)\n readAt DateTime?\n createdAt DateTime @default(now())\n\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n\n @@index([userId, read])\n @@index([userId, createdAt])\n}\n`;\n}\n\nfunction types(): string {\n return `${STAMP}\n\nexport const NOTIFICATION_TYPES = {\n SYSTEM: 'system',\n WELCOME: 'welcome',\n ACCOUNT: 'account',\n SECURITY: 'security',\n BILLING: 'billing',\n MENTION: 'mention',\n UPDATE: 'update',\n} as const;\n\nexport type NotificationType = (typeof NOTIFICATION_TYPES)[keyof typeof NOTIFICATION_TYPES];\n\nexport interface NotificationItem {\n id: string;\n userId: string;\n type: string;\n title: string;\n body: string | null;\n resourceId: string | null;\n resourceType: string | null;\n read: boolean;\n readAt: Date | null;\n createdAt: Date;\n}\n`;\n}\n\nfunction schemas(): string {\n return `${STAMP}\nimport { z } from 'zod';\n\nexport const listNotificationsSchema = z.object({\n page: z.coerce.number().int().min(1).default(1),\n limit: z.coerce.number().int().min(1).max(100).default(20),\n unreadOnly: z\n .enum(['true', 'false'])\n .default('false')\n .transform((v) => v === 'true'),\n});\n\nexport type ListNotificationsParams = z.infer<typeof listNotificationsSchema>;\n`;\n}\n\nfunction serverLogic(): string {\n return `${STAMP}\nimport 'server-only';\n\nimport { prisma } from '@/lib/prisma';\nimport type { NotificationType } from '../types';\n\ninterface CreateNotificationInput {\n userId: string;\n type: NotificationType | string;\n title: string;\n body?: string;\n resourceId?: string;\n resourceType?: string;\n}\n\nexport async function createNotification(input: CreateNotificationInput) {\n return prisma.notification.create({\n data: {\n userId: input.userId,\n type: input.type,\n title: input.title,\n body: input.body ?? null,\n resourceId: input.resourceId ?? null,\n resourceType: input.resourceType ?? null,\n },\n });\n}\n\ninterface ListNotificationsOptions {\n userId: string;\n page?: number;\n limit?: number;\n unreadOnly?: boolean;\n}\n\nexport async function listNotifications({\n userId,\n page = 1,\n limit = 20,\n unreadOnly = false,\n}: ListNotificationsOptions) {\n const where = {\n userId,\n ...(unreadOnly ? { read: false } : {}),\n };\n\n const [notifications, total] = await prisma.$transaction([\n prisma.notification.findMany({\n where,\n orderBy: { createdAt: 'desc' },\n skip: (page - 1) * limit,\n take: limit,\n }),\n prisma.notification.count({ where }),\n ]);\n\n return {\n notifications,\n total,\n page,\n limit,\n totalPages: Math.ceil(total / limit),\n };\n}\n\nexport async function markAsRead(notificationId: string, userId: string) {\n return prisma.notification.updateMany({\n where: { id: notificationId, userId },\n data: { read: true, readAt: new Date() },\n });\n}\n\nexport async function markAllAsRead(userId: string) {\n return prisma.notification.updateMany({\n where: { userId, read: false },\n data: { read: true, readAt: new Date() },\n });\n}\n\nexport async function getUnreadCount(userId: string) {\n return prisma.notification.count({\n where: { userId, read: false },\n });\n}\n`;\n}\n\nfunction useNotificationsHook(): string {\n return `${STAMP}\n'use client';\n\nimport { useCallback, useEffect, useRef, useState } from 'react';\nimport type { NotificationItem } from '../types';\n\ninterface UseNotificationsOptions {\n pollingInterval?: number;\n}\n\ninterface UseNotificationsReturn {\n notifications: NotificationItem[];\n unreadCount: number;\n isLoading: boolean;\n error: string | null;\n markAsRead: (id: string) => Promise<void>;\n markAllAsRead: () => Promise<void>;\n refresh: () => Promise<void>;\n}\n\nexport function useNotifications({\n pollingInterval = 30000,\n}: UseNotificationsOptions = {}): UseNotificationsReturn {\n const [notifications, setNotifications] = useState<NotificationItem[]>([]);\n const [unreadCount, setUnreadCount] = useState(0);\n const [isLoading, setIsLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const intervalRef = useRef<ReturnType<typeof setInterval> | null>(null);\n\n const fetchNotifications = useCallback(async () => {\n try {\n const res = await fetch('/api/protected/notifications?limit=20');\n if (!res.ok) throw new Error('Failed to fetch notifications');\n const data = await res.json();\n setNotifications(data.notifications);\n setError(null);\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Unknown error');\n }\n }, []);\n\n const fetchUnreadCount = useCallback(async () => {\n try {\n const res = await fetch('/api/protected/notifications/count');\n if (!res.ok) throw new Error('Failed to fetch unread count');\n const data = await res.json();\n setUnreadCount(data.count);\n } catch {\n // Silently fail for count polling\n }\n }, []);\n\n const refresh = useCallback(async () => {\n setIsLoading(true);\n await Promise.all([fetchNotifications(), fetchUnreadCount()]);\n setIsLoading(false);\n }, [fetchNotifications, fetchUnreadCount]);\n\n const markAsRead = useCallback(\n async (id: string) => {\n const res = await fetch(\\`/api/protected/notifications/\\${id}/read\\`, {\n method: 'PATCH',\n });\n if (!res.ok) throw new Error('Failed to mark notification as read');\n\n setNotifications((prev) =>\n prev.map((n) => (n.id === id ? { ...n, read: true, readAt: new Date() } : n)),\n );\n setUnreadCount((prev) => Math.max(0, prev - 1));\n },\n [],\n );\n\n const markAllAsRead = useCallback(async () => {\n const res = await fetch('/api/protected/notifications/read-all', {\n method: 'PATCH',\n });\n if (!res.ok) throw new Error('Failed to mark all as read');\n\n setNotifications((prev) =>\n prev.map((n) => ({ ...n, read: true, readAt: new Date() })),\n );\n setUnreadCount(0);\n }, []);\n\n useEffect(() => {\n refresh();\n }, [refresh]);\n\n useEffect(() => {\n if (pollingInterval <= 0) return;\n\n intervalRef.current = setInterval(() => {\n fetchUnreadCount();\n }, pollingInterval);\n\n return () => {\n if (intervalRef.current) clearInterval(intervalRef.current);\n };\n }, [pollingInterval, fetchUnreadCount]);\n\n return {\n notifications,\n unreadCount,\n isLoading,\n error,\n markAsRead,\n markAllAsRead,\n refresh,\n };\n}\n`;\n}\n\nfunction notificationBell(): string {\n return `${STAMP}\n'use client';\n\nimport { useState, useRef, useEffect } from 'react';\nimport { useNotifications } from '../hooks/use-notifications';\nimport { NotificationPanel } from './NotificationPanel';\n\nexport function NotificationBell() {\n const [isOpen, setIsOpen] = useState(false);\n const containerRef = useRef<HTMLDivElement>(null);\n const { notifications, unreadCount, isLoading, markAsRead, markAllAsRead, refresh } =\n useNotifications();\n\n useEffect(() => {\n function handleClickOutside(event: MouseEvent) {\n if (containerRef.current && !containerRef.current.contains(event.target as Node)) {\n setIsOpen(false);\n }\n }\n\n document.addEventListener('mousedown', handleClickOutside);\n return () => document.removeEventListener('mousedown', handleClickOutside);\n }, []);\n\n function handleToggle() {\n if (!isOpen) refresh();\n setIsOpen((prev) => !prev);\n }\n\n return (\n <div ref={containerRef} className=\"relative\">\n <button\n type=\"button\"\n onClick={handleToggle}\n aria-label={\\`Notifications\\${unreadCount > 0 ? \\` (\\${unreadCount} unread)\\` : ''}\\`}\n className=\"relative rounded-full p-2 text-text-secondary transition-colors hover:bg-surface-secondary hover:text-text-primary\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n strokeWidth={1.5}\n stroke=\"currentColor\"\n className=\"size-5\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M14.857 17.082a23.848 23.848 0 0 0 5.454-1.31A8.967 8.967 0 0 1 18 9.75V9A6 6 0 0 0 6 9v.75a8.967 8.967 0 0 1-2.312 6.022c1.733.64 3.56 1.085 5.455 1.31m5.714 0a24.255 24.255 0 0 1-5.714 0m5.714 0a3 3 0 1 1-5.714 0\"\n />\n </svg>\n {unreadCount > 0 && (\n <span className=\"absolute -right-0.5 -top-0.5 flex size-5 items-center justify-center rounded-full bg-brand-primary text-[10px] font-bold text-text-on-brand\">\n {unreadCount > 99 ? '99+' : unreadCount}\n </span>\n )}\n </button>\n\n {isOpen && (\n <NotificationPanel\n notifications={notifications}\n isLoading={isLoading}\n onMarkAsRead={markAsRead}\n onMarkAllAsRead={markAllAsRead}\n onClose={() => setIsOpen(false)}\n />\n )}\n </div>\n );\n}\n`;\n}\n\nfunction notificationPanel(): string {\n return `${STAMP}\n'use client';\n\nimport type { NotificationItem } from '../types';\n\ninterface NotificationPanelProps {\n notifications: NotificationItem[];\n isLoading: boolean;\n onMarkAsRead: (id: string) => Promise<void>;\n onMarkAllAsRead: () => Promise<void>;\n onClose: () => void;\n}\n\nfunction formatRelativeTime(date: Date | string): string {\n const now = Date.now();\n const then = new Date(date).getTime();\n const seconds = Math.floor((now - then) / 1000);\n\n if (seconds < 60) return 'just now';\n\n const minutes = Math.floor(seconds / 60);\n if (minutes < 60) return \\`\\${minutes}m ago\\`;\n\n const hours = Math.floor(minutes / 60);\n if (hours < 24) return \\`\\${hours}h ago\\`;\n\n const days = Math.floor(hours / 24);\n if (days < 7) return \\`\\${days}d ago\\`;\n\n const weeks = Math.floor(days / 7);\n if (weeks < 4) return \\`\\${weeks}w ago\\`;\n\n const months = Math.floor(days / 30);\n if (months < 12) return \\`\\${months}mo ago\\`;\n\n const years = Math.floor(days / 365);\n return \\`\\${years}y ago\\`;\n}\n\nexport function NotificationPanel({\n notifications,\n isLoading,\n onMarkAsRead,\n onMarkAllAsRead,\n onClose,\n}: NotificationPanelProps) {\n const hasUnread = notifications.some((n) => !n.read);\n\n return (\n <div className=\"absolute right-0 top-full z-50 mt-2 w-80 overflow-hidden rounded-xl border border-border-default bg-surface-primary shadow-lg sm:w-96\">\n <div className=\"flex items-center justify-between border-b border-border-default px-4 py-3\">\n <h2 className=\"text-sm font-semibold text-text-primary\">Notifications</h2>\n {hasUnread && (\n <button\n type=\"button\"\n onClick={onMarkAllAsRead}\n className=\"text-xs font-medium text-brand-primary transition-colors hover:text-brand-primary-hover\"\n >\n Mark all as read\n </button>\n )}\n </div>\n\n <div className=\"max-h-96 overflow-y-auto\">\n {isLoading && notifications.length === 0 ? (\n <div className=\"flex items-center justify-center py-12\">\n <div className=\"size-5 animate-spin rounded-full border-2 border-border-default border-t-brand-primary\" />\n </div>\n ) : notifications.length === 0 ? (\n <div className=\"px-4 py-12 text-center\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n strokeWidth={1.5}\n stroke=\"currentColor\"\n className=\"mx-auto size-8 text-text-muted\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M14.857 17.082a23.848 23.848 0 0 0 5.454-1.31A8.967 8.967 0 0 1 18 9.75V9A6 6 0 0 0 6 9v.75a8.967 8.967 0 0 1-2.312 6.022c1.733.64 3.56 1.085 5.455 1.31m5.714 0a24.255 24.255 0 0 1-5.714 0m5.714 0a3 3 0 1 1-5.714 0\"\n />\n </svg>\n <p className=\"mt-2 text-sm text-text-muted\">No notifications yet</p>\n </div>\n ) : (\n <ul role=\"list\">\n {notifications.map((notification) => (\n <li key={notification.id}>\n <button\n type=\"button\"\n onClick={() => {\n if (!notification.read) onMarkAsRead(notification.id);\n }}\n className={\\`flex w-full gap-3 px-4 py-3 text-left transition-colors hover:bg-surface-secondary \\${\n !notification.read ? 'bg-surface-background' : ''\n }\\`}\n >\n <div className=\"mt-1.5 flex shrink-0\">\n {!notification.read && (\n <span className=\"size-2 rounded-full bg-brand-primary\" />\n )}\n {notification.read && <span className=\"size-2\" />}\n </div>\n <div className=\"min-w-0 flex-1\">\n <p className={\\`text-sm \\${\n !notification.read\n ? 'font-semibold text-text-primary'\n : 'text-text-secondary'\n }\\`}>\n {notification.title}\n </p>\n {notification.body && (\n <p className=\"mt-0.5 line-clamp-2 text-xs text-text-muted\">\n {notification.body}\n </p>\n )}\n <p className=\"mt-1 text-xs text-text-muted\">\n {formatRelativeTime(notification.createdAt)}\n </p>\n </div>\n </button>\n </li>\n ))}\n </ul>\n )}\n </div>\n </div>\n );\n}\n`;\n}\n\nfunction componentIndex(): string {\n return `${STAMP}\nexport { NotificationBell } from './NotificationBell';\nexport { NotificationPanel } from './NotificationPanel';\n`;\n}\n\nfunction listRoute(): string {\n return `${STAMP}\nimport { withAuthNoParams, handleApiError } from '@/lib/mars';\nimport { listNotifications } from '@/features/notifications/server';\nimport { listNotificationsSchema } from '@/features/notifications/validation/schemas';\nimport type { AuthenticatedRequest } from '@mars-stack/core/auth/middleware';\nimport { NextResponse } from 'next/server';\n\nexport const GET = withAuthNoParams(async (request: AuthenticatedRequest) => {\n try {\n const url = new URL(request.url);\n const params = listNotificationsSchema.parse({\n page: url.searchParams.get('page') ?? undefined,\n limit: url.searchParams.get('limit') ?? undefined,\n unreadOnly: url.searchParams.get('unreadOnly') ?? undefined,\n });\n\n const result = await listNotifications({\n userId: request.session.userId,\n ...params,\n });\n\n return NextResponse.json(result);\n } catch (error) {\n return handleApiError(error, { endpoint: '/api/protected/notifications' });\n }\n});\n`;\n}\n\nfunction markReadRoute(): string {\n return `${STAMP}\nimport { withAuth, handleApiError } from '@/lib/mars';\nimport { markAsRead } from '@/features/notifications/server';\nimport type { AuthenticatedRequest } from '@mars-stack/core/auth/middleware';\nimport { NextResponse } from 'next/server';\n\nexport const PATCH = withAuth(\n async (\n request: AuthenticatedRequest,\n context: { params: Promise<{ [key: string]: string }> },\n ) => {\n try {\n const { id } = await context.params;\n\n await markAsRead(id, request.session.userId);\n\n return NextResponse.json({ success: true });\n } catch (error) {\n return handleApiError(error, {\n endpoint: '/api/protected/notifications/[id]/read',\n });\n }\n },\n);\n`;\n}\n\nfunction markAllReadRoute(): string {\n return `${STAMP}\nimport { withAuthNoParams, handleApiError } from '@/lib/mars';\nimport { markAllAsRead } from '@/features/notifications/server';\nimport type { AuthenticatedRequest } from '@mars-stack/core/auth/middleware';\nimport { NextResponse } from 'next/server';\n\nexport const PATCH = withAuthNoParams(async (request: AuthenticatedRequest) => {\n try {\n await markAllAsRead(request.session.userId);\n return NextResponse.json({ success: true });\n } catch (error) {\n return handleApiError(error, { endpoint: '/api/protected/notifications/read-all' });\n }\n});\n`;\n}\n\nfunction countRoute(): string {\n return `${STAMP}\nimport { withAuthNoParams, handleApiError } from '@/lib/mars';\nimport { getUnreadCount } from '@/features/notifications/server';\nimport type { AuthenticatedRequest } from '@mars-stack/core/auth/middleware';\nimport { NextResponse } from 'next/server';\n\nexport const GET = withAuthNoParams(async (request: AuthenticatedRequest) => {\n try {\n const count = await getUnreadCount(request.session.userId);\n return NextResponse.json({ count });\n } catch (error) {\n return handleApiError(error, { endpoint: '/api/protected/notifications/count' });\n }\n});\n`;\n}\n","import fs from 'fs-extra';\nimport path from 'node:path';\nimport { log } from '../../utils/logger.js';\nimport { createRollbackContext } from '../../utils/rollback.js';\n\nconst GENERATOR_VERSION = '0.1.0';\nconst STAMP = `// @mars-generated analytics@${GENERATOR_VERSION}`;\n\nexport async function generateAnalytics(projectRoot: string): Promise<void> {\n const featureDir = path.join(projectRoot, 'src', 'features', 'analytics');\n\n if (await fs.pathExists(featureDir)) {\n log.error('Analytics feature already exists at src/features/analytics/');\n return;\n }\n\n const ctx = createRollbackContext();\n\n try {\n const files: Record<string, string> = {\n 'src/features/analytics/types.ts': types(),\n 'src/features/analytics/index.ts': barrelExports(),\n 'src/lib/shared/components/providers/AnalyticsProvider.tsx': analyticsProvider(),\n 'src/lib/shared/utils/analytics.ts': analyticsUtils(),\n 'src/lib/shared/components/patterns/ConsentBanner.tsx': consentBanner(),\n };\n\n let count = 0;\n for (const [filePath, content] of Object.entries(files)) {\n const fullPath = path.join(projectRoot, filePath);\n ctx.trackCreatedFile(fullPath);\n await fs.ensureDir(path.dirname(fullPath));\n await fs.writeFile(fullPath, content);\n count++;\n }\n\n await setConfigFlag(projectRoot, ctx);\n await ctx.commit();\n\n log.success(`Generated analytics feature with ${count} files`);\n log.blank();\n log.step('src/features/analytics/ — types and barrel exports');\n log.step('src/lib/shared/components/providers/AnalyticsProvider.tsx — provider wrapper');\n log.step('src/lib/shared/utils/analytics.ts — unified tracking API');\n log.step('src/lib/shared/components/patterns/ConsentBanner.tsx — cookie consent banner');\n log.blank();\n log.warn('Install dependencies for your chosen provider:');\n log.step('Vercel: yarn add @vercel/analytics @vercel/speed-insights');\n log.step('PostHog: yarn add posthog-js');\n log.step('Google: No packages needed');\n log.blank();\n log.warn('Next steps:');\n log.step('Set the provider in appConfig.services.analytics.provider');\n log.step('Set required environment variables for the chosen provider');\n log.step('Add <AnalyticsProvider> and <ConsentBanner /> to your root layout');\n log.blank();\n } catch (error) {\n await ctx.rollback();\n throw error;\n }\n}\n\nasync function setConfigFlag(projectRoot: string, ctx: { trackModifiedFile: (p: string) => Promise<void> }): Promise<void> {\n const configPath = path.join(projectRoot, 'src', 'config', 'app.config.ts');\n if (!(await fs.pathExists(configPath))) return;\n\n await ctx.trackModifiedFile(configPath);\n const content = await fs.readFile(configPath, 'utf-8');\n const updated = content.replace(/analytics:\\s*false/, 'analytics: true');\n await fs.writeFile(configPath, updated);\n}\n\nfunction types(): string {\n return `${STAMP}\n\nexport type AnalyticsProvider = 'vercel' | 'posthog' | 'google' | 'none';\n\nexport interface TrackEventParams {\n eventName: string;\n properties?: Record<string, string | number | boolean>;\n}\n`;\n}\n\nfunction barrelExports(): string {\n return `${STAMP}\n\nexport type { AnalyticsProvider, TrackEventParams } from './types';\n`;\n}\n\nfunction analyticsProvider(): string {\n return `${STAMP}\n'use client';\n\nimport { useEffect, useState } from 'react';\nimport { usePathname, useSearchParams } from 'next/navigation';\nimport Script from 'next/script';\nimport { appConfig } from '@/config/app.config';\nimport { trackPageView } from '@/lib/shared/utils/analytics';\n\ninterface AnalyticsProviderProps {\n children: React.ReactNode;\n}\n\nexport function AnalyticsProvider({ children }: AnalyticsProviderProps) {\n const provider: string = appConfig.services.analytics.provider;\n const isDev = process.env.NODE_ENV === 'development';\n\n if (provider === 'none' || isDev) {\n return <>{children}</>;\n }\n\n return (\n <>\n {provider === 'vercel' && <VercelAnalyticsProvider />}\n {provider === 'posthog' && <PostHogAnalyticsProvider />}\n {provider === 'google' && <GoogleAnalyticsProvider />}\n <PageViewTracker />\n {children}\n </>\n );\n}\n\nfunction VercelAnalyticsProvider() {\n const [components, setComponents] = useState<{ Analytics: React.ComponentType; SpeedInsights: React.ComponentType } | null>(null);\n\n useEffect(() => {\n const analyticsSpec = '@vercel/analytics/react';\n const insightsSpec = '@vercel/speed-insights/next';\n Promise.all([import(/* webpackIgnore: true */ analyticsSpec), import(/* webpackIgnore: true */ insightsSpec)])\n .then(([a, s]) => setComponents({ Analytics: a.Analytics, SpeedInsights: s.SpeedInsights }))\n .catch(() => {\n if (process.env.NODE_ENV === 'development') {\n console.warn('[mars/analytics] @vercel/analytics or @vercel/speed-insights not installed. Run: yarn add @vercel/analytics @vercel/speed-insights');\n }\n });\n }, []);\n\n if (!components) return null;\n const { Analytics, SpeedInsights } = components;\n\n return (\n <>\n <Analytics />\n <SpeedInsights />\n </>\n );\n}\n\nfunction PostHogAnalyticsProvider() {\n const posthogKey = process.env.NEXT_PUBLIC_POSTHOG_KEY;\n const posthogHost = process.env.NEXT_PUBLIC_POSTHOG_HOST || 'https://us.i.posthog.com';\n\n useEffect(() => {\n if (!posthogKey) {\n console.warn('[mars/analytics] NEXT_PUBLIC_POSTHOG_KEY is not set. PostHog analytics disabled.');\n return;\n }\n\n const spec = 'posthog-js';\n import(/* webpackIgnore: true */ spec)\n .then((mod) => {\n const posthog = mod.default;\n posthog.init(posthogKey, {\n api_host: posthogHost,\n capture_pageview: false,\n capture_pageleave: true,\n });\n })\n .catch(() => {\n console.warn('[mars/analytics] posthog-js not installed. Run: yarn add posthog-js');\n });\n }, [posthogKey, posthogHost]);\n\n return null;\n}\n\nfunction GoogleAnalyticsProvider() {\n const gaId = process.env.NEXT_PUBLIC_GA_MEASUREMENT_ID;\n\n if (!gaId) {\n if (process.env.NODE_ENV === 'development') {\n console.warn('[mars/analytics] NEXT_PUBLIC_GA_MEASUREMENT_ID is not set. Google Analytics disabled.');\n }\n return null;\n }\n\n return (\n <>\n <Script\n src={\\`https://www.googletagmanager.com/gtag/js?id=\\${gaId}\\`}\n strategy=\"afterInteractive\"\n />\n <Script id=\"google-analytics\" strategy=\"afterInteractive\">\n {\\`\n window.dataLayer = window.dataLayer || [];\n function gtag(){dataLayer.push(arguments);}\n gtag('js', new Date());\n gtag('config', '\\${gaId}');\n \\`}\n </Script>\n </>\n );\n}\n\nfunction PageViewTracker() {\n const pathname = usePathname();\n const searchParams = useSearchParams();\n\n useEffect(() => {\n const url = searchParams.toString()\n ? \\`\\${pathname}?\\${searchParams.toString()}\\`\n : pathname;\n trackPageView(url);\n }, [pathname, searchParams]);\n\n return null;\n}\n`;\n}\n\nfunction analyticsUtils(): string {\n return `${STAMP}\n\nimport { appConfig } from '@/config/app.config';\n\nfunction getProvider(): string {\n return appConfig.services.analytics.provider;\n}\n\nfunction isDisabledInDev(): boolean {\n return process.env.NODE_ENV === 'development';\n}\n\nexport function trackPageView(url: string): void {\n const provider = getProvider();\n\n if (provider === 'none' || isDisabledInDev()) {\n if (process.env.NODE_ENV === 'development') {\n console.debug('[mars/analytics] pageview:', url);\n }\n return;\n }\n\n switch (provider) {\n case 'vercel':\n break;\n\n case 'posthog': {\n const spec = 'posthog-js';\n import(/* webpackIgnore: true */ spec)\n .then((mod) => mod.default.capture('$pageview', { $current_url: url }))\n .catch(() => {});\n break;\n }\n\n case 'google': {\n if (typeof window !== 'undefined' && typeof window.gtag === 'function') {\n window.gtag('config', process.env.NEXT_PUBLIC_GA_MEASUREMENT_ID!, {\n page_path: url,\n });\n }\n break;\n }\n }\n}\n\nexport function trackEvent(\n eventName: string,\n properties?: Record<string, string | number | boolean>,\n): void {\n const provider = getProvider();\n\n if (provider === 'none' || isDisabledInDev()) {\n if (process.env.NODE_ENV === 'development') {\n console.debug('[mars/analytics] event:', eventName, properties);\n }\n return;\n }\n\n switch (provider) {\n case 'vercel': {\n try {\n const { track } = require('@vercel/analytics');\n track(eventName, properties);\n } catch {\n // @vercel/analytics not available\n }\n break;\n }\n\n case 'posthog': {\n try {\n const posthog = require('posthog-js').default;\n posthog.capture(eventName, properties);\n } catch {\n // posthog-js not available\n }\n break;\n }\n\n case 'google': {\n if (typeof window !== 'undefined' && typeof window.gtag === 'function') {\n window.gtag('event', eventName, properties);\n }\n break;\n }\n }\n}\n\nexport function identifyUser(\n userId: string,\n traits?: Record<string, string>,\n): void {\n const provider = getProvider();\n\n if (provider === 'none' || isDisabledInDev()) {\n if (process.env.NODE_ENV === 'development') {\n console.debug('[mars/analytics] identify:', userId, traits);\n }\n return;\n }\n\n switch (provider) {\n case 'vercel':\n break;\n\n case 'posthog': {\n try {\n const posthog = require('posthog-js').default;\n posthog.identify(userId, traits);\n } catch {\n // posthog-js not available\n }\n break;\n }\n\n case 'google': {\n if (typeof window !== 'undefined' && typeof window.gtag === 'function') {\n window.gtag('set', { user_id: userId, ...traits });\n }\n break;\n }\n }\n}\n\ndeclare global {\n interface Window {\n gtag: (...args: unknown[]) => void;\n dataLayer: unknown[];\n }\n}\n`;\n}\n\nfunction consentBanner(): string {\n return `${STAMP}\n'use client';\n\nimport { useState, useEffect } from 'react';\n\nconst CONSENT_KEY = 'mars-analytics-consent';\n\ntype ConsentStatus = 'accepted' | 'declined' | null;\n\nfunction getStoredConsent(): ConsentStatus {\n if (typeof window === 'undefined') return null;\n return localStorage.getItem(CONSENT_KEY) as ConsentStatus;\n}\n\nexport function ConsentBanner() {\n const [consent, setConsent] = useState<ConsentStatus>(null);\n const [mounted, setMounted] = useState(false);\n\n useEffect(() => {\n setMounted(true);\n setConsent(getStoredConsent());\n }, []);\n\n if (!mounted || consent !== null) {\n return null;\n }\n\n function handleAccept() {\n localStorage.setItem(CONSENT_KEY, 'accepted');\n setConsent('accepted');\n }\n\n function handleDecline() {\n localStorage.setItem(CONSENT_KEY, 'declined');\n setConsent('declined');\n }\n\n return (\n <div className=\"fixed inset-x-0 bottom-0 z-50 p-4\">\n <div className=\"mx-auto flex max-w-xl items-center justify-between gap-4 rounded-xl border border-border-default bg-surface-card px-6 py-4 shadow-lg\">\n <p className=\"text-sm text-text-secondary\">\n We use cookies and analytics to improve your experience.\n </p>\n <div className=\"flex shrink-0 gap-2\">\n <button\n onClick={handleDecline}\n className=\"rounded-lg border border-border-default px-4 py-2 text-sm font-medium text-text-secondary transition-colors hover:bg-surface-background\"\n >\n Decline\n </button>\n <button\n onClick={handleAccept}\n className=\"rounded-lg bg-brand-primary px-4 py-2 text-sm font-medium text-text-on-brand transition-colors hover:opacity-90\"\n >\n Accept\n </button>\n </div>\n </div>\n </div>\n );\n}\n`;\n}\n","import fs from 'fs-extra';\nimport path from 'node:path';\nimport { log } from '../../utils/logger.js';\nimport { createRollbackContext } from '../../utils/rollback.js';\nimport { addDependencies } from '../../utils/dependencies.js';\n\nconst GENERATOR_VERSION = '0.1.0';\nconst STAMP = `// @mars-generated command-palette@${GENERATOR_VERSION}`;\n\nexport async function generateCommandPalette(projectRoot: string): Promise<void> {\n const featureDir = path.join(projectRoot, 'src', 'features', 'command-palette');\n\n if (await fs.pathExists(featureDir)) {\n log.error('Command palette feature already exists at src/features/command-palette/');\n return;\n }\n\n const ctx = createRollbackContext();\n\n try {\n const files: Record<string, string> = {\n 'src/features/command-palette/types.ts': types(),\n 'src/features/command-palette/actions.ts': actions(),\n 'src/features/command-palette/registry.ts': registry(),\n 'src/features/command-palette/recent.ts': recent(),\n 'src/features/command-palette/components/CommandPalette.tsx': commandPalette(),\n 'src/features/command-palette/components/CommandTrigger.tsx': commandTrigger(),\n 'src/features/command-palette/components/index.ts': componentIndex(),\n 'src/features/command-palette/index.ts': featureIndex(),\n };\n\n let count = 0;\n for (const [filePath, content] of Object.entries(files)) {\n const fullPath = path.join(projectRoot, filePath);\n ctx.trackCreatedFile(fullPath);\n await fs.ensureDir(path.dirname(fullPath));\n await fs.writeFile(fullPath, content);\n count++;\n }\n\n await addDependencies(projectRoot, { cmdk: '^1.0.0' });\n await setConfigFlag(projectRoot, ctx);\n await ctx.commit();\n\n log.success(`Generated command palette feature with ${count} files`);\n log.blank();\n log.step('src/features/command-palette/ — types, actions, registry, recent, components');\n log.blank();\n log.warn('Integration steps:');\n log.step('Add <CommandPalette /> to your protected layout');\n log.step('Optionally add <CommandTrigger /> to your navbar for discoverability');\n log.step('Register custom actions with registerAction() from any feature');\n log.blank();\n } catch (error) {\n await ctx.rollback();\n throw error;\n }\n}\n\nasync function setConfigFlag(projectRoot: string, ctx: { trackModifiedFile: (p: string) => Promise<void> }): Promise<void> {\n const configPath = path.join(projectRoot, 'src', 'config', 'app.config.ts');\n if (!(await fs.pathExists(configPath))) return;\n\n await ctx.trackModifiedFile(configPath);\n const content = await fs.readFile(configPath, 'utf-8');\n const updated = content.replace(/commandPalette:\\s*false/, 'commandPalette: true');\n await fs.writeFile(configPath, updated);\n}\n\nfunction types(): string {\n return `${STAMP}\nimport type { ReactNode } from 'react';\n\nexport interface CommandAction {\n id: string;\n label: string;\n description?: string;\n icon?: ReactNode;\n keywords?: string[];\n shortcut?: string[];\n section: string;\n onSelect: () => void;\n}\n`;\n}\n\nfunction actions(): string {\n return `${STAMP}\n'use client';\n\nimport type { AppRouterInstance } from 'next/dist/shared/lib/app-router-context.shared-runtime';\nimport type { CommandAction } from './types';\n\nexport function createNavigationActions(router: AppRouterInstance): CommandAction[] {\n return [\n {\n id: 'nav-dashboard',\n label: 'Go to Dashboard',\n description: 'Navigate to the main dashboard',\n keywords: ['home', 'main', 'overview'],\n section: 'Navigation',\n onSelect: () => router.push('/dashboard'),\n },\n {\n id: 'nav-settings',\n label: 'Go to Settings',\n description: 'Manage your account settings',\n keywords: ['preferences', 'account', 'config'],\n section: 'Navigation',\n onSelect: () => router.push('/settings'),\n },\n {\n id: 'nav-profile',\n label: 'Go to Profile',\n description: 'View and edit your profile',\n keywords: ['user', 'account', 'me'],\n section: 'Navigation',\n onSelect: () => router.push('/profile'),\n },\n ];\n}\n\nexport function createThemeActions(setTheme: (theme: string) => void): CommandAction[] {\n return [\n {\n id: 'theme-light',\n label: 'Switch to Light Mode',\n description: 'Use the light color scheme',\n keywords: ['appearance', 'bright'],\n section: 'Theme',\n onSelect: () => setTheme('light'),\n },\n {\n id: 'theme-dark',\n label: 'Switch to Dark Mode',\n description: 'Use the dark color scheme',\n keywords: ['appearance', 'night'],\n section: 'Theme',\n onSelect: () => setTheme('dark'),\n },\n {\n id: 'theme-system',\n label: 'Use System Theme',\n description: 'Follow your operating system preference',\n keywords: ['appearance', 'auto', 'default'],\n section: 'Theme',\n onSelect: () => setTheme('system'),\n },\n ];\n}\n\nexport function createUserActions(callbacks: { onSignOut: () => void }): CommandAction[] {\n return [\n {\n id: 'user-signout',\n label: 'Sign Out',\n description: 'Log out of your account',\n keywords: ['logout', 'exit', 'leave'],\n section: 'User',\n onSelect: callbacks.onSignOut,\n },\n ];\n}\n`;\n}\n\nfunction registry(): string {\n return `${STAMP}\n'use client';\n\nimport type { CommandAction } from './types';\n\nconst customActions = new Map<string, CommandAction>();\n\nexport function registerAction(action: CommandAction): void {\n customActions.set(action.id, action);\n}\n\nexport function getCustomActions(): CommandAction[] {\n return Array.from(customActions.values());\n}\n`;\n}\n\nfunction recent(): string {\n return `${STAMP}\n'use client';\n\nconst STORAGE_KEY = 'mars:command-palette:recent';\nconst MAX_RECENT = 5;\n\nexport function getRecentActions(): string[] {\n if (typeof window === 'undefined') return [];\n\n try {\n const stored = localStorage.getItem(STORAGE_KEY);\n if (!stored) return [];\n const parsed: unknown = JSON.parse(stored);\n if (!Array.isArray(parsed)) return [];\n return parsed.filter((item): item is string => typeof item === 'string');\n } catch {\n return [];\n }\n}\n\nexport function addRecentAction(actionId: string): void {\n if (typeof window === 'undefined') return;\n\n try {\n const recent = getRecentActions().filter((id) => id !== actionId);\n recent.unshift(actionId);\n localStorage.setItem(STORAGE_KEY, JSON.stringify(recent.slice(0, MAX_RECENT)));\n } catch {\n // localStorage may be unavailable\n }\n}\n`;\n}\n\nfunction commandPalette(): string {\n return `${STAMP}\n'use client';\n\nimport { useState, useEffect, useCallback } from 'react';\nimport { useRouter } from 'next/navigation';\nimport { Command } from 'cmdk';\nimport type { CommandAction } from '../types';\nimport { createNavigationActions, createThemeActions, createUserActions } from '../actions';\nimport { getCustomActions } from '../registry';\nimport { addRecentAction, getRecentActions } from '../recent';\n\nfunction SearchIcon({ className }: { className?: string }) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n strokeWidth={1.5}\n stroke=\"currentColor\"\n className={className}\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"m21 21-5.197-5.197m0 0A7.5 7.5 0 1 0 5.196 5.196a7.5 7.5 0 0 0 10.607 10.607Z\"\n />\n </svg>\n );\n}\n\nexport function CommandPalette() {\n const [open, setOpen] = useState(false);\n const router = useRouter();\n\n const handleKeyDown = useCallback((e: KeyboardEvent) => {\n if ((e.metaKey || e.ctrlKey) && e.key === 'k') {\n e.preventDefault();\n setOpen((prev) => !prev);\n }\n }, []);\n\n useEffect(() => {\n document.addEventListener('keydown', handleKeyDown);\n return () => document.removeEventListener('keydown', handleKeyDown);\n }, [handleKeyDown]);\n\n const navigationActions = createNavigationActions(router);\n const themeActions = createThemeActions((theme) => {\n document.documentElement.setAttribute('data-theme', theme);\n });\n const userActions = createUserActions({\n onSignOut: () => router.push('/api/auth/signout'),\n });\n const customActions = getCustomActions();\n\n const allActions = [...navigationActions, ...themeActions, ...userActions, ...customActions];\n\n const recentIds = getRecentActions();\n const recentActions = recentIds\n .map((id) => allActions.find((a) => a.id === id))\n .filter((a): a is CommandAction => a !== undefined);\n\n const sections = allActions.reduce<Record<string, CommandAction[]>>((acc, action) => {\n if (!acc[action.section]) acc[action.section] = [];\n acc[action.section].push(action);\n return acc;\n }, {});\n\n function handleSelect(action: CommandAction) {\n setOpen(false);\n addRecentAction(action.id);\n action.onSelect();\n }\n\n if (!open) return null;\n\n return (\n <div className=\"fixed inset-0 z-50\">\n <div\n className=\"fixed inset-0 bg-surface-overlay backdrop-blur-sm\"\n onClick={() => setOpen(false)}\n aria-hidden=\"true\"\n />\n\n <div className=\"fixed left-1/2 top-[20%] w-full max-w-lg -translate-x-1/2\">\n <Command\n className=\"overflow-hidden rounded-xl border border-border-default bg-surface-card shadow-2xl\"\n loop\n >\n <div className=\"flex items-center gap-2 border-b border-border-default px-4\">\n <SearchIcon className=\"size-4 shrink-0 text-text-muted\" />\n <Command.Input\n placeholder=\"Type a command or search...\"\n className=\"flex-1 bg-transparent py-3 text-sm text-text-primary outline-none placeholder:text-text-muted\"\n />\n <kbd className=\"rounded border border-border-default bg-surface-background px-1.5 py-0.5 text-[10px] font-medium text-text-muted\">\n ESC\n </kbd>\n </div>\n\n <Command.List className=\"max-h-80 overflow-y-auto p-2\">\n <Command.Empty className=\"py-6 text-center text-sm text-text-muted\">\n No results found.\n </Command.Empty>\n\n {recentActions.length > 0 && (\n <Command.Group heading=\"Recent\">\n {recentActions.map((action) => (\n <CommandItem key={\\`recent-\\${action.id}\\`} action={action} onSelect={handleSelect} />\n ))}\n </Command.Group>\n )}\n\n {Object.entries(sections).map(([section, sectionActions]) => (\n <Command.Group key={section} heading={section}>\n {sectionActions.map((action) => (\n <CommandItem key={action.id} action={action} onSelect={handleSelect} />\n ))}\n </Command.Group>\n ))}\n </Command.List>\n\n <div className=\"flex items-center justify-between border-t border-border-default px-4 py-2 text-xs text-text-muted\">\n <div className=\"flex items-center gap-2\">\n <span className=\"flex items-center gap-1\">\n <kbd className=\"rounded border border-border-default bg-surface-background px-1 py-0.5 text-[10px]\">↑</kbd>\n <kbd className=\"rounded border border-border-default bg-surface-background px-1 py-0.5 text-[10px]\">↓</kbd>\n navigate\n </span>\n <span className=\"flex items-center gap-1\">\n <kbd className=\"rounded border border-border-default bg-surface-background px-1 py-0.5 text-[10px]\">↵</kbd>\n select\n </span>\n </div>\n <span className=\"flex items-center gap-1\">\n <kbd className=\"rounded border border-border-default bg-surface-background px-1 py-0.5 text-[10px]\">esc</kbd>\n close\n </span>\n </div>\n </Command>\n </div>\n </div>\n );\n}\n\nfunction CommandItem({\n action,\n onSelect,\n}: {\n action: CommandAction;\n onSelect: (action: CommandAction) => void;\n}) {\n return (\n <Command.Item\n value={\\`\\${action.label} \\${action.keywords?.join(' ') ?? ''}\\`}\n onSelect={() => onSelect(action)}\n className=\"flex cursor-pointer items-center justify-between rounded-lg px-3 py-2 text-sm text-text-primary aria-selected:bg-brand-primary aria-selected:text-text-on-brand\"\n >\n <div className=\"flex items-center gap-3\">\n {action.icon && <span className=\"shrink-0\">{action.icon}</span>}\n <div>\n <div className=\"font-medium\">{action.label}</div>\n {action.description && (\n <div className=\"text-xs text-text-muted aria-selected:text-text-on-brand/70\">\n {action.description}\n </div>\n )}\n </div>\n </div>\n {action.shortcut && action.shortcut.length > 0 && (\n <div className=\"flex items-center gap-0.5\">\n {action.shortcut.map((key) => (\n <kbd\n key={key}\n className=\"rounded border border-border-default bg-surface-background px-1.5 py-0.5 text-[10px] font-medium text-text-muted\"\n >\n {key}\n </kbd>\n ))}\n </div>\n )}\n </Command.Item>\n );\n}\n`;\n}\n\nfunction commandTrigger(): string {\n return `${STAMP}\n'use client';\n\nfunction SearchIcon({ className }: { className?: string }) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n strokeWidth={1.5}\n stroke=\"currentColor\"\n className={className}\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"m21 21-5.197-5.197m0 0A7.5 7.5 0 1 0 5.196 5.196a7.5 7.5 0 0 0 10.607 10.607Z\"\n />\n </svg>\n );\n}\n\nexport function CommandTrigger() {\n function handleClick() {\n const event = new KeyboardEvent('keydown', {\n key: 'k',\n metaKey: true,\n bubbles: true,\n });\n document.dispatchEvent(event);\n }\n\n return (\n <button\n type=\"button\"\n onClick={handleClick}\n className=\"flex items-center gap-2 rounded-lg border border-border-default bg-surface-background px-3 py-1.5 text-sm text-text-muted transition-colors hover:border-border-default hover:text-text-primary\"\n >\n <SearchIcon className=\"size-4\" />\n <span>Search...</span>\n <kbd className=\"rounded border border-border-default bg-surface-card px-1.5 py-0.5 text-[10px] font-medium\">\n ⌘K\n </kbd>\n </button>\n );\n}\n`;\n}\n\nfunction componentIndex(): string {\n return `${STAMP}\nexport { CommandPalette } from './CommandPalette';\nexport { CommandTrigger } from './CommandTrigger';\n`;\n}\n\nfunction featureIndex(): string {\n return `${STAMP}\nexport { CommandPalette, CommandTrigger } from './components';\nexport { registerAction, getCustomActions } from './registry';\nexport { createNavigationActions, createThemeActions, createUserActions } from './actions';\nexport { getRecentActions, addRecentAction } from './recent';\nexport type { CommandAction } from './types';\n`;\n}\n","import fs from 'fs-extra';\nimport path from 'node:path';\nimport { log } from '../../utils/logger.js';\nimport { createRollbackContext } from '../../utils/rollback.js';\nimport { addUserRelation } from '../../utils/prisma.js';\n\nconst GENERATOR_VERSION = '0.1.0';\nconst STAMP = `// @mars-generated onboarding@${GENERATOR_VERSION}`;\n\nexport async function generateOnboarding(projectRoot: string): Promise<void> {\n const featureDir = path.join(projectRoot, 'src', 'features', 'onboarding');\n\n if (await fs.pathExists(featureDir)) {\n log.error('Onboarding feature already exists at src/features/onboarding/');\n return;\n }\n\n const ctx = createRollbackContext();\n\n try {\n const files: Record<string, string> = {\n 'prisma/schema/onboarding.prisma': prismaSchema(),\n 'src/features/onboarding/config.ts': stepConfig(),\n 'src/features/onboarding/types.ts': types(),\n 'src/features/onboarding/server/index.ts': serverLogic(),\n 'src/features/onboarding/validation/schemas.ts': schemas(),\n 'src/features/onboarding/components/OnboardingProgress.tsx': progressBar(),\n 'src/features/onboarding/components/OnboardingFlow.tsx': flowComponent(),\n 'src/features/onboarding/components/index.ts': componentIndex(),\n 'src/app/(protected)/onboarding/page.tsx': onboardingPage(),\n 'src/app/api/protected/onboarding/route.ts': getProgressRoute(),\n 'src/app/api/protected/onboarding/step/route.ts': stepActionRoute(),\n 'src/features/onboarding/index.ts': featureIndex(),\n };\n\n let count = 0;\n for (const [filePath, content] of Object.entries(files)) {\n const fullPath = path.join(projectRoot, filePath);\n ctx.trackCreatedFile(fullPath);\n await fs.ensureDir(path.dirname(fullPath));\n await fs.writeFile(fullPath, content);\n count++;\n }\n\n await addUserRelation(projectRoot, 'onboardingProgress OnboardingProgress?', ctx);\n await setConfigFlag(projectRoot, ctx);\n await ctx.commit();\n\n log.success(`Generated onboarding feature with ${count} files`);\n log.blank();\n log.step('src/features/onboarding/ — config, types, server logic, validation, components');\n log.step('src/app/(protected)/onboarding/ — onboarding page');\n log.step('src/app/api/protected/onboarding/ — progress and step API routes');\n log.step('prisma/schema/onboarding.prisma — OnboardingProgress model');\n log.blank();\n log.warn('Next steps:');\n log.step('Run `yarn db:push` to sync the Prisma schema');\n log.step('Add onboarding redirect check to your protected layout');\n log.step('Customize steps in `src/features/onboarding/config.ts`');\n log.blank();\n } catch (error) {\n await ctx.rollback();\n throw error;\n }\n}\n\nasync function setConfigFlag(projectRoot: string, ctx: { trackModifiedFile: (p: string) => Promise<void> }): Promise<void> {\n const configPath = path.join(projectRoot, 'src', 'config', 'app.config.ts');\n if (!(await fs.pathExists(configPath))) return;\n\n await ctx.trackModifiedFile(configPath);\n const content = await fs.readFile(configPath, 'utf-8');\n const updated = content.replace(/onboarding:\\s*false/, 'onboarding: true');\n await fs.writeFile(configPath, updated);\n}\n\nfunction prismaSchema(): string {\n return `// Generated by mars generate onboarding (onboarding@${GENERATOR_VERSION})\nmodel OnboardingProgress {\n id String @id @default(cuid())\n userId String @unique\n completedAt DateTime?\n currentStep Int @default(0)\n stepsData String @default(\"{}\")\n skippedSteps String @default(\"[]\")\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n}\n`;\n}\n\nfunction stepConfig(): string {\n return `${STAMP}\n\nexport interface OnboardingStep {\n id: string;\n title: string;\n description: string;\n required: boolean;\n}\n\nexport const ONBOARDING_STEPS: OnboardingStep[] = [\n {\n id: 'profile',\n title: 'Complete Your Profile',\n description: 'Add your name and profile details to personalize your experience.',\n required: true,\n },\n {\n id: 'preferences',\n title: 'Set Preferences',\n description: 'Choose your notification and display preferences.',\n required: false,\n },\n {\n id: 'workspace',\n title: 'Create a Workspace',\n description: 'Set up your first workspace to start collaborating.',\n required: true,\n },\n {\n id: 'invite',\n title: 'Invite Team Members',\n description: 'Bring your team on board to work together.',\n required: false,\n },\n];\n`;\n}\n\nfunction types(): string {\n return `${STAMP}\nimport type { OnboardingStep } from './config';\n\nexport interface OnboardingProgressData {\n id: string;\n userId: string;\n completedAt: Date | null;\n currentStep: number;\n stepsData: Record<string, unknown>;\n skippedSteps: number[];\n createdAt: Date;\n updatedAt: Date;\n}\n\nexport type StepStatus = 'complete' | 'current' | 'skipped' | 'pending';\n\nexport interface StepWithStatus extends OnboardingStep {\n index: number;\n status: StepStatus;\n}\n`;\n}\n\nfunction serverLogic(): string {\n return `${STAMP}\nimport 'server-only';\n\nimport { prisma } from '@/lib/prisma';\nimport { ONBOARDING_STEPS } from '../config';\n\nexport async function getOnboardingProgress(userId: string) {\n const existing = await prisma.onboardingProgress.findUnique({\n where: { userId },\n });\n\n if (existing) {\n return {\n ...existing,\n stepsData: JSON.parse(existing.stepsData) as Record<string, unknown>,\n skippedSteps: JSON.parse(existing.skippedSteps) as number[],\n };\n }\n\n const created = await prisma.onboardingProgress.create({\n data: { userId },\n });\n\n return {\n ...created,\n stepsData: {} as Record<string, unknown>,\n skippedSteps: [] as number[],\n };\n}\n\nexport async function updateOnboardingStep(\n userId: string,\n stepIndex: number,\n data?: Record<string, unknown>,\n) {\n const progress = await getOnboardingProgress(userId);\n const stepsData = { ...progress.stepsData };\n\n if (data) {\n const step = ONBOARDING_STEPS[stepIndex];\n if (step) {\n stepsData[step.id] = data;\n }\n }\n\n const nextStep = stepIndex + 1;\n\n return prisma.onboardingProgress.update({\n where: { userId },\n data: {\n currentStep: nextStep,\n stepsData: JSON.stringify(stepsData),\n },\n });\n}\n\nexport async function skipOnboardingStep(userId: string, stepIndex: number) {\n const step = ONBOARDING_STEPS[stepIndex];\n\n if (!step) {\n throw new Error(\\`Invalid step index: \\${stepIndex}\\`);\n }\n\n if (step.required) {\n throw new Error(\\`Cannot skip required step: \\${step.title}\\`);\n }\n\n const progress = await getOnboardingProgress(userId);\n const skippedSteps = [...progress.skippedSteps, stepIndex];\n const nextStep = stepIndex + 1;\n\n return prisma.onboardingProgress.update({\n where: { userId },\n data: {\n currentStep: nextStep,\n skippedSteps: JSON.stringify(skippedSteps),\n },\n });\n}\n\nexport async function completeOnboarding(userId: string) {\n return prisma.onboardingProgress.update({\n where: { userId },\n data: {\n completedAt: new Date(),\n currentStep: ONBOARDING_STEPS.length,\n },\n });\n}\n\nexport async function isOnboardingComplete(userId: string): Promise<boolean> {\n const progress = await prisma.onboardingProgress.findUnique({\n where: { userId },\n select: { completedAt: true },\n });\n\n return progress?.completedAt !== null && progress?.completedAt !== undefined;\n}\n`;\n}\n\nfunction schemas(): string {\n return `${STAMP}\nimport { z } from 'zod';\n\nexport const stepActionSchema = z.object({\n stepIndex: z.number().int().min(0),\n action: z.enum(['complete', 'skip']),\n data: z.record(z.string(), z.unknown()).optional(),\n});\n\nexport type StepAction = z.infer<typeof stepActionSchema>;\n`;\n}\n\nfunction progressBar(): string {\n return `${STAMP}\nimport type { StepWithStatus } from '../types';\n\ninterface OnboardingProgressProps {\n steps: StepWithStatus[];\n}\n\nexport function OnboardingProgress({ steps }: OnboardingProgressProps) {\n return (\n <nav aria-label=\"Onboarding progress\" className=\"w-full\">\n <ol className=\"flex items-center\">\n {steps.map((step, index) => (\n <li key={step.id} className=\"flex items-center\">\n <div className=\"flex flex-col items-center\">\n <div className=\"flex items-center justify-center\">\n {step.status === 'complete' ? (\n <span className=\"flex h-8 w-8 items-center justify-center rounded-full bg-brand-primary\">\n <svg\n className=\"h-4 w-4 text-text-on-brand\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n strokeWidth={2.5}\n stroke=\"currentColor\"\n >\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M4.5 12.75l6 6 9-13.5\" />\n </svg>\n </span>\n ) : step.status === 'current' ? (\n <span className=\"flex h-8 w-8 items-center justify-center rounded-full border-2 border-brand-primary bg-surface-card\">\n <span className=\"text-sm font-semibold text-brand-primary\">{index + 1}</span>\n </span>\n ) : step.status === 'skipped' ? (\n <span className=\"flex h-8 w-8 items-center justify-center rounded-full bg-surface-muted\">\n <span className=\"text-sm text-text-muted line-through\">{index + 1}</span>\n </span>\n ) : (\n <span className=\"flex h-8 w-8 items-center justify-center rounded-full border border-border-default bg-surface-card\">\n <span className=\"text-sm text-text-muted\">{index + 1}</span>\n </span>\n )}\n </div>\n <span\n className={\\`mt-2 text-center text-xs font-medium \\${\n step.status === 'current'\n ? 'text-brand-primary'\n : step.status === 'complete'\n ? 'text-text-primary'\n : 'text-text-muted'\n }\\`}\n >\n {step.title}\n </span>\n </div>\n\n {index < steps.length - 1 && (\n <div\n className={\\`mx-2 h-0.5 w-12 sm:w-20 \\${\n step.status === 'complete' ? 'bg-brand-primary' : 'bg-border-default'\n }\\`}\n />\n )}\n </li>\n ))}\n </ol>\n </nav>\n );\n}\n`;\n}\n\nfunction flowComponent(): string {\n return `${STAMP}\n'use client';\n\nimport { useState, useCallback } from 'react';\nimport { useRouter } from 'next/navigation';\nimport { OnboardingProgress } from './OnboardingProgress';\nimport { ONBOARDING_STEPS } from '../config';\nimport type { StepWithStatus, OnboardingProgressData } from '../types';\n\ninterface OnboardingFlowProps {\n initialProgress: OnboardingProgressData;\n}\n\nexport function OnboardingFlow({ initialProgress }: OnboardingFlowProps) {\n const router = useRouter();\n const [currentStep, setCurrentStep] = useState(initialProgress.currentStep);\n const [skippedSteps, setSkippedSteps] = useState<number[]>(initialProgress.skippedSteps);\n const [isLoading, setIsLoading] = useState(false);\n\n const steps: StepWithStatus[] = ONBOARDING_STEPS.map((step, index) => ({\n ...step,\n index,\n status:\n index < currentStep\n ? skippedSteps.includes(index)\n ? 'skipped'\n : 'complete'\n : index === currentStep\n ? 'current'\n : 'pending',\n }));\n\n const activeStep = ONBOARDING_STEPS[currentStep];\n const isLastStep = currentStep >= ONBOARDING_STEPS.length;\n\n const handleAction = useCallback(\n async (action: 'complete' | 'skip') => {\n setIsLoading(true);\n try {\n const response = await fetch('/api/protected/onboarding/step', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n credentials: 'include',\n body: JSON.stringify({ stepIndex: currentStep, action }),\n });\n\n if (!response.ok) {\n const errorData: { error?: string } = await response.json();\n throw new Error(errorData.error || 'Failed to update step');\n }\n\n if (action === 'skip') {\n setSkippedSteps((prev) => [...prev, currentStep]);\n }\n\n const nextStep = currentStep + 1;\n setCurrentStep(nextStep);\n\n if (nextStep >= ONBOARDING_STEPS.length) {\n router.push('/dashboard');\n }\n } catch (error) {\n console.error('Onboarding step error:', error);\n } finally {\n setIsLoading(false);\n }\n },\n [currentStep, router],\n );\n\n if (isLastStep) {\n return (\n <div className=\"flex min-h-[400px] items-center justify-center\">\n <div className=\"text-center\">\n <h2 className=\"text-2xl font-bold text-text-primary\">All done!</h2>\n <p className=\"mt-2 text-text-secondary\">Redirecting to your dashboard...</p>\n </div>\n </div>\n );\n }\n\n return (\n <div className=\"mx-auto w-full max-w-2xl px-4 py-12\">\n <OnboardingProgress steps={steps} />\n\n <div className=\"mt-10 rounded-2xl border border-border-default bg-surface-card p-8\">\n <h2 className=\"text-2xl font-bold text-text-primary\">{activeStep?.title}</h2>\n <p className=\"mt-2 text-text-secondary\">{activeStep?.description}</p>\n\n <div className=\"mt-8 flex items-center gap-3\">\n <button\n type=\"button\"\n onClick={() => handleAction('complete')}\n disabled={isLoading}\n className=\"rounded-lg bg-brand-primary px-6 py-2.5 text-sm font-medium text-text-on-brand transition-colors hover:bg-brand-primary-hover disabled:opacity-50\"\n >\n {isLoading ? 'Saving...' : 'Complete Step'}\n </button>\n\n {activeStep && !activeStep.required && (\n <button\n type=\"button\"\n onClick={() => handleAction('skip')}\n disabled={isLoading}\n className=\"rounded-lg border border-border-default bg-surface-card px-6 py-2.5 text-sm font-medium text-text-secondary transition-colors hover:bg-surface-muted disabled:opacity-50\"\n >\n Skip\n </button>\n )}\n </div>\n </div>\n </div>\n );\n}\n`;\n}\n\nfunction componentIndex(): string {\n return `${STAMP}\nexport { OnboardingProgress } from './OnboardingProgress';\nexport { OnboardingFlow } from './OnboardingFlow';\n`;\n}\n\nfunction onboardingPage(): string {\n return `${STAMP}\nimport { redirect } from 'next/navigation';\nimport { getSession } from '@/lib/mars';\nimport { getOnboardingProgress, isOnboardingComplete } from '@/features/onboarding/server';\nimport { OnboardingFlow } from '@/features/onboarding/components';\n\nexport default async function OnboardingPage() {\n const session = await getSession();\n\n if (!session) {\n redirect('/sign-in');\n }\n\n const complete = await isOnboardingComplete(session.userId);\n if (complete) {\n redirect('/dashboard');\n }\n\n const progress = await getOnboardingProgress(session.userId);\n\n return (\n <div className=\"flex min-h-screen flex-col items-center justify-center bg-surface-background\">\n <div className=\"w-full max-w-3xl\">\n <div className=\"mb-8 text-center\">\n <h1 className=\"text-3xl font-bold tracking-tight text-text-primary\">\n Welcome! Let&apos;s get you set up.\n </h1>\n <p className=\"mt-2 text-text-secondary\">\n Complete these steps to get the most out of your account.\n </p>\n </div>\n <OnboardingFlow initialProgress={progress} />\n </div>\n </div>\n );\n}\n`;\n}\n\nfunction getProgressRoute(): string {\n return `${STAMP}\nimport { withAuthNoParams, handleApiError } from '@/lib/mars';\nimport { getOnboardingProgress } from '@/features/onboarding/server';\nimport type { AuthenticatedRequest } from '@mars-stack/core/auth/middleware';\nimport { NextResponse } from 'next/server';\n\nexport const GET = withAuthNoParams(async (request: AuthenticatedRequest) => {\n try {\n const progress = await getOnboardingProgress(request.session.userId);\n return NextResponse.json({ progress });\n } catch (error) {\n return handleApiError(error, { endpoint: '/api/protected/onboarding' });\n }\n});\n`;\n}\n\nfunction stepActionRoute(): string {\n return `${STAMP}\nimport { withAuthNoParams, handleApiError } from '@/lib/mars';\nimport {\n updateOnboardingStep,\n skipOnboardingStep,\n completeOnboarding,\n} from '@/features/onboarding/server';\nimport { stepActionSchema } from '@/features/onboarding/validation/schemas';\nimport { ONBOARDING_STEPS } from '@/features/onboarding/config';\nimport type { AuthenticatedRequest } from '@mars-stack/core/auth/middleware';\nimport { NextResponse } from 'next/server';\n\nexport const POST = withAuthNoParams(async (request: AuthenticatedRequest) => {\n try {\n const body = await request.json();\n const result = stepActionSchema.safeParse(body);\n\n if (!result.success) {\n return NextResponse.json(\n { error: result.error.issues[0]?.message || 'Invalid input' },\n { status: 400 },\n );\n }\n\n const { stepIndex, action, data } = result.data;\n const userId = request.session.userId;\n\n if (stepIndex < 0 || stepIndex >= ONBOARDING_STEPS.length) {\n return NextResponse.json({ error: 'Invalid step index' }, { status: 400 });\n }\n\n if (action === 'skip') {\n await skipOnboardingStep(userId, stepIndex);\n } else {\n await updateOnboardingStep(userId, stepIndex, data);\n }\n\n const isLastStep = stepIndex + 1 >= ONBOARDING_STEPS.length;\n if (isLastStep) {\n await completeOnboarding(userId);\n }\n\n return NextResponse.json({ success: true });\n } catch (error) {\n if (error instanceof Error && error.message.startsWith('Cannot skip required step')) {\n return NextResponse.json({ error: error.message }, { status: 400 });\n }\n return handleApiError(error, { endpoint: '/api/protected/onboarding/step' });\n }\n});\n`;\n}\n\nfunction featureIndex(): string {\n return `${STAMP}\nexport { ONBOARDING_STEPS } from './config';\nexport type { OnboardingStep } from './config';\nexport type { OnboardingProgressData, StepStatus, StepWithStatus } from './types';\nexport {\n getOnboardingProgress,\n updateOnboardingStep,\n skipOnboardingStep,\n completeOnboarding,\n isOnboardingComplete,\n} from './server';\n`;\n}\n","import fs from 'fs-extra';\nimport path from 'node:path';\nimport { log } from '../../utils/logger.js';\nimport { createRollbackContext } from '../../utils/rollback.js';\n\nconst GENERATOR_VERSION = '0.1.0';\nconst STAMP = `// @mars-generated search@${GENERATOR_VERSION}`;\n\nexport async function generateSearch(projectRoot: string): Promise<void> {\n const featureDir = path.join(projectRoot, 'src', 'features', 'search');\n\n if (await fs.pathExists(featureDir)) {\n log.error('Search feature already exists at src/features/search/');\n return;\n }\n\n const ctx = createRollbackContext();\n\n try {\n const files: Record<string, string> = {\n 'src/features/search/types.ts': types(),\n 'src/features/search/validation/schemas.ts': schemas(),\n 'src/features/search/server/postgres.ts': postgresProvider(),\n 'src/features/search/server/index.ts': serverIndex(),\n 'src/features/search/hooks/use-search.ts': useSearchHook(),\n 'src/features/search/components/SearchInput.tsx': searchInput(),\n 'src/features/search/components/index.ts': componentIndex(),\n 'src/features/search/index.ts': featureIndex(),\n 'src/app/api/protected/search/route.ts': searchRoute(),\n };\n\n let count = 0;\n for (const [filePath, content] of Object.entries(files)) {\n const fullPath = path.join(projectRoot, filePath);\n ctx.trackCreatedFile(fullPath);\n await fs.ensureDir(path.dirname(fullPath));\n await fs.writeFile(fullPath, content);\n count++;\n }\n\n await setConfigFlag(projectRoot, ctx);\n await ctx.commit();\n\n log.success(`Generated search feature with ${count} files`);\n log.blank();\n log.step('src/features/search/ — types, validation, server logic, hooks, components');\n log.step('src/app/api/protected/search/ — authenticated search endpoint');\n log.blank();\n log.warn('Search uses Postgres full-text search by default (no extra setup).');\n log.blank();\n log.step('For Algolia: yarn add algoliasearch + set ALGOLIA_APP_ID, ALGOLIA_API_KEY env vars');\n log.step('For Meilisearch: yarn add meilisearch + set MEILISEARCH_HOST, MEILISEARCH_API_KEY env vars');\n log.blank();\n log.step('Add a tsvector column via raw migration for models you want to search');\n log.step('Use the useSearch hook or SearchInput component in your pages');\n log.blank();\n } catch (error) {\n await ctx.rollback();\n throw error;\n }\n}\n\nasync function setConfigFlag(projectRoot: string, ctx: { trackModifiedFile: (p: string) => Promise<void> }): Promise<void> {\n const configPath = path.join(projectRoot, 'src', 'config', 'app.config.ts');\n if (!(await fs.pathExists(configPath))) return;\n\n await ctx.trackModifiedFile(configPath);\n const content = await fs.readFile(configPath, 'utf-8');\n const updated = content.replace(/search:\\s*false/, 'search: true');\n await fs.writeFile(configPath, updated);\n}\n\nfunction types(): string {\n return `${STAMP}\n\nexport interface SearchResult<T = Record<string, unknown>> {\n id: string;\n score: number;\n data: T;\n}\n\nexport interface SearchOptions {\n model: string;\n page?: number;\n limit?: number;\n}\n\nexport interface SearchProvider {\n search<T = Record<string, unknown>>(query: string, options: SearchOptions): Promise<SearchResult<T>[]>;\n index(model: string, id: string, data: Record<string, unknown>): Promise<void>;\n remove(model: string, id: string): Promise<void>;\n}\n`;\n}\n\nfunction schemas(): string {\n return `${STAMP}\nimport { z } from 'zod';\n\nexport const searchParamsSchema = z.object({\n q: z.string().min(1).max(500),\n model: z.string().min(1).max(100),\n page: z.coerce.number().int().positive().default(1),\n limit: z.coerce.number().int().min(1).max(100).default(20),\n});\n\nexport type SearchParams = z.infer<typeof searchParamsSchema>;\n`;\n}\n\nfunction postgresProvider(): string {\n return `${STAMP}\nimport 'server-only';\n\nimport { prisma } from '@/lib/prisma';\nimport type { SearchResult, SearchOptions, SearchProvider } from '../types';\n\nfunction sanitizeQuery(raw: string): string {\n return raw\n .replace(/[^\\\\w\\\\s]/g, '')\n .trim()\n .split(/\\\\s+/)\n .filter(Boolean)\n .join(' & ');\n}\n\nasync function searchPostgres<T = Record<string, unknown>>(\n query: string,\n options: SearchOptions,\n): Promise<SearchResult<T>[]> {\n const sanitized = sanitizeQuery(query);\n if (!sanitized) return [];\n\n const { model, page = 1, limit = 20 } = options;\n const offset = (page - 1) * limit;\n\n const results = await prisma.$queryRaw<Array<{ id: string; rank: number; data: unknown }>>\\`\n SELECT\n id,\n ts_rank(search_vector, plainto_tsquery('english', \\${sanitized})) AS rank,\n row_to_json(t.*) AS data\n FROM \\${prisma.$queryRawUnsafe(\\`\"\\${model}\"\\`)} t\n WHERE search_vector @@ plainto_tsquery('english', \\${sanitized})\n ORDER BY rank DESC\n LIMIT \\${limit}\n OFFSET \\${offset}\n \\`;\n\n return results.map((row) => ({\n id: row.id,\n score: row.rank,\n data: row.data as T,\n }));\n}\n\nexport const postgresSearchProvider: SearchProvider = {\n async search<T = Record<string, unknown>>(query: string, options: SearchOptions) {\n return searchPostgres<T>(query, options);\n },\n\n async index(_model: string, _id: string, _data: Record<string, unknown>) {\n // Postgres tsvector columns are maintained via triggers — no-op\n },\n\n async remove(_model: string, _id: string) {\n // Postgres handles this via cascading deletes — no-op\n },\n};\n`;\n}\n\nfunction serverIndex(): string {\n return `${STAMP}\nimport 'server-only';\n\nimport { appConfig } from '@/config/app.config';\nimport type { SearchProvider } from '../types';\nimport { postgresSearchProvider } from './postgres';\n\nexport async function getSearchProvider(): Promise<SearchProvider> {\n const provider: string = appConfig.services.search.provider;\n\n switch (provider) {\n case 'algolia':\n throw new Error('Algolia provider not installed. Run: yarn add algoliasearch');\n case 'meilisearch':\n throw new Error('Meilisearch provider not installed. Run: yarn add meilisearch');\n case 'postgres':\n case 'local':\n case 'none':\n default:\n return postgresSearchProvider;\n }\n}\n`;\n}\n\nfunction useSearchHook(): string {\n return `${STAMP}\n'use client';\n\nimport { useState, useEffect, useRef, useCallback } from 'react';\nimport type { SearchResult } from '../types';\n\ninterface UseSearchOptions {\n model: string;\n debounceMs?: number;\n limit?: number;\n}\n\ninterface UseSearchReturn<T> {\n query: string;\n setQuery: (q: string) => void;\n results: SearchResult<T>[];\n isLoading: boolean;\n page: number;\n setPage: (p: number) => void;\n error: string | null;\n}\n\nexport function useSearch<T = Record<string, unknown>>(\n options: UseSearchOptions,\n): UseSearchReturn<T> {\n const { model, debounceMs = 300, limit = 20 } = options;\n\n const [query, setQuery] = useState('');\n const [results, setResults] = useState<SearchResult<T>[]>([]);\n const [isLoading, setIsLoading] = useState(false);\n const [page, setPage] = useState(1);\n const [error, setError] = useState<string | null>(null);\n const abortRef = useRef<AbortController | null>(null);\n\n const fetchResults = useCallback(\n async (q: string, p: number) => {\n if (!q.trim()) {\n setResults([]);\n setIsLoading(false);\n return;\n }\n\n abortRef.current?.abort();\n const controller = new AbortController();\n abortRef.current = controller;\n\n setIsLoading(true);\n setError(null);\n\n try {\n const params = new URLSearchParams({\n q,\n model,\n page: String(p),\n limit: String(limit),\n });\n\n const response = await fetch(\\`/api/protected/search?\\${params}\\`, {\n signal: controller.signal,\n });\n\n if (!response.ok) {\n const body = await response.json().catch(() => ({}));\n throw new Error(body.error || 'Search request failed');\n }\n\n const data = await response.json();\n setResults(data.results ?? []);\n } catch (err) {\n if (err instanceof DOMException && err.name === 'AbortError') return;\n setError(err instanceof Error ? err.message : 'Search failed');\n setResults([]);\n } finally {\n if (!controller.signal.aborted) {\n setIsLoading(false);\n }\n }\n },\n [model, limit],\n );\n\n useEffect(() => {\n const timer = setTimeout(() => {\n fetchResults(query, page);\n }, debounceMs);\n\n return () => clearTimeout(timer);\n }, [query, page, debounceMs, fetchResults]);\n\n useEffect(() => {\n setPage(1);\n }, [query]);\n\n return { query, setQuery, results, isLoading, page, setPage, error };\n}\n`;\n}\n\nfunction searchInput(): string {\n return `${STAMP}\n'use client';\n\ninterface SearchInputProps {\n value: string;\n onQueryChange: (query: string) => void;\n placeholder?: string;\n autoFocus?: boolean;\n className?: string;\n}\n\nexport function SearchInput({\n value,\n onQueryChange,\n placeholder = 'Search...',\n autoFocus = false,\n className = '',\n}: SearchInputProps) {\n return (\n <div className={\\`relative \\${className}\\`}>\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n strokeWidth={1.5}\n stroke=\"currentColor\"\n className=\"pointer-events-none absolute left-3 top-1/2 size-5 -translate-y-1/2 text-text-muted\"\n aria-hidden=\"true\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"m21 21-5.197-5.197m0 0A7.5 7.5 0 1 0 5.196 5.196a7.5 7.5 0 0 0 10.607 10.607Z\"\n />\n </svg>\n <input\n type=\"search\"\n value={value}\n onChange={(e) => onQueryChange(e.target.value)}\n placeholder={placeholder}\n autoFocus={autoFocus}\n className=\"w-full rounded-xl border border-border-default bg-surface-card py-2.5 pl-10 pr-4 text-sm text-text-primary placeholder:text-text-muted transition-colors focus:border-brand-primary focus:outline-none focus:ring-2 focus:ring-brand-primary/20\"\n />\n </div>\n );\n}\n`;\n}\n\nfunction componentIndex(): string {\n return `${STAMP}\nexport { SearchInput } from './SearchInput';\n`;\n}\n\nfunction featureIndex(): string {\n return `${STAMP}\nexport type { SearchResult, SearchOptions, SearchProvider } from './types';\nexport { searchParamsSchema } from './validation/schemas';\nexport type { SearchParams } from './validation/schemas';\nexport { SearchInput } from './components';\nexport { useSearch } from './hooks/use-search';\n`;\n}\n\nfunction searchRoute(): string {\n return `${STAMP}\nimport { NextRequest, NextResponse } from 'next/server';\nimport { withAuthNoParams, handleApiError } from '@/lib/mars';\nimport { searchParamsSchema } from '@/features/search/validation/schemas';\nimport { getSearchProvider } from '@/features/search/server';\n\nexport const GET = withAuthNoParams(async (request) => {\n try {\n const url = new URL(request.url);\n const raw = Object.fromEntries(url.searchParams);\n\n const parsed = searchParamsSchema.safeParse(raw);\n if (!parsed.success) {\n return NextResponse.json(\n { error: 'Invalid search parameters', details: parsed.error.flatten().fieldErrors },\n { status: 400 },\n );\n }\n\n const { q, model, page, limit } = parsed.data;\n const provider = await getSearchProvider();\n const results = await provider.search(q, { model, page, limit });\n\n return NextResponse.json({ results, page, limit });\n } catch (error) {\n return handleApiError(error, { endpoint: '/api/protected/search' });\n }\n});\n`;\n}\n","import fs from 'fs-extra';\nimport path from 'node:path';\nimport { log } from '../../utils/logger.js';\nimport { createRollbackContext } from '../../utils/rollback.js';\n\nconst GENERATOR_VERSION = '0.1.0';\nconst STAMP = `// @mars-generated realtime@${GENERATOR_VERSION}`;\n\nexport async function generateRealtime(projectRoot: string): Promise<void> {\n const featureDir = path.join(projectRoot, 'src', 'features', 'realtime');\n\n if (await fs.pathExists(featureDir)) {\n log.error('Realtime feature already exists at src/features/realtime/');\n return;\n }\n\n const ctx = createRollbackContext();\n\n try {\n const files: Record<string, string> = {\n 'src/features/realtime/types.ts': types(),\n 'src/features/realtime/server/index.ts': serverIndex(),\n 'src/features/realtime/server/sse.ts': sseProvider(),\n 'src/features/realtime/hooks/use-event-source.ts': useEventSourceHook(),\n 'src/features/realtime/hooks/index.ts': hooksIndex(),\n 'src/features/realtime/index.ts': featureIndex(),\n 'src/app/api/protected/realtime/stream/route.ts': sseStreamRoute(),\n };\n\n let count = 0;\n for (const [filePath, content] of Object.entries(files)) {\n const fullPath = path.join(projectRoot, filePath);\n ctx.trackCreatedFile(fullPath);\n await fs.ensureDir(path.dirname(fullPath));\n await fs.writeFile(fullPath, content);\n count++;\n }\n\n await setConfigFlag(projectRoot, ctx);\n await ctx.commit();\n\n log.success(`Generated realtime feature with ${count} files`);\n log.blank();\n log.step('src/features/realtime/ — types, server provider, SSE client hook');\n log.step('src/app/api/protected/realtime/stream/ — authenticated SSE endpoint');\n log.blank();\n log.info('Realtime uses Server-Sent Events by default (no external services)');\n log.warn('SSE has a ~30s timeout on serverless (Vercel) — use Pusher or Ably for production');\n log.blank();\n log.step('For Pusher: yarn add pusher pusher-js + set PUSHER_* env vars');\n log.step('For Ably: yarn add ably + set ABLY_API_KEY env var');\n log.blank();\n log.info('Use publish(channel, event, data) from server code to send events');\n log.info('Use useEventSource hook to listen for events in client components');\n log.blank();\n } catch (error) {\n await ctx.rollback();\n throw error;\n }\n}\n\nasync function setConfigFlag(projectRoot: string, ctx: { trackModifiedFile: (p: string) => Promise<void> }): Promise<void> {\n const configPath = path.join(projectRoot, 'src', 'config', 'app.config.ts');\n if (!(await fs.pathExists(configPath))) return;\n\n await ctx.trackModifiedFile(configPath);\n const content = await fs.readFile(configPath, 'utf-8');\n const updated = content.replace(/realtime:\\s*false/, 'realtime: true');\n await fs.writeFile(configPath, updated);\n}\n\nfunction types(): string {\n return `${STAMP}\n\nexport interface RealtimeProvider {\n publish(channel: string, event: string, data: unknown): Promise<void>;\n authorizeChannel?(channel: string, userId: string): Promise<boolean>;\n}\n\nexport interface RealtimeEvent<T = unknown> {\n channel: string;\n event: string;\n data: T;\n timestamp: number;\n}\n\nexport type RealtimeProviderType = 'sse' | 'pusher' | 'ably';\n`;\n}\n\nfunction serverIndex(): string {\n return `${STAMP}\nimport 'server-only';\n\nimport { appConfig } from '@/config/app.config';\nimport type { RealtimeProvider } from '../types';\n\nlet cachedProvider: RealtimeProvider | null = null;\n\nexport async function getRealtimeProvider(): Promise<RealtimeProvider> {\n if (cachedProvider) return cachedProvider;\n\n const providerType: string = appConfig.services.realtime.provider;\n\n switch (providerType) {\n case 'pusher': {\n throw new Error(\n 'Pusher provider not installed. Run: yarn add pusher pusher-js',\n );\n }\n case 'ably': {\n throw new Error(\n 'Ably provider not installed. Run: yarn add ably',\n );\n }\n default: {\n const { SSEProvider } = await import('./sse');\n cachedProvider = new SSEProvider();\n return cachedProvider;\n }\n }\n}\n\nexport async function publish(\n channel: string,\n event: string,\n data: unknown,\n): Promise<void> {\n const provider = await getRealtimeProvider();\n await provider.publish(channel, event, data);\n}\n`;\n}\n\nfunction sseProvider(): string {\n return `${STAMP}\nimport 'server-only';\n\nimport type { RealtimeProvider, RealtimeEvent } from '../types';\n\ntype Subscriber = (event: RealtimeEvent) => void;\n\nconst subscribers = new Map<string, Set<Subscriber>>();\n\nexport class SSEProvider implements RealtimeProvider {\n async publish(channel: string, event: string, data: unknown): Promise<void> {\n const channelSubs = subscribers.get(channel);\n if (!channelSubs || channelSubs.size === 0) return;\n\n const realtimeEvent: RealtimeEvent = {\n channel,\n event,\n data,\n timestamp: Date.now(),\n };\n\n for (const callback of channelSubs) {\n try {\n callback(realtimeEvent);\n } catch {\n // Subscriber errors should not break publish\n }\n }\n }\n}\n\nexport function subscribe(\n channel: string,\n callback: Subscriber,\n): () => void {\n if (!subscribers.has(channel)) {\n subscribers.set(channel, new Set());\n }\n\n const channelSubs = subscribers.get(channel)!;\n channelSubs.add(callback);\n\n return () => {\n channelSubs.delete(callback);\n if (channelSubs.size === 0) {\n subscribers.delete(channel);\n }\n };\n}\n`;\n}\n\nfunction useEventSourceHook(): string {\n return `${STAMP}\n'use client';\n\nimport { useEffect, useRef, useState, useCallback } from 'react';\n\ninterface UseEventSourceOptions {\n channel: string;\n events?: string[];\n onEvent: (event: string, data: unknown) => void;\n enabled?: boolean;\n}\n\nconst MIN_RETRY_MS = 1000;\nconst MAX_RETRY_MS = 30000;\n\nexport function useEventSource({\n channel,\n events,\n onEvent,\n enabled = true,\n}: UseEventSourceOptions) {\n const [connected, setConnected] = useState(false);\n const retryDelay = useRef(MIN_RETRY_MS);\n const retryTimer = useRef<ReturnType<typeof setTimeout> | null>(null);\n const eventSourceRef = useRef<EventSource | null>(null);\n const onEventRef = useRef(onEvent);\n onEventRef.current = onEvent;\n\n const connect = useCallback(() => {\n if (eventSourceRef.current) {\n eventSourceRef.current.close();\n }\n\n const params = new URLSearchParams({ channel });\n if (events && events.length > 0) {\n params.set('events', events.join(','));\n }\n\n const es = new EventSource(\\`/api/protected/realtime/stream?\\${params}\\`);\n eventSourceRef.current = es;\n\n es.onopen = () => {\n setConnected(true);\n retryDelay.current = MIN_RETRY_MS;\n };\n\n es.onmessage = (msg) => {\n try {\n const parsed = JSON.parse(msg.data);\n onEventRef.current(parsed.event, parsed.data);\n } catch {\n // Malformed messages are silently dropped\n }\n };\n\n es.onerror = () => {\n setConnected(false);\n es.close();\n eventSourceRef.current = null;\n\n retryTimer.current = setTimeout(() => {\n retryDelay.current = Math.min(retryDelay.current * 2, MAX_RETRY_MS);\n connect();\n }, retryDelay.current);\n };\n }, [channel, events]);\n\n useEffect(() => {\n if (!enabled) {\n eventSourceRef.current?.close();\n eventSourceRef.current = null;\n setConnected(false);\n return;\n }\n\n connect();\n\n return () => {\n if (retryTimer.current) clearTimeout(retryTimer.current);\n eventSourceRef.current?.close();\n eventSourceRef.current = null;\n setConnected(false);\n };\n }, [enabled, connect]);\n\n return { connected };\n}\n`;\n}\n\nfunction hooksIndex(): string {\n return `${STAMP}\nexport { useEventSource } from './use-event-source';\n`;\n}\n\nfunction featureIndex(): string {\n return `${STAMP}\nexport type {\n RealtimeProvider,\n RealtimeEvent,\n RealtimeProviderType,\n} from './types';\n\nexport { useEventSource } from './hooks';\n`;\n}\n\nfunction sseStreamRoute(): string {\n return `${STAMP}\nimport { NextResponse } from 'next/server';\nimport { withAuthNoParams } from '@/lib/mars';\nimport { subscribe } from '@/features/realtime/server/sse';\n\nexport const dynamic = 'force-dynamic';\n\nexport const GET = withAuthNoParams(async (request) => {\n const channel = request.nextUrl.searchParams.get('channel');\n if (!channel) {\n return NextResponse.json(\n { error: 'Missing channel parameter' },\n { status: 400 },\n );\n }\n\n const eventsParam = request.nextUrl.searchParams.get('events');\n const allowedEvents = eventsParam ? eventsParam.split(',') : null;\n\n const stream = new ReadableStream({\n start(controller) {\n const encoder = new TextEncoder();\n\n const keepAlive = setInterval(() => {\n try {\n controller.enqueue(encoder.encode(': keepalive\\\\n\\\\n'));\n } catch {\n clearInterval(keepAlive);\n }\n }, 15000);\n\n const unsubscribe = subscribe(channel, (event) => {\n if (allowedEvents && !allowedEvents.includes(event.event)) return;\n\n const payload = JSON.stringify({\n event: event.event,\n data: event.data,\n timestamp: event.timestamp,\n });\n\n try {\n controller.enqueue(encoder.encode(\\`data: \\${payload}\\\\n\\\\n\\`));\n } catch {\n clearInterval(keepAlive);\n unsubscribe();\n }\n });\n\n request.signal.addEventListener('abort', () => {\n clearInterval(keepAlive);\n unsubscribe();\n try {\n controller.close();\n } catch {\n // Stream already closed\n }\n });\n },\n });\n\n return new NextResponse(stream, {\n headers: {\n 'Content-Type': 'text/event-stream',\n 'Cache-Control': 'no-cache, no-transform',\n Connection: 'keep-alive',\n 'X-Accel-Buffering': 'no',\n },\n });\n});\n`;\n}\n","import fs from 'fs-extra';\nimport path from 'node:path';\nimport { log } from '../../utils/logger.js';\nimport { createRollbackContext } from '../../utils/rollback.js';\nimport { addDependencies } from '../../utils/dependencies.js';\n\nconst GENERATOR_VERSION = '0.1.0';\nconst STAMP = `// @mars-generated ai@${GENERATOR_VERSION}`;\n\nexport async function generateAI(projectRoot: string): Promise<void> {\n const featureDir = path.join(projectRoot, 'src', 'features', 'ai');\n\n if (await fs.pathExists(featureDir)) {\n log.error('AI feature already exists at src/features/ai/');\n return;\n }\n\n const ctx = createRollbackContext();\n\n try {\n const files: Record<string, string> = {\n 'src/features/ai/types.ts': types(),\n 'src/features/ai/server/index.ts': serverFactory(),\n 'src/features/ai/server/openai-provider.ts': openaiProvider(),\n 'src/features/ai/server/anthropic-provider.ts': anthropicProvider(),\n 'src/features/ai/validation/schemas.ts': schemas(),\n 'src/features/ai/hooks/use-chat.ts': useChatHook(),\n 'src/features/ai/index.ts': barrelExports(),\n 'src/app/api/protected/ai/chat/route.ts': chatRoute(),\n };\n\n let count = 0;\n for (const [filePath, content] of Object.entries(files)) {\n const fullPath = path.join(projectRoot, filePath);\n ctx.trackCreatedFile(fullPath);\n await fs.ensureDir(path.dirname(fullPath));\n await fs.writeFile(fullPath, content);\n count++;\n }\n\n await addDependencies(projectRoot, {\n openai: '^4.0.0',\n '@anthropic-ai/sdk': '^0.30.0',\n });\n await setConfigFlag(projectRoot, ctx);\n await ctx.commit();\n\n log.success(`Generated AI feature with ${count} files`);\n log.blank();\n log.step('src/features/ai/ — types, provider factory, hooks, validation');\n log.step('src/app/api/protected/ai/chat/ — streaming chat endpoint');\n log.blank();\n log.warn('Next steps:');\n log.step('Set the provider in appConfig.services.ai.provider (\"openai\" or \"anthropic\")');\n log.step('Set OPENAI_API_KEY or ANTHROPIC_API_KEY in .env');\n log.step('Use getAIProvider() from server code for chat/streaming');\n log.step('Use useChat() hook for client-side chat interfaces');\n log.blank();\n } catch (error) {\n await ctx.rollback();\n throw error;\n }\n}\n\nasync function setConfigFlag(projectRoot: string, ctx: { trackModifiedFile: (p: string) => Promise<void> }): Promise<void> {\n const configPath = path.join(projectRoot, 'src', 'config', 'app.config.ts');\n if (!(await fs.pathExists(configPath))) return;\n\n await ctx.trackModifiedFile(configPath);\n const content = await fs.readFile(configPath, 'utf-8');\n const updated = content.replace(/ai:\\s*false/, 'ai: true');\n await fs.writeFile(configPath, updated);\n}\n\nfunction types(): string {\n return `${STAMP}\n\nexport interface ChatMessage {\n role: 'system' | 'user' | 'assistant';\n content: string;\n}\n\nexport interface ChatParams {\n messages: ChatMessage[];\n model?: string;\n temperature?: number;\n maxTokens?: number;\n jsonMode?: boolean;\n}\n\nexport interface ChatResponse {\n content: string;\n usage: {\n promptTokens: number;\n completionTokens: number;\n totalTokens: number;\n };\n finishReason: string;\n}\n\nexport interface AIProvider {\n chat(params: ChatParams): Promise<ChatResponse>;\n stream(params: ChatParams): ReadableStream<Uint8Array>;\n}\n`;\n}\n\nfunction serverFactory(): string {\n return `${STAMP}\nimport 'server-only';\n\nimport { appConfig } from '@/config/app.config';\nimport type { AIProvider } from '../types';\n\nlet cachedProvider: AIProvider | null = null;\n\nexport async function getAIProvider(): Promise<AIProvider> {\n if (cachedProvider) return cachedProvider;\n\n const providerName: string = appConfig.services.ai.provider;\n\n switch (providerName) {\n case 'anthropic': {\n const { createAnthropicProvider } = await import('./anthropic-provider');\n cachedProvider = createAnthropicProvider();\n break;\n }\n case 'openai':\n default: {\n const { createOpenAIProvider } = await import('./openai-provider');\n cachedProvider = createOpenAIProvider();\n break;\n }\n }\n\n return cachedProvider;\n}\n`;\n}\n\nfunction openaiProvider(): string {\n return `${STAMP}\nimport 'server-only';\n\nimport OpenAI from 'openai';\nimport type { AIProvider, ChatParams, ChatResponse } from '../types';\n\nlet client: OpenAI | null = null;\n\nfunction getClient(): OpenAI {\n if (client) return client;\n\n const apiKey = process.env.OPENAI_API_KEY;\n if (!apiKey) {\n throw new Error(\n 'OPENAI_API_KEY is not set. Add it to your .env file to use the OpenAI provider.',\n );\n }\n\n client = new OpenAI({ apiKey });\n return client;\n}\n\nfunction getDefaultModel(): string {\n return process.env.OPENAI_MODEL || 'gpt-4o';\n}\n\nexport function createOpenAIProvider(): AIProvider {\n return { chat, stream };\n}\n\nasync function chat(params: ChatParams): Promise<ChatResponse> {\n const openai = getClient();\n\n const response = await openai.chat.completions.create({\n model: params.model || getDefaultModel(),\n messages: params.messages.map((m) => ({ role: m.role, content: m.content })),\n temperature: params.temperature,\n max_tokens: params.maxTokens,\n ...(params.jsonMode && { response_format: { type: 'json_object' } }),\n });\n\n const choice = response.choices[0];\n\n return {\n content: choice.message.content || '',\n usage: {\n promptTokens: response.usage?.prompt_tokens ?? 0,\n completionTokens: response.usage?.completion_tokens ?? 0,\n totalTokens: response.usage?.total_tokens ?? 0,\n },\n finishReason: choice.finish_reason || 'stop',\n };\n}\n\nfunction stream(params: ChatParams): ReadableStream<Uint8Array> {\n const encoder = new TextEncoder();\n\n return new ReadableStream({\n async start(controller) {\n try {\n const openai = getClient();\n\n const response = await openai.chat.completions.create({\n model: params.model || getDefaultModel(),\n messages: params.messages.map((m) => ({ role: m.role, content: m.content })),\n temperature: params.temperature,\n max_tokens: params.maxTokens,\n stream: true,\n });\n\n for await (const chunk of response) {\n const delta = chunk.choices[0]?.delta?.content;\n if (delta) {\n controller.enqueue(encoder.encode(delta));\n }\n }\n\n controller.close();\n } catch (error) {\n controller.error(error);\n }\n },\n });\n}\n`;\n}\n\nfunction anthropicProvider(): string {\n return `${STAMP}\nimport 'server-only';\n\nimport Anthropic from '@anthropic-ai/sdk';\nimport type { AIProvider, ChatParams, ChatResponse, ChatMessage } from '../types';\n\nlet client: Anthropic | null = null;\n\nfunction getClient(): Anthropic {\n if (client) return client;\n\n const apiKey = process.env.ANTHROPIC_API_KEY;\n if (!apiKey) {\n throw new Error(\n 'ANTHROPIC_API_KEY is not set. Add it to your .env file to use the Anthropic provider.',\n );\n }\n\n client = new Anthropic({ apiKey });\n return client;\n}\n\nfunction getDefaultModel(): string {\n return process.env.ANTHROPIC_MODEL || 'claude-sonnet-4-20250514';\n}\n\nfunction extractSystemMessage(messages: ChatMessage[]): {\n system: string | undefined;\n conversationMessages: ChatMessage[];\n} {\n const systemMessages = messages.filter((m) => m.role === 'system');\n const conversationMessages = messages.filter((m) => m.role !== 'system');\n const system = systemMessages.length > 0\n ? systemMessages.map((m) => m.content).join('\\\\n\\\\n')\n : undefined;\n\n return { system, conversationMessages };\n}\n\nexport function createAnthropicProvider(): AIProvider {\n return { chat, stream };\n}\n\nasync function chat(params: ChatParams): Promise<ChatResponse> {\n const anthropic = getClient();\n const { system, conversationMessages } = extractSystemMessage(params.messages);\n\n const response = await anthropic.messages.create({\n model: params.model || getDefaultModel(),\n max_tokens: params.maxTokens || 4096,\n messages: conversationMessages.map((m) => ({\n role: m.role as 'user' | 'assistant',\n content: m.content,\n })),\n ...(system && { system }),\n ...(params.temperature !== undefined && { temperature: params.temperature }),\n });\n\n const textBlock = response.content.find((block) => block.type === 'text');\n\n return {\n content: textBlock?.text || '',\n usage: {\n promptTokens: response.usage.input_tokens,\n completionTokens: response.usage.output_tokens,\n totalTokens: response.usage.input_tokens + response.usage.output_tokens,\n },\n finishReason: response.stop_reason || 'end_turn',\n };\n}\n\nfunction stream(params: ChatParams): ReadableStream<Uint8Array> {\n const encoder = new TextEncoder();\n\n return new ReadableStream({\n async start(controller) {\n try {\n const anthropic = getClient();\n const { system, conversationMessages } = extractSystemMessage(params.messages);\n\n const response = anthropic.messages.stream({\n model: params.model || getDefaultModel(),\n max_tokens: params.maxTokens || 4096,\n messages: conversationMessages.map((m) => ({\n role: m.role as 'user' | 'assistant',\n content: m.content,\n })),\n ...(system && { system }),\n ...(params.temperature !== undefined && { temperature: params.temperature }),\n });\n\n for await (const event of response) {\n if (\n event.type === 'content_block_delta' &&\n event.delta.type === 'text_delta'\n ) {\n controller.enqueue(encoder.encode(event.delta.text));\n }\n }\n\n controller.close();\n } catch (error) {\n controller.error(error);\n }\n },\n });\n}\n`;\n}\n\nfunction schemas(): string {\n return `${STAMP}\nimport { z } from 'zod';\n\nexport const chatSchema = z.object({\n messages: z.array(\n z.object({\n role: z.enum(['system', 'user', 'assistant']),\n content: z.string().min(1).max(32_000),\n }),\n ).min(1).max(100),\n stream: z.boolean().default(true),\n});\n\nexport type ChatInput = z.infer<typeof chatSchema>;\n`;\n}\n\nfunction useChatHook(): string {\n return `${STAMP}\n'use client';\n\nimport { useState, useCallback, useRef } from 'react';\nimport type { ChatMessage } from '../types';\n\ninterface UseChatOptions {\n apiUrl?: string;\n}\n\ninterface UseChatReturn {\n messages: ChatMessage[];\n isLoading: boolean;\n error: string | null;\n send: (content: string) => Promise<void>;\n reset: () => void;\n}\n\nexport function useChat(options: UseChatOptions = {}): UseChatReturn {\n const { apiUrl = '/api/protected/ai/chat' } = options;\n const [messages, setMessages] = useState<ChatMessage[]>([]);\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const abortRef = useRef<AbortController | null>(null);\n\n const send = useCallback(async (content: string) => {\n setError(null);\n setIsLoading(true);\n\n const userMessage: ChatMessage = { role: 'user', content };\n setMessages((prev) => [...prev, userMessage]);\n\n const assistantMessage: ChatMessage = { role: 'assistant', content: '' };\n setMessages((prev) => [...prev, assistantMessage]);\n\n abortRef.current = new AbortController();\n\n try {\n const response = await fetch(apiUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n messages: [...messages, userMessage],\n stream: true,\n }),\n signal: abortRef.current.signal,\n });\n\n if (!response.ok) {\n const errorBody = await response.json().catch(() => null);\n throw new Error(errorBody?.error || \\`Request failed with status \\${response.status}\\`);\n }\n\n if (!response.body) {\n throw new Error('No response body received');\n }\n\n const reader = response.body.getReader();\n const decoder = new TextDecoder();\n let assembled = '';\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n assembled += decoder.decode(value, { stream: true });\n\n setMessages((prev) => {\n const updated = [...prev];\n updated[updated.length - 1] = { role: 'assistant', content: assembled };\n return updated;\n });\n }\n } catch (err) {\n if (err instanceof DOMException && err.name === 'AbortError') return;\n\n const message = err instanceof Error ? err.message : 'An unexpected error occurred';\n setError(message);\n\n setMessages((prev) => prev.slice(0, -1));\n } finally {\n setIsLoading(false);\n abortRef.current = null;\n }\n }, [apiUrl, messages]);\n\n const reset = useCallback(() => {\n abortRef.current?.abort();\n setMessages([]);\n setError(null);\n setIsLoading(false);\n }, []);\n\n return { messages, isLoading, error, send, reset };\n}\n`;\n}\n\nfunction barrelExports(): string {\n return `${STAMP}\nexport type { ChatMessage, ChatParams, ChatResponse, AIProvider } from './types';\nexport { chatSchema, type ChatInput } from './validation/schemas';\nexport { useChat } from './hooks/use-chat';\n`;\n}\n\nfunction chatRoute(): string {\n return `${STAMP}\nimport { NextResponse } from 'next/server';\nimport { handleApiError, withAuthNoParams } from '@/lib/mars';\nimport { getAIProvider } from '@/features/ai/server';\nimport { checkRateLimit, RATE_LIMITS } from '@mars-stack/core/rate-limit';\nimport { getClientIP } from '@mars-stack/core/rate-limit';\nimport { chatSchema } from '@/features/ai/validation/schemas';\n\nexport const POST = withAuthNoParams(async (request) => {\n try {\n const ip = getClientIP(request) ?? request.session.userId;\n await checkRateLimit(ip, { ...RATE_LIMITS.api, identifier: 'ai-chat' });\n\n const body = await request.json();\n const { messages, stream } = chatSchema.parse(body);\n const provider = await getAIProvider();\n\n if (stream) {\n const readableStream = provider.stream({ messages });\n return new NextResponse(readableStream, {\n headers: {\n 'Content-Type': 'text/plain; charset=utf-8',\n 'Transfer-Encoding': 'chunked',\n 'Cache-Control': 'no-cache',\n },\n });\n }\n\n const response = await provider.chat({ messages });\n return NextResponse.json(response);\n } catch (error) {\n return handleApiError(error, { endpoint: '/api/protected/ai/chat' });\n }\n});\n`;\n}\n","import fs from 'fs-extra';\nimport path from 'node:path';\nimport { log } from '../../utils/logger.js';\nimport { createRollbackContext } from '../../utils/rollback.js';\n\nconst GENERATOR_VERSION = '0.1.0';\nconst STAMP = `// @mars-generated cookie-consent@${GENERATOR_VERSION}`;\n\nexport async function generateCookieConsent(projectRoot: string): Promise<void> {\n const featureDir = path.join(projectRoot, 'src', 'features', 'cookie-consent');\n\n if (await fs.pathExists(featureDir)) {\n log.error('Cookie consent feature already exists at src/features/cookie-consent/');\n return;\n }\n\n const ctx = createRollbackContext();\n\n try {\n const files: Record<string, string> = {\n 'src/features/cookie-consent/types.ts': types(),\n 'src/features/cookie-consent/hooks/use-consent.ts': useConsent(),\n 'src/features/cookie-consent/components/CookieConsentBanner.tsx': cookieConsentBanner(),\n 'src/features/cookie-consent/components/CookiePreferencesDialog.tsx': cookiePreferencesDialog(),\n 'src/features/cookie-consent/components/index.ts': componentsIndex(),\n 'src/features/cookie-consent/index.ts': featureIndex(),\n };\n\n let count = 0;\n for (const [filePath, content] of Object.entries(files)) {\n const fullPath = path.join(projectRoot, filePath);\n ctx.trackCreatedFile(fullPath);\n await fs.ensureDir(path.dirname(fullPath));\n await fs.writeFile(fullPath, content);\n count++;\n }\n\n await setConfigFlag(projectRoot, ctx);\n await ctx.commit();\n\n log.success(`Generated cookie consent feature with ${count} files`);\n log.blank();\n log.step('src/features/cookie-consent/types.ts — ConsentStatus, ConsentPreferences');\n log.step('src/features/cookie-consent/hooks/use-consent.ts — useConsent hook');\n log.step('src/features/cookie-consent/components/CookieConsentBanner.tsx — banner');\n log.step('src/features/cookie-consent/components/CookiePreferencesDialog.tsx — preferences modal');\n log.blank();\n log.warn('Complete setup:');\n log.step('Add <CookieConsentBanner /> to your root layout');\n log.step('Optionally add <CookiePreferencesDialog /> for granular consent management');\n log.step('Check consent status with useConsent() before loading tracking scripts');\n log.blank();\n } catch (error) {\n await ctx.rollback();\n throw error;\n }\n}\n\nasync function setConfigFlag(projectRoot: string, ctx: { trackModifiedFile: (p: string) => Promise<void> }): Promise<void> {\n const configPath = path.join(projectRoot, 'src', 'config', 'app.config.ts');\n if (!(await fs.pathExists(configPath))) return;\n\n await ctx.trackModifiedFile(configPath);\n const content = await fs.readFile(configPath, 'utf-8');\n const updated = content.replace(/cookieConsent:\\s*false/, 'cookieConsent: true');\n await fs.writeFile(configPath, updated);\n}\n\nfunction types(): string {\n return `${STAMP}\n\nexport type ConsentStatus = 'granted' | 'denied' | 'pending';\n\nexport interface ConsentPreferences {\n analytics: boolean;\n marketing: boolean;\n functional: boolean;\n}\n`;\n}\n\nfunction useConsent(): string {\n return `${STAMP}\n'use client';\n\nimport { useCallback, useEffect, useState } from 'react';\nimport type { ConsentPreferences, ConsentStatus } from '../types';\n\nconst STORAGE_KEY = 'mars-cookie-consent';\n\nconst DEFAULT_PREFERENCES: ConsentPreferences = {\n analytics: false,\n marketing: false,\n functional: false,\n};\n\nconst ALL_GRANTED: ConsentPreferences = {\n analytics: true,\n marketing: true,\n functional: true,\n};\n\ninterface StoredConsent {\n status: ConsentStatus;\n preferences: ConsentPreferences;\n}\n\nfunction readStored(): StoredConsent | null {\n if (typeof window === 'undefined') return null;\n try {\n const raw = localStorage.getItem(STORAGE_KEY);\n if (!raw) return null;\n const parsed = JSON.parse(raw) as StoredConsent;\n if (\n parsed &&\n typeof parsed.status === 'string' &&\n parsed.status !== 'pending' &&\n parsed.preferences &&\n typeof parsed.preferences.analytics === 'boolean' &&\n typeof parsed.preferences.marketing === 'boolean' &&\n typeof parsed.preferences.functional === 'boolean'\n ) {\n return parsed;\n }\n } catch {\n // ignore\n }\n return null;\n}\n\nfunction writeStored(data: StoredConsent): void {\n if (typeof window === 'undefined') return;\n try {\n localStorage.setItem(STORAGE_KEY, JSON.stringify(data));\n } catch {\n // ignore\n }\n}\n\nexport function useConsent() {\n const [status, setStatus] = useState<ConsentStatus>('pending');\n const [preferences, setPreferencesState] = useState<ConsentPreferences>(DEFAULT_PREFERENCES);\n const [mounted, setMounted] = useState(false);\n\n useEffect(() => {\n const stored = readStored();\n if (stored) {\n setStatus(stored.status);\n setPreferencesState(stored.preferences);\n }\n setMounted(true);\n }, []);\n\n const accept = useCallback(() => {\n const data: StoredConsent = { status: 'granted', preferences: ALL_GRANTED };\n writeStored(data);\n setStatus('granted');\n setPreferencesState(ALL_GRANTED);\n }, []);\n\n const decline = useCallback(() => {\n const data: StoredConsent = { status: 'denied', preferences: DEFAULT_PREFERENCES };\n writeStored(data);\n setStatus('denied');\n setPreferencesState(DEFAULT_PREFERENCES);\n }, []);\n\n const updatePreferences = useCallback((next: Partial<ConsentPreferences>) => {\n const merged: ConsentPreferences = { ...DEFAULT_PREFERENCES, ...next };\n const data: StoredConsent = { status: 'granted', preferences: merged };\n writeStored(data);\n setStatus('granted');\n setPreferencesState(merged);\n }, []);\n\n return { status, preferences, mounted, accept, decline, updatePreferences };\n}\n`;\n}\n\nfunction cookieConsentBanner(): string {\n return `${STAMP}\n'use client';\n\nimport { useConsent } from '../hooks/use-consent';\nimport { Button } from '@mars-stack/ui';\n\nexport function CookieConsentBanner() {\n const { status, mounted, accept, decline } = useConsent();\n\n if (!mounted || status !== 'pending') return null;\n\n return (\n <div\n role=\"dialog\"\n aria-labelledby=\"cookie-consent-title\"\n aria-describedby=\"cookie-consent-description\"\n className=\"fixed bottom-0 left-0 right-0 z-50 border-t border-border-default bg-surface-card p-4 shadow-lg sm:p-6\"\n >\n <div className=\"mx-auto flex max-w-4xl flex-col gap-4 sm:flex-row sm:items-center sm:justify-between\">\n <div className=\"flex-1\">\n <h2 id=\"cookie-consent-title\" className=\"text-base font-semibold text-text-primary\">\n Cookie usage\n </h2>\n <p id=\"cookie-consent-description\" className=\"mt-1 text-sm text-text-secondary\">\n We use cookies to improve your experience, analyze traffic, and personalize content. You can accept all or\n decline optional cookies.\n </p>\n </div>\n <div className=\"flex shrink-0 flex-col gap-2 sm:flex-row sm:items-center\">\n <Button variant=\"secondary\" size=\"sm\" onClick={decline}>\n Decline\n </Button>\n <Button variant=\"primary\" size=\"sm\" onClick={accept}>\n Accept\n </Button>\n </div>\n </div>\n </div>\n );\n}\n`;\n}\n\nfunction cookiePreferencesDialog(): string {\n return `${STAMP}\n'use client';\n\nimport { useState, useEffect } from 'react';\nimport { Modal, Button } from '@mars-stack/ui';\nimport type { ConsentPreferences } from '../types';\n\ninterface CookiePreferencesDialogProps {\n open: boolean;\n onClose: () => void;\n currentPreferences: ConsentPreferences;\n onSave: (preferences: ConsentPreferences) => void;\n}\n\nfunction PreferenceRow({\n label,\n description,\n checked,\n onChange,\n}: {\n label: string;\n description: string;\n checked: boolean;\n onChange: (checked: boolean) => void;\n}) {\n return (\n <div className=\"flex items-start justify-between gap-4 py-3\">\n <div>\n <p className=\"text-sm font-medium text-text-primary\">{label}</p>\n <p className=\"mt-0.5 text-xs text-text-secondary\">{description}</p>\n </div>\n <label className=\"relative inline-flex shrink-0 cursor-pointer items-center\">\n <input\n type=\"checkbox\"\n checked={checked}\n onChange={(e) => onChange(e.target.checked)}\n className=\"peer sr-only\"\n role=\"switch\"\n />\n <div className=\"h-6 w-11 rounded-full bg-surface-secondary transition-colors peer-checked:bg-brand-primary\" />\n <div className=\"absolute left-1 top-1 h-4 w-4 rounded-full bg-surface-primary shadow-sm transition-transform peer-checked:translate-x-5\" />\n </label>\n </div>\n );\n}\n\nexport function CookiePreferencesDialog({ open, onClose, currentPreferences, onSave }: CookiePreferencesDialogProps) {\n const [preferences, setPreferences] = useState<ConsentPreferences>(currentPreferences);\n\n useEffect(() => {\n if (open) {\n setPreferences(currentPreferences);\n }\n }, [open, currentPreferences]);\n\n const handleSave = () => {\n onSave(preferences);\n onClose();\n };\n\n return (\n <Modal open={open} onClose={onClose} title=\"Cookie preferences\">\n <div className=\"space-y-1\">\n <p className=\"text-sm text-text-secondary\">\n Choose which categories of cookies you want to allow.\n </p>\n <div className=\"mt-4 divide-y divide-border-default\">\n <PreferenceRow\n label=\"Functional\"\n description=\"Essential for the site to work\"\n checked={preferences.functional}\n onChange={(v) => setPreferences((p) => ({ ...p, functional: v }))}\n />\n <PreferenceRow\n label=\"Analytics\"\n description=\"Help us understand how visitors use the site\"\n checked={preferences.analytics}\n onChange={(v) => setPreferences((p) => ({ ...p, analytics: v }))}\n />\n <PreferenceRow\n label=\"Marketing\"\n description=\"Used for personalized ads and campaigns\"\n checked={preferences.marketing}\n onChange={(v) => setPreferences((p) => ({ ...p, marketing: v }))}\n />\n </div>\n <div className=\"mt-6 flex justify-end gap-2\">\n <Button variant=\"subtle\" size=\"sm\" onClick={onClose}>\n Cancel\n </Button>\n <Button variant=\"primary\" size=\"sm\" onClick={handleSave}>\n Save\n </Button>\n </div>\n </div>\n </Modal>\n );\n}\n`;\n}\n\nfunction componentsIndex(): string {\n return `${STAMP}\nexport { CookieConsentBanner } from './CookieConsentBanner';\nexport { CookiePreferencesDialog } from './CookiePreferencesDialog';\n`;\n}\n\nfunction featureIndex(): string {\n return `${STAMP}\nexport type { ConsentStatus, ConsentPreferences } from './types';\nexport { useConsent } from './hooks/use-consent';\nexport { CookieConsentBanner, CookiePreferencesDialog } from './components';\n`;\n}\n","import fs from 'fs-extra';\nimport path from 'node:path';\nimport { log } from '../../utils/logger.js';\nimport { createRollbackContext } from '../../utils/rollback.js';\n\nconst GENERATOR_VERSION = '0.1.0';\nconst STAMP = `// @mars-generated coming-soon@${GENERATOR_VERSION}`;\n\nexport async function generateComingSoon(projectRoot: string): Promise<void> {\n const featureDir = path.join(projectRoot, 'src', 'features', 'coming-soon');\n\n if (await fs.pathExists(featureDir)) {\n log.error('Coming soon feature already exists at src/features/coming-soon/');\n return;\n }\n\n const ctx = createRollbackContext();\n\n try {\n const files: Record<string, string> = {\n 'src/features/coming-soon/types.ts': types(),\n 'src/features/coming-soon/validation/schemas.ts': schemas(),\n 'src/features/coming-soon/components/ComingSoonPage.tsx': comingSoonPage(),\n 'src/features/coming-soon/components/index.ts': componentIndex(),\n 'src/features/coming-soon/index.ts': barrelExports(),\n 'src/app/coming-soon/page.tsx': pageRoute(),\n 'src/app/api/waitlist/route.ts': waitlistRoute(),\n };\n\n let count = 0;\n for (const [filePath, content] of Object.entries(files)) {\n const fullPath = path.join(projectRoot, filePath);\n ctx.trackCreatedFile(fullPath);\n await fs.ensureDir(path.dirname(fullPath));\n await fs.writeFile(fullPath, content);\n count++;\n }\n\n await setConfigFlag(projectRoot, ctx);\n await ctx.commit();\n\n log.success(`Generated coming soon feature with ${count} files`);\n log.blank();\n log.step('src/features/coming-soon/ — types, validation, components');\n log.step('src/app/coming-soon/ — landing page');\n log.step('src/app/api/waitlist/ — waitlist signup endpoint');\n log.blank();\n log.step('Visit /coming-soon to see the page');\n log.step('Wire up the waitlist API to your preferred email service');\n log.step('To use as the default landing page, update your middleware or root redirect');\n log.blank();\n } catch (error) {\n await ctx.rollback();\n throw error;\n }\n}\n\nasync function setConfigFlag(\n projectRoot: string,\n ctx: { trackModifiedFile: (p: string) => Promise<void> },\n): Promise<void> {\n const configPath = path.join(projectRoot, 'src', 'config', 'app.config.ts');\n if (!(await fs.pathExists(configPath))) return;\n\n await ctx.trackModifiedFile(configPath);\n const content = await fs.readFile(configPath, 'utf-8');\n const updated = content.replace(/comingSoon:\\s*false/, 'comingSoon: true');\n await fs.writeFile(configPath, updated);\n}\n\nfunction types(): string {\n return `${STAMP}\n\nexport interface WaitlistEntry {\n email: string;\n createdAt: Date;\n}\n`;\n}\n\nfunction schemas(): string {\n return `${STAMP}\nimport { z } from 'zod';\n\nexport const waitlistSchema = z.object({\n email: z.string().email('Please enter a valid email address'),\n});\n`;\n}\n\nfunction comingSoonPage(): string {\n return `${STAMP}\n'use client';\n\nimport { useState } from 'react';\nimport { appConfig } from '@/config/app.config';\n\nexport function ComingSoonPage() {\n const [email, setEmail] = useState('');\n const [submitted, setSubmitted] = useState(false);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n async function handleSubmit(e: React.FormEvent<HTMLFormElement>) {\n e.preventDefault();\n setError(null);\n setLoading(true);\n\n try {\n const res = await fetch('/api/waitlist', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ email }),\n });\n\n const data = await res.json();\n\n if (!res.ok) {\n setError(data.error ?? 'Something went wrong');\n setLoading(false);\n return;\n }\n\n setSubmitted(true);\n setEmail('');\n } catch {\n setError('Failed to join the waitlist');\n } finally {\n setLoading(false);\n }\n }\n\n return (\n <div className=\"relative min-h-screen bg-surface-background bg-gradient-to-br from-surface-background via-surface-card/30 to-surface-background\">\n <div className=\"flex min-h-screen flex-col items-center justify-center px-4 py-16 sm:px-6 lg:px-8\">\n <div className=\"mx-auto max-w-2xl text-center\">\n <h1 className=\"text-5xl font-bold tracking-tight text-text-primary sm:text-6xl md:text-7xl\">\n {appConfig.name}\n </h1>\n <h2 className=\"mt-6 text-3xl font-semibold text-text-primary sm:text-4xl\">\n Coming Soon\n </h2>\n <p className=\"mt-4 text-lg text-text-secondary sm:text-xl\">\n {appConfig.tagline || appConfig.description}\n </p>\n\n <div className=\"mt-12\">\n {submitted ? (\n <p className=\"rounded-xl border border-border-default bg-surface-card px-6 py-4 text-text-primary\">\n Thanks for joining! We&apos;ll notify you when we launch.\n </p>\n ) : (\n <form onSubmit={handleSubmit} className=\"flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-center\">\n <input\n type=\"email\"\n value={email}\n onChange={(e) => setEmail(e.target.value)}\n placeholder=\"Enter your email\"\n required\n className=\"w-full rounded-lg border border-border-default bg-surface-card px-4 py-3 text-text-primary placeholder:text-text-muted focus:border-brand-primary focus:outline-none focus:ring-2 focus:ring-brand-primary/20 sm:w-72\"\n disabled={loading}\n />\n <button\n type=\"submit\"\n disabled={loading}\n className=\"shrink-0 rounded-lg bg-brand-primary px-6 py-3 font-medium text-text-on-brand transition-colors hover:opacity-90 disabled:opacity-50\"\n >\n {loading ? 'Joining…' : 'Join waitlist'}\n </button>\n </form>\n )}\n {error && (\n <p className=\"mt-3 text-sm text-text-error\" role=\"alert\">\n {error}\n </p>\n )}\n </div>\n </div>\n </div>\n </div>\n );\n}\n`;\n}\n\nfunction componentIndex(): string {\n return `${STAMP}\nexport { ComingSoonPage } from './ComingSoonPage';\n`;\n}\n\nfunction barrelExports(): string {\n return `${STAMP}\nexport { ComingSoonPage } from './components';\nexport type { WaitlistEntry } from './types';\n`;\n}\n\nfunction pageRoute(): string {\n return `${STAMP}\nimport type { Metadata } from 'next';\nimport { ComingSoonPage } from '@/features/coming-soon';\n\nexport const metadata: Metadata = {\n title: 'Coming Soon',\n};\n\nexport default function ComingSoonRoute() {\n return <ComingSoonPage />;\n}\n`;\n}\n\nfunction waitlistRoute(): string {\n return `${STAMP}\nimport { NextResponse } from 'next/server';\nimport { waitlistSchema } from '@/features/coming-soon/validation/schemas';\n\nexport async function POST(request: Request) {\n try {\n const body = await request.json();\n const parsed = waitlistSchema.safeParse(body);\n\n if (!parsed.success) {\n return NextResponse.json(\n { error: parsed.error.issues[0]?.message ?? 'Invalid input' },\n { status: 400 },\n );\n }\n\n const { email } = parsed.data;\n\n // Stub: log to console (local-first). Wire up to your email service for production.\n console.log('[waitlist] New signup:', email);\n\n return NextResponse.json({ success: true });\n } catch {\n return NextResponse.json(\n { error: 'Invalid request body' },\n { status: 400 },\n );\n }\n}\n`;\n}\n","import fs from 'fs-extra';\nimport path from 'node:path';\nimport { log } from '../../utils/logger.js';\nimport { createRollbackContext } from '../../utils/rollback.js';\nimport { addDependencies } from '../../utils/dependencies.js';\n\nconst GENERATOR_VERSION = '0.1.0';\nconst STAMP = `// @mars-generated sentry@${GENERATOR_VERSION}`;\n\nexport async function generateSentry(projectRoot: string): Promise<void> {\n const featureDir = path.join(projectRoot, 'src', 'features', 'sentry');\n\n if (await fs.pathExists(featureDir)) {\n log.error('Sentry feature already exists at src/features/sentry/');\n return;\n }\n\n const ctx = createRollbackContext();\n\n try {\n const files: Record<string, string> = {\n 'src/features/sentry/types.ts': types(),\n 'src/features/sentry/client-init.ts': clientInit(),\n 'src/features/sentry/server-init.ts': serverInit(),\n 'src/features/sentry/components/ErrorBoundary.tsx': errorBoundary(),\n 'src/features/sentry/components/index.ts': componentsIndex(),\n 'src/features/sentry/index.ts': barrelExports(),\n };\n\n let count = 0;\n for (const [filePath, content] of Object.entries(files)) {\n const fullPath = path.join(projectRoot, filePath);\n ctx.trackCreatedFile(fullPath);\n await fs.ensureDir(path.dirname(fullPath));\n await fs.writeFile(fullPath, content);\n count++;\n }\n\n await addDependencies(projectRoot, { '@sentry/nextjs': '^8.0.0' });\n await setConfigFlag(projectRoot, ctx);\n await ctx.commit();\n\n log.success(`Generated sentry feature with ${count} files`);\n log.blank();\n log.step('src/features/sentry/ — types, client-init, server-init, ErrorBoundary');\n log.blank();\n log.warn('Optional: run npx @sentry/wizard@latest -i nextjs for full setup');\n log.blank();\n log.warn('Next steps:');\n log.step('Set NEXT_PUBLIC_SENTRY_DSN and SENTRY_DSN environment variables');\n log.step('Wrap pages or layouts with <ErrorBoundary> for graceful error handling');\n log.step('Import client-init and server-init in your instrumentation files');\n log.blank();\n } catch (error) {\n await ctx.rollback();\n throw error;\n }\n}\n\nasync function setConfigFlag(projectRoot: string, ctx: { trackModifiedFile: (p: string) => Promise<void> }): Promise<void> {\n const configPath = path.join(projectRoot, 'src', 'config', 'app.config.ts');\n if (!(await fs.pathExists(configPath))) return;\n\n await ctx.trackModifiedFile(configPath);\n const content = await fs.readFile(configPath, 'utf-8');\n const updated = content.replace(/sentry:\\s*false/, 'sentry: true');\n await fs.writeFile(configPath, updated);\n}\n\nfunction types(): string {\n return `${STAMP}\n\nexport interface SentryConfig {\n dsn: string;\n environment: string;\n tracesSampleRate: number;\n enabled: boolean;\n}\n`;\n}\n\nfunction clientInit(): string {\n return `${STAMP}\nimport * as Sentry from '@sentry/nextjs';\n\nconst dsn = process.env.NEXT_PUBLIC_SENTRY_DSN;\n\nif (dsn) {\n Sentry.init({\n dsn,\n environment: process.env.NODE_ENV ?? 'development',\n tracesSampleRate: process.env.NODE_ENV === 'development' ? 1.0 : 0.1,\n enabled: !!dsn,\n });\n}\n`;\n}\n\nfunction serverInit(): string {\n return `${STAMP}\nimport 'server-only';\nimport * as Sentry from '@sentry/nextjs';\n\nconst dsn = process.env.SENTRY_DSN;\n\nif (dsn) {\n Sentry.init({\n dsn,\n environment: process.env.NODE_ENV ?? 'development',\n tracesSampleRate: process.env.NODE_ENV === 'development' ? 1.0 : 0.1,\n enabled: !!dsn,\n });\n}\n`;\n}\n\nfunction errorBoundary(): string {\n return `${STAMP}\n'use client';\n\nimport { Component, type ErrorInfo, type ReactNode } from 'react';\nimport * as Sentry from '@sentry/nextjs';\n\ninterface ErrorBoundaryProps {\n children: ReactNode;\n fallback?: ReactNode | ((error: Error, reset: () => void) => ReactNode);\n}\n\ninterface ErrorBoundaryState {\n hasError: boolean;\n error: Error | null;\n}\n\nexport class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {\n constructor(props: ErrorBoundaryProps) {\n super(props);\n this.state = { hasError: false, error: null };\n }\n\n static getDerivedStateFromError(error: Error): ErrorBoundaryState {\n return { hasError: true, error };\n }\n\n componentDidCatch(error: Error, errorInfo: ErrorInfo): void {\n Sentry.captureException(error, { extra: { componentStack: errorInfo.componentStack } });\n }\n\n reset = (): void => {\n this.setState({ hasError: false, error: null });\n };\n\n render(): ReactNode {\n if (this.state.hasError && this.state.error) {\n if (typeof this.props.fallback === 'function') {\n return this.props.fallback(this.state.error, this.reset);\n }\n if (this.props.fallback) {\n return this.props.fallback;\n }\n return <DefaultErrorFallback error={this.state.error} reset={this.reset} />;\n }\n return this.props.children;\n }\n}\n\nfunction DefaultErrorFallback({ error, reset }: { error: Error; reset: () => void }) {\n return (\n <div className=\"flex min-h-[300px] flex-col items-center justify-center gap-4 p-6\">\n <div className=\"rounded-xl border border-border-default bg-surface-card p-6 text-center\">\n <h2 className=\"mb-2 text-lg font-semibold text-text-primary\">Something went wrong</h2>\n <p className=\"mb-4 text-sm text-text-secondary\">\n {error.message || 'An unexpected error occurred.'}\n </p>\n <button\n type=\"button\"\n onClick={reset}\n className=\"rounded-lg bg-brand-primary px-4 py-2 text-sm font-medium text-text-inverse transition-colors hover:bg-brand-primary-hover focus:outline-none focus:ring-2 focus:ring-brand-primary focus:ring-offset-2\"\n >\n Try Again\n </button>\n </div>\n </div>\n );\n}\n`;\n}\n\nfunction componentsIndex(): string {\n return `${STAMP}\nexport { ErrorBoundary } from './ErrorBoundary';\n`;\n}\n\nfunction barrelExports(): string {\n return `${STAMP}\n\nexport type { SentryConfig } from './types';\nexport { ErrorBoundary } from './components';\n`;\n}\n","import fs from 'fs-extra';\nimport path from 'node:path';\nimport { log } from '../../utils/logger.js';\nimport { createRollbackContext } from '../../utils/rollback.js';\n\nconst GENERATOR_VERSION = '0.1.0';\nconst STAMP = `// @mars-generated feature-flags@${GENERATOR_VERSION}`;\n\nexport async function generateFeatureFlags(projectRoot: string): Promise<void> {\n const featureDir = path.join(projectRoot, 'src', 'features', 'feature-flags');\n\n if (await fs.pathExists(featureDir)) {\n log.error('Feature flags feature already exists at src/features/feature-flags/');\n return;\n }\n\n const ctx = createRollbackContext();\n\n try {\n const files: Record<string, string> = {\n 'src/features/feature-flags/types.ts': types(),\n 'src/features/feature-flags/server/local-provider.ts': localProvider(),\n 'src/features/feature-flags/server/index.ts': serverIndex(),\n 'src/features/feature-flags/hooks/use-feature-flag.ts': useFeatureFlag(),\n 'src/features/feature-flags/components/FeatureGate.tsx': featureGate(),\n 'src/features/feature-flags/components/index.ts': componentsIndex(),\n 'src/features/feature-flags/index.ts': featureIndex(),\n 'src/config/feature-flags.json': featureFlagsJson(),\n 'src/app/api/protected/feature-flags/route.ts': apiRoute(),\n };\n\n let count = 0;\n for (const [filePath, content] of Object.entries(files)) {\n const fullPath = path.join(projectRoot, filePath);\n ctx.trackCreatedFile(fullPath);\n await fs.ensureDir(path.dirname(fullPath));\n await fs.writeFile(fullPath, content);\n count++;\n }\n\n await setConfigFlag(projectRoot, ctx);\n await ctx.commit();\n\n log.success(`Generated feature flags feature with ${count} files`);\n log.blank();\n log.step('Feature flags use a local JSON provider by default');\n log.step('Edit src/config/feature-flags.json to define flags');\n log.step('Use getFlag(\\'my-flag\\', false) in server code');\n log.step('Use useFeatureFlag(\\'my-flag\\', false) in client code');\n log.step('Use <FeatureGate flag=\"my-flag\"> for conditional rendering');\n log.step('For LaunchDarkly/PostHog, install their SDK and update the provider');\n log.blank();\n } catch (error) {\n await ctx.rollback();\n throw error;\n }\n}\n\nasync function setConfigFlag(projectRoot: string, ctx: { trackModifiedFile: (p: string) => Promise<void> }): Promise<void> {\n const configPath = path.join(projectRoot, 'src', 'config', 'app.config.ts');\n if (!(await fs.pathExists(configPath))) return;\n\n await ctx.trackModifiedFile(configPath);\n const content = await fs.readFile(configPath, 'utf-8');\n const updated = content.replace(/featureFlags:\\s*false/, 'featureFlags: true');\n await fs.writeFile(configPath, updated);\n}\n\nfunction types(): string {\n return `${STAMP}\n\nexport type FeatureFlagProvider = 'local' | 'launchdarkly' | 'posthog';\n\nexport type FeatureFlagValue = boolean | string | number;\n\nexport interface FeatureFlagContext {\n userId?: string;\n email?: string;\n custom?: Record<string, string | number | boolean>;\n}\n`;\n}\n\nfunction localProvider(): string {\n return `${STAMP}\nimport 'server-only';\n\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport type { FeatureFlagValue } from '../types';\n\nconst CONFIG_PATH = path.join(process.cwd(), 'src', 'config', 'feature-flags.json');\n\ninterface FlagsConfig {\n flags: Record<string, FeatureFlagValue>;\n}\n\nfunction loadFlags(): Record<string, FeatureFlagValue> {\n try {\n if (fs.existsSync(CONFIG_PATH)) {\n const raw = fs.readFileSync(CONFIG_PATH, 'utf-8');\n const parsed: FlagsConfig = JSON.parse(raw);\n return parsed.flags ?? {};\n }\n } catch {\n // Fallback to empty config\n }\n return {};\n}\n\nexport function getLocalFlag(flagKey: string, defaultValue: FeatureFlagValue): FeatureFlagValue {\n const flags = loadFlags();\n return flagKey in flags ? flags[flagKey] : defaultValue;\n}\n`;\n}\n\nfunction serverIndex(): string {\n return `${STAMP}\nimport 'server-only';\n\nimport type { FeatureFlagValue, FeatureFlagContext } from '../types';\nimport { getLocalFlag } from './local-provider';\n\nexport interface FlagProvider {\n getFlag(key: string, defaultValue: FeatureFlagValue, context?: FeatureFlagContext): FeatureFlagValue;\n}\n\nfunction getLocalProvider(): FlagProvider {\n return {\n getFlag(key, defaultValue) {\n return getLocalFlag(key, defaultValue);\n },\n };\n}\n\nlet cachedProvider: FlagProvider | null = null;\n\nfunction getProvider(): FlagProvider {\n if (!cachedProvider) {\n cachedProvider = getLocalProvider();\n }\n return cachedProvider;\n}\n\nexport function getFlag(\n flagKey: string,\n defaultValue: FeatureFlagValue,\n context?: FeatureFlagContext,\n): FeatureFlagValue {\n const provider = getProvider();\n return provider.getFlag(flagKey, defaultValue, context);\n}\n`;\n}\n\nfunction useFeatureFlag(): string {\n return `${STAMP}\n'use client';\n\nimport { useState, useEffect } from 'react';\nimport type { FeatureFlagValue } from '../types';\n\nconst cache = new Map<string, FeatureFlagValue>();\n\nasync function fetchFlag(flagKey: string): Promise<FeatureFlagValue> {\n const cached = cache.get(flagKey);\n if (cached !== undefined) {\n return cached;\n }\n\n const res = await fetch(\\`/api/protected/feature-flags?key=\\${encodeURIComponent(flagKey)}\\`);\n if (!res.ok) {\n throw new Error(\\`Failed to fetch flag \\${flagKey}\\`);\n }\n const json = await res.json();\n const value = json.value as FeatureFlagValue;\n cache.set(flagKey, value);\n return value;\n}\n\nexport function useFeatureFlag(flagKey: string, defaultValue: FeatureFlagValue): FeatureFlagValue | undefined {\n const [value, setValue] = useState<FeatureFlagValue | undefined>(() => cache.get(flagKey) ?? undefined);\n const [isLoading, setIsLoading] = useState(() => !cache.has(flagKey));\n\n useEffect(() => {\n let cancelled = false;\n\n if (cache.has(flagKey)) {\n setValue(cache.get(flagKey));\n setIsLoading(false);\n return;\n }\n\n fetchFlag(flagKey).then((v) => {\n if (!cancelled) {\n setValue(v);\n setIsLoading(false);\n }\n }).catch(() => {\n if (!cancelled) {\n setValue(defaultValue);\n setIsLoading(false);\n }\n });\n\n return () => {\n cancelled = true;\n };\n }, [flagKey, defaultValue]);\n\n return isLoading ? undefined : (value ?? defaultValue);\n}\n`;\n}\n\nfunction featureGate(): string {\n return `${STAMP}\n'use client';\n\nimport { useFeatureFlag } from '../hooks/use-feature-flag';\n\ninterface FeatureGateProps {\n flag: string;\n fallback?: React.ReactNode;\n children: React.ReactNode;\n defaultValue?: boolean;\n}\n\nexport function FeatureGate({ flag, fallback = null, children, defaultValue = false }: FeatureGateProps) {\n const value = useFeatureFlag(flag, defaultValue);\n\n if (value === undefined) {\n return null;\n }\n\n const enabled = value === true || (typeof value === 'string' && value.toLowerCase() === 'true') || (typeof value === 'number' && value !== 0);\n\n return enabled ? <>{children}</> : <>{fallback}</>;\n}\n`;\n}\n\nfunction componentsIndex(): string {\n return `${STAMP}\nexport { FeatureGate } from './FeatureGate';\n`;\n}\n\nfunction featureIndex(): string {\n return `${STAMP}\nexport { getFlag } from './server';\nexport { useFeatureFlag } from './hooks/use-feature-flag';\nexport { FeatureGate } from './components';\nexport type { FeatureFlagProvider, FeatureFlagValue, FeatureFlagContext } from './types';\n`;\n}\n\nfunction featureFlagsJson(): string {\n return `{\n \"flags\": {}\n}\n`;\n}\n\nfunction apiRoute(): string {\n return `${STAMP}\nimport { NextRequest, NextResponse } from 'next/server';\nimport { z } from 'zod';\nimport { withAuthNoParams, handleApiError } from '@/lib/mars';\nimport { getFlag } from '@/features/feature-flags/server';\n\nconst querySchema = z.object({\n key: z.string().min(1, 'Flag key is required'),\n});\n\nexport const GET = withAuthNoParams(async (request) => {\n try {\n const url = new URL(request.url);\n const parsed = querySchema.safeParse({ key: url.searchParams.get('key') });\n\n if (!parsed.success) {\n return NextResponse.json(\n { error: 'Invalid parameters', details: parsed.error.flatten().fieldErrors },\n { status: 400 },\n );\n }\n\n const { key } = parsed.data;\n const value = getFlag(key, false);\n\n return NextResponse.json({ value });\n } catch (error) {\n return handleApiError(error, { endpoint: '/api/protected/feature-flags' });\n }\n});\n`;\n}\n","import { Command } from 'commander';\nimport { createCommand } from './commands/create.js';\nimport { doctorCommand } from './commands/doctor.js';\nimport { addFeatureCommand, addPageCommand, addModelCommand, addComponentCommand, addEmailCommand } from './commands/add.js';\nimport { configureCommand } from './commands/configure.js';\nimport { deployCommand } from './commands/deploy.js';\nimport { upgradeCommand } from './commands/upgrade.js';\nimport { generateBlog } from './generators/features/blog.js';\nimport { generateDarkMode } from './generators/features/dark-mode.js';\nimport { generateNotifications } from './generators/features/notifications.js';\nimport { generateAnalytics } from './generators/features/analytics.js';\nimport { generateCommandPalette } from './generators/features/command-palette.js';\nimport { generateOnboarding } from './generators/features/onboarding.js';\nimport { generateSearch } from './generators/features/search.js';\nimport { generateRealtime } from './generators/features/realtime.js';\nimport { generateAI } from './generators/features/ai.js';\nimport { generateCookieConsent } from './generators/features/cookie-consent.js';\nimport { generateComingSoon } from './generators/features/coming-soon.js';\nimport { generateSentry } from './generators/features/sentry.js';\nimport { generateFeatureFlags } from './generators/features/feature-flags.js';\nimport { enableTelemetry, disableTelemetry } from './utils/telemetry.js';\nimport { log } from './utils/logger.js';\n\nconst program = new Command();\n\nprogram\n .name('mars')\n .description('MARS CLI: scaffold, configure, and maintain SaaS apps')\n .version('0.1.0')\n .option('-v, --verbose', 'Enable verbose output for debugging');\n\nexport function isVerbose(): boolean {\n return program.opts().verbose === true;\n}\n\nprogram\n .command('create')\n .description('Create a new MARS project')\n .argument('[name]', 'Project name (kebab-case)')\n .option('--defaults', 'Skip prompts, use default configuration')\n .action(async (name?: string, options?: { defaults?: boolean }) => {\n await createCommand(name, options);\n });\n\nconst add = program\n .command('add')\n .description('Add a feature, page, model, component, or email template to your project');\n\nadd\n .command('feature')\n .description('Scaffold a new feature module')\n .argument('<name>', 'Feature name (e.g., billing, blog, notifications)')\n .action(async (name: string) => {\n await addFeatureCommand(name);\n });\n\nadd\n .command('page')\n .description('Create a new page')\n .argument('<path>', 'Route path (e.g., pricing, blog/[slug])')\n .option('-p, --protected', 'Create in (protected) route group', false)\n .action(async (routePath: string, options: { protected?: boolean }) => {\n await addPageCommand(routePath, options);\n });\n\nadd\n .command('model')\n .description('Create a new Prisma model')\n .argument('<name>', 'Model name in PascalCase (e.g., Product, Invoice)')\n .action(async (name: string) => {\n await addModelCommand(name);\n });\n\nadd\n .command('component')\n .description('Create a new UI component')\n .argument('<name>', 'Component name in PascalCase (e.g., Toggle, DataGrid)')\n .option('-t, --type <type>', 'Component type: primitive or pattern', 'primitive')\n .action(async (name: string, options: { type?: string }) => {\n await addComponentCommand(name, options);\n });\n\nadd\n .command('email')\n .description('Create a new email template')\n .argument('<name>', 'Template name in kebab-case (e.g., invoice, team-invite)')\n .action(async (name: string) => {\n await addEmailCommand(name);\n });\n\nconst generate = program\n .command('generate')\n .description('Generate a feature with full scaffolding (pages, components, server logic, config)');\n\ngenerate\n .command('blog')\n .description('Add an MDX-based blog with listing, post pages, RSS feed, and SEO')\n .action(async () => {\n await generateBlog(process.cwd());\n });\n\ngenerate\n .command('dark-mode')\n .description('Add dark mode with ThemeProvider, theme toggle, system preference detection, and FOUC prevention')\n .action(async () => {\n await generateDarkMode(process.cwd());\n });\n\ngenerate\n .command('notifications')\n .description('Add in-app notifications with Prisma model, API routes, bell component, and polling hook')\n .action(async () => {\n await generateNotifications(process.cwd());\n });\n\ngenerate\n .command('analytics')\n .description('Add analytics with Vercel/PostHog/Google providers, consent banner, and unified tracking API')\n .action(async () => {\n await generateAnalytics(process.cwd());\n });\n\ngenerate\n .command('command-palette')\n .description('Add a Cmd+K command palette with fuzzy search, action registry, and keyboard navigation')\n .action(async () => {\n await generateCommandPalette(process.cwd());\n });\n\ngenerate\n .command('onboarding')\n .description('Add multi-step user onboarding with progress tracking, skip/complete, and redirect logic')\n .action(async () => {\n await generateOnboarding(process.cwd());\n });\n\ngenerate\n .command('search')\n .description('Add search with Postgres full-text, Algolia, or Meilisearch providers and debounced hook')\n .action(async () => {\n await generateSearch(process.cwd());\n });\n\ngenerate\n .command('realtime')\n .description('Add realtime updates with SSE (default), Pusher, or Ably providers and client hooks')\n .action(async () => {\n await generateRealtime(process.cwd());\n });\n\ngenerate\n .command('ai')\n .description('Add AI integration with OpenAI/Anthropic providers, streaming chat API, and useChat hook')\n .action(async () => {\n await generateAI(process.cwd());\n });\n\ngenerate\n .command('cookie-consent')\n .description('Add a cookie consent banner with preferences dialog and useConsent hook')\n .action(async () => {\n await generateCookieConsent(process.cwd());\n });\n\ngenerate\n .command('coming-soon')\n .description('Add a coming soon landing page with waitlist signup')\n .action(async () => {\n await generateComingSoon(process.cwd());\n });\n\ngenerate\n .command('sentry')\n .description('Add Sentry error tracking with client/server init and ErrorBoundary component')\n .action(async () => {\n await generateSentry(process.cwd());\n });\n\ngenerate\n .command('feature-flags')\n .description('Add feature flags with local JSON provider, server getFlag, client hook, and FeatureGate component')\n .action(async () => {\n await generateFeatureFlags(process.cwd());\n });\n\nprogram\n .command('configure')\n .description('Configure a service provider (email, payments, storage, etc.)')\n .argument('[service]', 'Service to configure (email, payments, storage, analytics, monitoring, auth)')\n .action(async (service?: string) => {\n await configureCommand(service);\n });\n\nprogram\n .command('deploy')\n .description('Deploy your project to Vercel')\n .action(async () => {\n await deployCommand();\n });\n\nprogram\n .command('doctor')\n .description('Check your development environment')\n .option('--upgrade-check', 'Check if Mars packages have updates available')\n .action(async (options: { upgradeCheck?: boolean }) => {\n await doctorCommand(options);\n });\n\nupgradeCommand(program);\n\nprogram\n .command('telemetry')\n .description('Manage anonymous usage telemetry')\n .argument('<action>', 'enable or disable')\n .action((action: string) => {\n if (action === 'enable') {\n enableTelemetry();\n log.success('Telemetry enabled. Thank you for helping improve Mars!');\n } else if (action === 'disable') {\n disableTelemetry();\n log.success('Telemetry disabled.');\n } else {\n log.error('Usage: mars telemetry <enable|disable>');\n }\n });\n\nprogram.parse();\n","import fs from 'fs-extra';\nimport path from 'path';\nimport os from 'os';\nimport ora from 'ora';\nimport pc from 'picocolors';\nimport prompts from 'prompts';\nimport { log } from '../utils/logger.js';\nimport { resolveProjectPath } from '../utils/template.js';\nimport { promptProjectInfo, getDefaultProjectInfo } from '../prompts/project-info.js';\nimport { promptFeatures, getDefaultFeatures } from '../prompts/features.js';\nimport { promptServices, getDefaultServices } from '../prompts/services.js';\nimport { promptTheme, getDefaultTheme } from '../prompts/theme.js';\nimport { scaffoldProject } from '../generators/scaffold.js';\nimport { generateSelectedFeatures } from '../generators/generate-selected.js';\nimport { enableTelemetry, trackEvent } from '../utils/telemetry.js';\nimport type { ProjectConfig, FeatureFlags, ServiceConfig, ThemeConfig } from '../types.js';\n\nconst RC_PATH = path.join(os.homedir(), '.marsrc');\n\nconst PROJECT_NAME_REGEX = /^[a-z0-9][a-z0-9-]*[a-z0-9]$/;\nconst MAX_PROJECT_NAME_LENGTH = 214;\n\nexport async function createCommand(\n projectName?: string,\n options?: { defaults?: boolean },\n): Promise<void> {\n const useDefaults = options?.defaults === true;\n\n log.banner();\n\n if (projectName) {\n if (!PROJECT_NAME_REGEX.test(projectName) && projectName.length > 1) {\n log.error('Project name must be lowercase letters, numbers, and hyphens only.');\n return;\n }\n if (projectName.length > MAX_PROJECT_NAME_LENGTH) {\n log.error(`Project name is too long (max ${MAX_PROJECT_NAME_LENGTH} characters).`);\n return;\n }\n if (projectName.includes('..') || projectName.includes('/') || projectName.includes('\\\\')) {\n log.error('Project name cannot contain path traversal characters.');\n return;\n }\n }\n\n if (useDefaults && !projectName) {\n log.error('Project name is required when using --defaults.');\n return;\n }\n\n const projectInfo = useDefaults\n ? getDefaultProjectInfo(projectName!)\n : await promptProjectInfo(projectName);\n if (!projectInfo) return;\n\n const targetDir = resolveProjectPath(projectInfo.name);\n if (await fs.pathExists(targetDir)) {\n const entries = await fs.readdir(targetDir);\n if (entries.length > 0) {\n log.error(`Directory \"${projectInfo.name}\" already exists and is not empty.`);\n return;\n }\n }\n\n const features: FeatureFlags = useDefaults\n ? getDefaultFeatures()\n : (await promptFeatures() as FeatureFlags);\n if (!features) return;\n\n const services: ServiceConfig = useDefaults\n ? getDefaultServices(features)\n : (await promptServices(features) as ServiceConfig);\n if (!services) return;\n\n const theme: ThemeConfig = useDefaults\n ? getDefaultTheme()\n : (await promptTheme() as ThemeConfig);\n if (!theme) return;\n\n const config: ProjectConfig = {\n ...projectInfo,\n features,\n services,\n theme,\n };\n\n log.blank();\n log.title('Summary');\n log.info(`Project: ${pc.bold(config.displayName)} (${config.name})`);\n log.info(`URL: ${config.url}`);\n log.info(`Features: ${countEnabled(features)} enabled`);\n log.info(`Database: ${services.database.provider}`);\n log.info(`Email: ${services.email.provider}`);\n log.info(`Theme: ${theme.primaryColor}, ${theme.font}, ${theme.designDirection}`);\n log.blank();\n\n if (!useDefaults) {\n const { confirmed } = await prompts(\n {\n type: 'confirm',\n name: 'confirmed',\n message: 'Proceed with scaffolding?',\n initial: true,\n },\n { onCancel: () => process.exit(0) },\n );\n\n if (!confirmed) {\n log.info('Scaffolding cancelled.');\n process.exit(0);\n }\n\n if (!fs.pathExistsSync(RC_PATH)) {\n const { telemetryOptIn } = await prompts(\n {\n type: 'confirm',\n name: 'telemetryOptIn',\n message: 'Help improve Mars by sharing anonymous usage data? This is completely opt-in.',\n initial: false,\n },\n { onCancel: () => {} },\n );\n if (telemetryOptIn) {\n enableTelemetry();\n log.success('Telemetry enabled. Thank you!');\n }\n }\n }\n\n const spinner = ora('Scaffolding project...').start();\n\n try {\n const { fileCount } = await scaffoldProject(targetDir, config);\n spinner.succeed(`Scaffolded ${pc.bold(String(fileCount))} files`);\n\n const generatedFeatures = await generateSelectedFeatures(targetDir, config.features);\n if (generatedFeatures.length > 0) {\n log.success(`Generated ${generatedFeatures.length} additional feature(s): ${generatedFeatures.join(', ')}`);\n }\n\n trackEvent('create', {\n features: Object.keys(features).filter((f) => features[f as keyof FeatureFlags]).join(','),\n });\n\n log.blank();\n log.title('Next Steps');\n log.step(`cd ${projectInfo.name}`);\n log.step('yarn install');\n log.step('yarn dev # starts database + syncs schema + launches dev server');\n log.blank();\n log.success('Your MARS project is ready. Happy building!');\n log.blank();\n } catch (err) {\n spinner.fail('Failed to scaffold project');\n log.error(err instanceof Error ? err.message : String(err));\n\n if (await fs.pathExists(targetDir)) {\n const cleanupSpinner = ora('Cleaning up...').start();\n try {\n await fs.remove(targetDir);\n cleanupSpinner.succeed('Cleaned up partial scaffold');\n } catch {\n cleanupSpinner.warn(`Could not clean up ${targetDir}. You may need to remove it manually.`);\n }\n }\n\n process.exit(1);\n }\n}\n\nfunction countEnabled(flags: Record<string, boolean>): number {\n return Object.values(flags).filter(Boolean).length;\n}\n","import path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport fs from 'fs-extra';\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\n\nexport function getTemplatePath(): string {\n const candidates = [\n // Built bundle: __dirname = packages/cli/dist/\n path.resolve(__dirname, '..', 'template'),\n path.resolve(__dirname, '..', '..', '..', 'template'),\n // Source (vitest): __dirname = packages/cli/src/utils/\n path.resolve(__dirname, '..', '..', '..', '..', 'template'),\n ];\n\n for (const candidate of candidates) {\n if (fs.existsSync(candidate)) {\n return candidate;\n }\n }\n\n throw new Error(\n 'Template directory not found. If installed from npm, ensure the package includes the template/ directory.',\n );\n}\n\nexport function resolveProjectPath(projectName: string): string {\n return path.resolve(process.cwd(), projectName);\n}\n","import prompts from 'prompts';\nimport { log } from '../utils/logger.js';\n\nexport interface ProjectInfoAnswers {\n name: string;\n displayName: string;\n description: string;\n url: string;\n supportEmail: string;\n}\n\nfunction toDisplayName(kebab: string): string {\n return kebab\n .split('-')\n .map((w) => w.charAt(0).toUpperCase() + w.slice(1))\n .join(' ');\n}\n\nexport function getDefaultProjectInfo(name: string): ProjectInfoAnswers {\n return {\n name,\n displayName: toDisplayName(name),\n description: 'A SaaS application built with MARS',\n url: `https://${name}.com`,\n supportEmail: `support@${name}.com`,\n };\n}\n\nfunction toKebabCase(str: string): string {\n return str\n .replace(/([a-z])([A-Z])/g, '$1-$2')\n .replace(/[\\s_]+/g, '-')\n .replace(/[^a-z0-9-]/gi, '')\n .toLowerCase();\n}\n\nexport async function promptProjectInfo(\n initialName?: string,\n): Promise<ProjectInfoAnswers | null> {\n log.title('Project Setup');\n\n const answers = await prompts(\n [\n {\n type: initialName ? null : 'text',\n name: 'name',\n message: 'Project name (kebab-case):',\n initial: 'my-app',\n validate: (val: string) =>\n /^[a-z0-9-]+$/.test(val) || 'Must be lowercase letters, numbers, and hyphens only',\n },\n {\n type: 'text',\n name: 'displayName',\n message: 'Display name:',\n initial: (prev: string) => toDisplayName(initialName || prev),\n },\n {\n type: 'text',\n name: 'description',\n message: 'Short description:',\n initial: 'A SaaS application built with MARS',\n },\n {\n type: 'text',\n name: 'url',\n message: 'Production URL:',\n initial: (prev: string, values: Record<string, string>) =>\n `https://${initialName || values.name}.com`,\n },\n {\n type: 'text',\n name: 'supportEmail',\n message: 'Support email:',\n initial: (prev: string, values: Record<string, string>) =>\n `support@${initialName || values.name}.com`,\n },\n ],\n {\n onCancel: () => {\n log.error('Setup cancelled.');\n return false;\n },\n },\n );\n\n if (!answers.displayName) return null;\n\n return {\n name: initialName || toKebabCase(answers.name),\n displayName: answers.displayName,\n description: answers.description,\n url: answers.url,\n supportEmail: answers.supportEmail,\n };\n}\n","import prompts from 'prompts';\nimport { log } from '../utils/logger.js';\nimport type { FeatureFlags } from '../types.js';\n\nconst FEATURE_GROUPS = [\n {\n title: 'Authentication & Users',\n features: [\n { name: 'auth', label: 'Email/password auth', default: true },\n { name: 'googleOAuth', label: 'Google OAuth', default: false },\n { name: 'emailVerification', label: 'Email verification', default: true },\n { name: 'magicLinks', label: 'Magic link login', default: false },\n { name: 'twoFactor', label: 'Two-factor auth', default: false },\n { name: 'admin', label: 'Admin role & panel', default: true },\n ],\n },\n {\n title: 'App Features',\n features: [\n { name: 'darkMode', label: 'Dark mode', default: false },\n { name: 'notifications', label: 'Notifications', default: false },\n { name: 'onboarding', label: 'Onboarding flow', default: false },\n { name: 'billing', label: 'Billing / subscriptions', default: false },\n { name: 'blog', label: 'Blog / content', default: false },\n { name: 'fileUpload', label: 'File uploads', default: false },\n { name: 'search', label: 'Search', default: false },\n { name: 'realtime', label: 'Realtime updates', default: false },\n { name: 'commandPalette', label: 'Command palette (⌘K)', default: false },\n { name: 'ai', label: 'AI integration', default: false },\n ],\n },\n {\n title: 'Infrastructure',\n features: [\n { name: 'seo', label: 'SEO & JSON-LD', default: true },\n { name: 'cookieConsent', label: 'Cookie consent', default: true },\n { name: 'analytics', label: 'Analytics', default: false },\n { name: 'sentry', label: 'Error monitoring', default: false },\n { name: 'featureFlags', label: 'Feature flags', default: false },\n ],\n },\n {\n title: 'Architecture',\n features: [\n { name: 'multiTenancy', label: 'Multi-tenancy', default: false },\n { name: 'teams', label: 'Teams / orgs', default: false },\n { name: 'comingSoon', label: 'Coming soon mode', default: false },\n ],\n },\n];\n\nexport function getDefaultFeatures(): FeatureFlags {\n const flags: Record<string, boolean> = {};\n for (const group of FEATURE_GROUPS) {\n for (const feature of group.features) {\n flags[feature.name] = feature.default;\n }\n }\n return flags as unknown as FeatureFlags;\n}\n\nexport async function promptFeatures(): Promise<FeatureFlags | null> {\n log.title('Feature Selection');\n log.info('Select the features you want to include:');\n log.blank();\n\n const flags: Record<string, boolean> = {};\n\n for (const group of FEATURE_GROUPS) {\n const choices = group.features.map((f) => ({\n title: f.label,\n value: f.name,\n selected: f.default,\n }));\n\n const response = await prompts(\n {\n type: 'multiselect',\n name: 'selected',\n message: group.title,\n choices,\n hint: '- Space to toggle, Enter to confirm',\n instructions: false,\n },\n {\n onCancel: () => {\n log.error('Setup cancelled.');\n return false;\n },\n },\n );\n\n if (!response.selected) return null;\n\n for (const feature of group.features) {\n flags[feature.name] = (response.selected as string[]).includes(feature.name);\n }\n }\n\n return flags as unknown as FeatureFlags;\n}\n","import prompts from 'prompts';\nimport { log } from '../utils/logger.js';\nimport type { FeatureFlags, ServiceConfig } from '../types.js';\n\ninterface ServiceQuestion {\n key: keyof ServiceConfig;\n message: string;\n choices: Array<{ title: string; value: string }>;\n condition?: (features: FeatureFlags) => boolean;\n defaultValue: string;\n}\n\nconst SERVICE_QUESTIONS: ServiceQuestion[] = [\n {\n key: 'database',\n message: 'Database provider:',\n choices: [\n { title: 'Local (Docker Postgres)', value: 'local' },\n { title: 'Vercel Postgres', value: 'vercel' },\n { title: 'Supabase', value: 'supabase' },\n ],\n defaultValue: 'local',\n },\n {\n key: 'email',\n message: 'Email provider:',\n choices: [\n { title: 'Console (dev only)', value: 'console' },\n { title: 'SendGrid', value: 'sendgrid' },\n { title: 'Resend', value: 'resend' },\n ],\n defaultValue: 'console',\n },\n {\n key: 'storage',\n message: 'File storage:',\n condition: (f) => f.fileUpload,\n choices: [\n { title: 'Local filesystem', value: 'local' },\n { title: 'Vercel Blob', value: 'vercel' },\n { title: 'AWS S3', value: 's3' },\n ],\n defaultValue: 'local',\n },\n {\n key: 'payments',\n message: 'Payment provider:',\n condition: (f) => f.billing,\n choices: [\n { title: 'None', value: 'none' },\n { title: 'Stripe', value: 'stripe' },\n ],\n defaultValue: 'none',\n },\n {\n key: 'analytics',\n message: 'Analytics provider:',\n condition: (f) => f.analytics,\n choices: [\n { title: 'None', value: 'none' },\n { title: 'Vercel Analytics', value: 'vercel' },\n { title: 'PostHog', value: 'posthog' },\n { title: 'Google Analytics', value: 'google' },\n ],\n defaultValue: 'none',\n },\n {\n key: 'monitoring',\n message: 'Error monitoring:',\n condition: (f) => f.sentry,\n choices: [\n { title: 'None', value: 'none' },\n { title: 'Sentry', value: 'sentry' },\n ],\n defaultValue: 'none',\n },\n {\n key: 'ai',\n message: 'AI provider:',\n condition: (f) => f.ai,\n choices: [\n { title: 'None', value: 'none' },\n { title: 'OpenAI', value: 'openai' },\n { title: 'Anthropic', value: 'anthropic' },\n ],\n defaultValue: 'none',\n },\n {\n key: 'search',\n message: 'Search provider:',\n condition: (f) => f.search,\n choices: [\n { title: 'None', value: 'none' },\n { title: 'Postgres full-text', value: 'postgres' },\n { title: 'Algolia', value: 'algolia' },\n { title: 'Meilisearch', value: 'meilisearch' },\n ],\n defaultValue: 'none',\n },\n {\n key: 'realtime',\n message: 'Realtime provider:',\n condition: (f) => f.realtime,\n choices: [\n { title: 'None', value: 'none' },\n { title: 'Server-Sent Events', value: 'sse' },\n { title: 'Pusher', value: 'pusher' },\n { title: 'Ably', value: 'ably' },\n ],\n defaultValue: 'none',\n },\n {\n key: 'jobs',\n message: 'Background jobs:',\n choices: [\n { title: 'None', value: 'none' },\n { title: 'Database-backed', value: 'db' },\n { title: 'Inngest', value: 'inngest' },\n { title: 'Trigger.dev', value: 'trigger' },\n ],\n defaultValue: 'none',\n },\n];\n\nexport function getDefaultServices(_features: FeatureFlags): ServiceConfig {\n const config: Record<string, { provider: string }> = {};\n for (const q of SERVICE_QUESTIONS) {\n config[q.key] = { provider: q.defaultValue };\n }\n return config as unknown as ServiceConfig;\n}\n\nexport async function promptServices(features: FeatureFlags): Promise<ServiceConfig | null> {\n log.title('Service Providers');\n log.info('Choose providers for each service:');\n log.blank();\n\n const config: Record<string, { provider: string }> = {};\n\n for (const q of SERVICE_QUESTIONS) {\n if (q.condition && !q.condition(features)) {\n config[q.key] = { provider: q.defaultValue };\n continue;\n }\n\n const response = await prompts(\n {\n type: 'select',\n name: 'provider',\n message: q.message,\n choices: q.choices,\n initial: q.choices.findIndex((c) => c.value === q.defaultValue),\n },\n {\n onCancel: () => {\n log.error('Setup cancelled.');\n return false;\n },\n },\n );\n\n if (response.provider === undefined) return null;\n\n config[q.key] = { provider: response.provider };\n }\n\n return config as unknown as ServiceConfig;\n}\n","import prompts from 'prompts';\nimport { log } from '../utils/logger.js';\nimport type { ThemeConfig } from '../types.js';\n\nconst COLOR_PRESETS = [\n { title: 'Blue (default)', value: 'blue-600' },\n { title: 'Indigo', value: 'indigo-600' },\n { title: 'Violet', value: 'violet-600' },\n { title: 'Emerald', value: 'emerald-600' },\n { title: 'Rose', value: 'rose-600' },\n { title: 'Amber', value: 'amber-600' },\n { title: 'Cyan', value: 'cyan-600' },\n { title: 'Slate', value: 'slate-600' },\n];\n\nconst FONT_CHOICES = [\n { title: 'Inter (clean, modern)', value: 'Inter' },\n { title: 'DM Sans (friendly)', value: 'DM Sans' },\n { title: 'Plus Jakarta Sans (professional)', value: 'Plus Jakarta Sans' },\n { title: 'Outfit (geometric)', value: 'Outfit' },\n { title: 'Space Grotesk (technical)', value: 'Space Grotesk' },\n { title: 'System default', value: 'system-ui' },\n];\n\nconst DESIGN_DIRECTIONS = [\n { title: 'Modern SaaS (default)', value: 'modern-saas' },\n { title: 'Minimal', value: 'minimal' },\n { title: 'Enterprise', value: 'enterprise' },\n { title: 'Creative', value: 'creative' },\n { title: 'Dashboard', value: 'dashboard' },\n];\n\nexport function getDefaultTheme(): ThemeConfig {\n return {\n primaryColor: COLOR_PRESETS[0].value,\n secondaryColor: 'amber-400',\n font: FONT_CHOICES[0].value,\n designDirection: DESIGN_DIRECTIONS[0].value as ThemeConfig['designDirection'],\n };\n}\n\nexport async function promptTheme(): Promise<ThemeConfig | null> {\n log.title('Theme & Design');\n\n const response = await prompts(\n [\n {\n type: 'select',\n name: 'primaryColor',\n message: 'Primary brand color:',\n choices: COLOR_PRESETS,\n initial: 0,\n },\n {\n type: 'select',\n name: 'font',\n message: 'Font family:',\n choices: FONT_CHOICES,\n initial: 0,\n },\n {\n type: 'select',\n name: 'designDirection',\n message: 'Design direction:',\n choices: DESIGN_DIRECTIONS,\n initial: 0,\n },\n ],\n {\n onCancel: () => {\n log.error('Setup cancelled.');\n return false;\n },\n },\n );\n\n if (response.primaryColor === undefined) return null;\n\n return {\n primaryColor: response.primaryColor,\n secondaryColor: 'amber-400',\n font: response.font,\n designDirection: response.designDirection,\n };\n}\n","import fs from 'fs-extra';\nimport path from 'node:path';\nimport { generateBrandCss } from '@mars-stack/ui/utils';\nimport type { FeatureFlags, ProjectConfig } from '../types.js';\nimport { log } from '../utils/logger.js';\nimport { getTemplatePath } from '../utils/template.js';\nimport { generateAppConfig } from './app-config.js';\nimport { generateEnvFile, generateEnvExample } from './env.js';\n\nconst IGNORED_DIRS = ['node_modules', '.next', '.turbo', 'dist', '.git'];\nconst IGNORED_FILES = [\n '.env',\n '.env.local',\n '.env.development',\n '.env.test',\n 'yarn.lock',\n 'next-env.d.ts',\n];\n\nasync function copyTemplateFiles(templateDir: string, targetDir: string): Promise<number> {\n let fileCount = 0;\n\n async function walkAndCopy(src: string, dest: string) {\n const entries = await fs.readdir(src, { withFileTypes: true });\n\n for (const entry of entries) {\n const srcPath = path.join(src, entry.name);\n const destPath = path.join(dest, entry.name);\n\n if (entry.isDirectory()) {\n if (IGNORED_DIRS.includes(entry.name)) continue;\n await fs.ensureDir(destPath);\n await walkAndCopy(srcPath, destPath);\n } else {\n if (IGNORED_FILES.includes(entry.name)) continue;\n await fs.copy(srcPath, destPath);\n fileCount++;\n }\n }\n }\n\n await walkAndCopy(templateDir, targetDir);\n return fileCount;\n}\n\n/**\n * Resolve the semver range for a @mars-stack/* package by reading its actual version.\n * Looks in the monorepo packages/ directory first, then falls back to the version\n * already declared in the template's package.json.\n */\nexport function resolveMarsPackageRange(packageName: string, templateDir: string): string {\n const shortName = packageName.replace('@mars-stack/', '');\n\n const candidates = [\n path.resolve(templateDir, '..', 'packages', shortName, 'package.json'),\n path.resolve(templateDir, '..', '..', 'packages', shortName, 'package.json'),\n ];\n\n for (const candidate of candidates) {\n if (fs.existsSync(candidate)) {\n const pkg = fs.readJsonSync(candidate) as { version?: string };\n if (typeof pkg.version === 'string') {\n const [major, minor] = pkg.version.split('.');\n return `^${major}.${minor}.0`;\n }\n }\n }\n\n const templatePkg = fs.readJsonSync(path.join(templateDir, 'package.json')) as {\n dependencies?: Record<string, string>;\n };\n const existing = templatePkg.dependencies?.[packageName];\n if (existing && existing !== '*') {\n if (/^[\\^~>=]/.test(existing)) return existing;\n const parts = existing.split('.');\n if (parts.length >= 2) return `^${parts[0]}.${parts[1]}.0`;\n }\n\n return '>=0.1.0';\n}\n\nfunction generatePackageJson(config: ProjectConfig): string {\n const templateDir = getTemplatePath();\n const templatePkg = path.join(templateDir, 'package.json');\n const pkg = fs.readJsonSync(templatePkg);\n\n pkg.name = config.name;\n pkg.version = '0.1.0';\n pkg.private = true;\n pkg.description = config.description;\n pkg.mars = true;\n\n delete pkg.workspaces;\n\n if (pkg.dependencies?.['@mars-stack/core']) {\n pkg.dependencies['@mars-stack/core'] = resolveMarsPackageRange('@mars-stack/core', templateDir);\n }\n if (pkg.dependencies?.['@mars-stack/ui']) {\n pkg.dependencies['@mars-stack/ui'] = resolveMarsPackageRange('@mars-stack/ui', templateDir);\n }\n\n return JSON.stringify(pkg, null, 2) + '\\n';\n}\n\nfunction escapeYamlValue(value: string): string {\n if (/[:\\$\\*\\&\\#\\[\\]\\{\\}\\|>!%@`]/.test(value) || value.includes('\"')) {\n return `\"${value.replace(/\\\\/g, '\\\\\\\\').replace(/\"/g, '\\\\\"')}\"`;\n }\n return value;\n}\n\nfunction generateDockerCompose(config: ProjectConfig): string {\n const dbName = escapeYamlValue(`${config.name}_dev`);\n const dbUser = escapeYamlValue(config.name);\n const dbPass = escapeYamlValue(config.name);\n\n return `# Optional: use Docker instead of the embedded database (prisma dev).\n# Start with: docker compose up -d\nservices:\n postgres:\n image: postgres:16-alpine\n ports:\n - '5432:5432'\n environment:\n POSTGRES_DB: ${dbName}\n POSTGRES_USER: ${dbUser}\n POSTGRES_PASSWORD: ${dbPass}\n volumes:\n - postgres_data:/var/lib/postgresql/data\n healthcheck:\n test: ['CMD-SHELL', 'pg_isready -U ${dbUser} -d ${dbName}']\n interval: 5s\n timeout: 5s\n retries: 5\n\n redis:\n image: redis:7-alpine\n ports:\n - '6379:6379'\n healthcheck:\n test: ['CMD', 'redis-cli', 'ping']\n interval: 5s\n timeout: 5s\n retries: 5\n\nvolumes:\n postgres_data:\n`;\n}\n\nconst FONT_IMPORTS: Record<string, { importName: string; importFrom: string }> = {\n 'Inter': { importName: 'Inter', importFrom: 'Inter' },\n 'DM Sans': { importName: 'DM_Sans', importFrom: 'DM_Sans' },\n 'Plus Jakarta Sans': { importName: 'Plus_Jakarta_Sans', importFrom: 'Plus_Jakarta_Sans' },\n 'Outfit': { importName: 'Outfit', importFrom: 'Outfit' },\n 'Space Grotesk': { importName: 'Space_Grotesk', importFrom: 'Space_Grotesk' },\n 'system-ui': { importName: '', importFrom: '' },\n};\n\nfunction generateLayout(config: ProjectConfig): string {\n const fontKey = config.theme.font;\n const fontConfig = FONT_IMPORTS[fontKey] || FONT_IMPORTS['Inter'];\n\n if (!fontConfig.importName) {\n return `import type { Metadata } from 'next';\nimport '@/styles/globals.css';\nimport { appConfig } from '@/config/app.config';\nimport { Providers } from './providers';\n\nexport const metadata: Metadata = {\n title: {\n default: appConfig.name,\n template: \\`%s | \\${appConfig.name}\\`,\n },\n description: appConfig.description,\n metadataBase: new URL(appConfig.url),\n};\n\nexport default function RootLayout({ children }: { children: React.ReactNode }) {\n return (\n <html lang=\"en\" suppressHydrationWarning>\n <body className=\"bg-surface-background text-text-primary antialiased font-sans\">\n <Providers>{children}</Providers>\n </body>\n </html>\n );\n}\n`;\n }\n\n return `import type { Metadata } from 'next';\nimport { ${fontConfig.importFrom} } from 'next/font/google';\nimport '@/styles/globals.css';\nimport { appConfig } from '@/config/app.config';\nimport { Providers } from './providers';\n\nconst font = ${fontConfig.importFrom}({\n subsets: ['latin'],\n variable: '--font-sans',\n});\n\nexport const metadata: Metadata = {\n title: {\n default: appConfig.name,\n template: \\`%s | \\${appConfig.name}\\`,\n },\n description: appConfig.description,\n metadataBase: new URL(appConfig.url),\n};\n\nexport default function RootLayout({ children }: { children: React.ReactNode }) {\n return (\n <html lang=\"en\" className={font.variable} suppressHydrationWarning>\n <body className=\"bg-surface-background text-text-primary antialiased\">\n <Providers>{children}</Providers>\n </body>\n </html>\n );\n}\n`;\n}\n\nfunction generateGitignore(): string {\n return `# dependencies\nnode_modules/\n.pnp\n.pnp.js\n\n# next.js\n.next/\nout/\n\n# testing\ncoverage/\n\n# build\ndist/\n*.tsbuildinfo\n\n# env\n.env\n.env.local\n.env.development\n.env.development.local\n.env.test\n\n# local database\n.mars/\n\n# misc\n.DS_Store\n*.pem\n\n# debug\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n\n# turbo\n.turbo\n\n# vercel\n.vercel\n\n# prisma\nprisma/migrations/\n`;\n}\n\nconst FEATURE_DIRECTORY_MAP: Record<string, string[]> = {\n admin: [\n 'src/app/(protected)/admin',\n 'src/app/api/protected/admin',\n ],\n billing: [\n 'src/features/billing',\n 'src/app/api/protected/billing',\n 'src/app/api/webhooks/stripe',\n 'prisma/schema/subscription.prisma',\n ],\n fileUpload: [\n 'src/features/uploads',\n 'src/app/api/protected/files',\n 'prisma/schema/file.prisma',\n ],\n};\n\nconst USER_RELATION_MAP: Record<string, string> = {\n billing: 'subscription',\n fileUpload: 'files',\n};\n\nexport async function pruneDisabledFeatures(\n features: FeatureFlags,\n targetDir: string,\n): Promise<void> {\n const relationsToRemove: string[] = [];\n\n for (const [feature, paths] of Object.entries(FEATURE_DIRECTORY_MAP)) {\n const flagValue = features[feature as keyof FeatureFlags];\n if (flagValue !== false) continue;\n\n for (const relativePath of paths) {\n const fullPath = path.join(targetDir, relativePath);\n if (await fs.pathExists(fullPath)) {\n await fs.remove(fullPath);\n log.step(`Pruned disabled feature path: ${relativePath}`);\n }\n }\n\n if (USER_RELATION_MAP[feature]) {\n relationsToRemove.push(USER_RELATION_MAP[feature]);\n }\n }\n\n if (relationsToRemove.length > 0) {\n const authPath = path.join(targetDir, 'prisma', 'schema', 'auth.prisma');\n if (await fs.pathExists(authPath)) {\n let content = await fs.readFile(authPath, 'utf-8');\n for (const field of relationsToRemove) {\n content = content.replace(new RegExp(`\\\\s*${field}\\\\s+\\\\S+.*\\\\n`, 'g'), '\\n');\n }\n await fs.writeFile(authPath, content);\n }\n }\n}\n\nexport async function scaffoldProject(\n targetDir: string,\n config: ProjectConfig,\n): Promise<{ fileCount: number }> {\n const templateDir = getTemplatePath();\n\n if (!(await fs.pathExists(templateDir))) {\n throw new Error(`Template directory not found: ${templateDir}`);\n }\n\n await fs.ensureDir(targetDir);\n\n const fileCount = await copyTemplateFiles(templateDir, targetDir);\n\n await pruneDisabledFeatures(config.features, targetDir);\n\n await fs.writeFile(path.join(targetDir, 'package.json'), generatePackageJson(config));\n\n await fs.writeFile(\n path.join(targetDir, 'src', 'config', 'app.config.ts'),\n generateAppConfig(config),\n );\n\n await fs.writeFile(path.join(targetDir, 'docker-compose.yml'), generateDockerCompose(config));\n\n await fs.writeFile(path.join(targetDir, 'src', 'app', 'layout.tsx'), generateLayout(config));\n\n await fs.writeFile(path.join(targetDir, '.env'), generateEnvFile(config));\n await fs.writeFile(path.join(targetDir, '.env.example'), generateEnvExample(config));\n await fs.writeFile(path.join(targetDir, '.gitignore'), generateGitignore());\n\n await patchGlobalsCssForScaffoldedProject(targetDir, config);\n\n await generateBrandCssForProject(targetDir, config);\n\n return { fileCount };\n}\n\n/** Overwrite the template's static brand.css with a palette derived from primaryColor. */\nasync function generateBrandCssForProject(\n targetDir: string,\n config: ProjectConfig,\n): Promise<void> {\n const brandPath = path.join(targetDir, 'src', 'styles', 'brand.css');\n if (!(await fs.pathExists(brandPath))) return;\n\n const css = generateBrandCss(config.theme.primaryColor);\n await fs.writeFile(brandPath, css);\n}\n\nconst VALID_DESIGN_DIRECTIONS = [\n 'modern-saas',\n 'minimal',\n 'enterprise',\n 'creative',\n 'dashboard',\n] as const;\n\n/** Fix @source path and inject the correct meta-theme import for the selected designDirection. */\nasync function patchGlobalsCssForScaffoldedProject(\n targetDir: string,\n config: ProjectConfig,\n): Promise<void> {\n const globalsPath = path.join(targetDir, 'src', 'styles', 'globals.css');\n if (!(await fs.pathExists(globalsPath))) return;\n\n let content = await fs.readFile(globalsPath, 'utf-8');\n\n content = content.replace(\n '@source \"../../../node_modules/@mars-stack/ui/dist/**/*.js\";',\n '@source \"../../node_modules/@mars-stack/ui/dist/**/*.js\";',\n );\n\n const direction = VALID_DESIGN_DIRECTIONS.includes(\n config.theme.designDirection as (typeof VALID_DESIGN_DIRECTIONS)[number],\n )\n ? config.theme.designDirection\n : 'modern-saas';\n\n const currentMetaImport = /@import\\s+['\"]@mars-stack\\/ui\\/styles\\/meta-[^'\"]+['\"]\\s*;/;\n const newImport = `@import '@mars-stack/ui/styles/meta-${direction}.css';`;\n\n if (currentMetaImport.test(content)) {\n content = content.replace(currentMetaImport, newImport);\n } else {\n content = content.replace(\n \"@import '@mars-stack/ui/styles/index.css';\",\n `@import '@mars-stack/ui/styles/index.css';\\n${newImport}`,\n );\n }\n\n await fs.writeFile(globalsPath, content);\n}\n","import type { ProjectConfig, FeatureFlags } from '../types.js';\n\nfunction escapeQuotes(value: string): string {\n return value.replace(/\\\\/g, '\\\\\\\\').replace(/'/g, \"\\\\'\");\n}\n\nconst SCAFFOLDED_FEATURES: Set<keyof FeatureFlags> = new Set([\n 'auth',\n 'emailVerification',\n 'admin',\n 'billing',\n 'fileUpload',\n 'seo',\n]);\n\nexport function generateAppConfig(config: ProjectConfig): string {\n const featureEntries = Object.entries(config.features)\n .map(([key, val]) => {\n const hasCode = SCAFFOLDED_FEATURES.has(key as keyof FeatureFlags);\n return ` ${key}: ${hasCode ? val : false},`;\n })\n .join('\\n');\n\n const serviceEntries = Object.entries(config.services)\n .map(([key, svc]) => {\n const provider = (svc as { provider: string }).provider;\n return ` ${key}: { provider: '${escapeQuotes(provider)}' },`;\n })\n .join('\\n');\n\n return `export const appConfig = {\n name: '${escapeQuotes(config.displayName)}',\n tagline: '${escapeQuotes(config.description)}',\n description: '${escapeQuotes(config.description)}',\n url: '${escapeQuotes(config.url)}',\n support: { email: '${escapeQuotes(config.supportEmail)}', phone: '' },\n social: {\n twitter: '',\n tiktok: '',\n linkedin: '',\n github: '',\n instagram: '',\n },\n legal: {\n companyName: '',\n registrationNumber: '',\n address: '',\n },\n theme: {\n primaryColor: '${config.theme.primaryColor}' as string,\n secondaryColor: '${config.theme.secondaryColor}' as string,\n font: '${config.theme.font}' as string,\n designDirection: '${config.theme.designDirection}' as\n | 'modern-saas'\n | 'minimal'\n | 'enterprise'\n | 'creative'\n | 'dashboard',\n },\n features: {\n${featureEntries}\n },\n services: {\n${serviceEntries}\n },\n} as const;\n\nexport type AppConfig = typeof appConfig;\n`;\n}\n","import crypto from 'node:crypto';\nimport type { ProjectConfig } from '../types.js';\n\nfunction generateSecret(): string {\n return crypto.randomBytes(32).toString('hex');\n}\n\nexport function generateEnvFile(config: ProjectConfig): string {\n const lines: string[] = [\n '# Generated by MARS CLI',\n `# Project: ${config.displayName}`,\n '',\n '# === Core ===',\n 'APP_URL=http://localhost:3000',\n '# DATABASE_URL is auto-configured by `yarn dev` (embedded Postgres via prisma dev).',\n '# Uncomment and set manually to use a cloud database (Neon, Supabase, etc.):',\n `# DATABASE_URL=\"postgresql://user:password@host:5432/${config.name}_dev\"`,\n '',\n '# === Auth ===',\n `JWT_SECRET=\"${generateSecret()}\"`,\n '',\n ];\n\n if (config.features.googleOAuth) {\n lines.push('# === Google OAuth ===');\n lines.push('GOOGLE_CLIENT_ID=');\n lines.push('GOOGLE_CLIENT_SECRET=');\n lines.push('');\n }\n\n if (config.services.email.provider === 'sendgrid') {\n lines.push('# === SendGrid ===');\n lines.push('SENDGRID_API_KEY=');\n lines.push(`SENDGRID_FROM_EMAIL=${config.supportEmail}`);\n lines.push('');\n } else if (config.services.email.provider === 'resend') {\n lines.push('# === Resend ===');\n lines.push('RESEND_API_KEY=');\n lines.push(`RESEND_FROM_EMAIL=${config.supportEmail}`);\n lines.push('');\n }\n\n if (config.services.payments.provider === 'stripe') {\n lines.push('# === Stripe ===');\n lines.push('STRIPE_SECRET_KEY=');\n lines.push('NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=');\n lines.push('STRIPE_WEBHOOK_SECRET=');\n lines.push('');\n }\n\n if (config.services.analytics.provider === 'posthog') {\n lines.push('# === PostHog ===');\n lines.push('NEXT_PUBLIC_POSTHOG_KEY=');\n lines.push('NEXT_PUBLIC_POSTHOG_HOST=');\n lines.push('');\n } else if (config.services.analytics.provider === 'google') {\n lines.push('# === Google Analytics ===');\n lines.push('NEXT_PUBLIC_GA_MEASUREMENT_ID=');\n lines.push('');\n }\n\n if (config.services.monitoring.provider === 'sentry') {\n lines.push('# === Sentry ===');\n lines.push('SENTRY_DSN=');\n lines.push('SENTRY_AUTH_TOKEN=');\n lines.push('');\n }\n\n if (config.services.ai.provider === 'openai') {\n lines.push('# === OpenAI ===');\n lines.push('OPENAI_API_KEY=');\n lines.push('');\n } else if (config.services.ai.provider === 'anthropic') {\n lines.push('# === Anthropic ===');\n lines.push('ANTHROPIC_API_KEY=');\n lines.push('');\n }\n\n if (config.services.search.provider === 'algolia') {\n lines.push('# === Algolia ===');\n lines.push('ALGOLIA_APP_ID=');\n lines.push('ALGOLIA_ADMIN_KEY=');\n lines.push('NEXT_PUBLIC_ALGOLIA_SEARCH_KEY=');\n lines.push('');\n }\n\n if (config.services.realtime.provider === 'pusher') {\n lines.push('# === Pusher ===');\n lines.push('PUSHER_APP_ID=');\n lines.push('PUSHER_KEY=');\n lines.push('PUSHER_SECRET=');\n lines.push('PUSHER_CLUSTER=');\n lines.push('');\n } else if (config.services.realtime.provider === 'ably') {\n lines.push('# === Ably ===');\n lines.push('ABLY_API_KEY=');\n lines.push('');\n }\n\n if (config.services.storage.provider === 'vercel') {\n lines.push('# === Vercel Blob ===');\n lines.push('BLOB_READ_WRITE_TOKEN=');\n lines.push('');\n } else if (config.services.storage.provider === 's3') {\n lines.push('# === AWS S3 ===');\n lines.push('AWS_ACCESS_KEY_ID=');\n lines.push('AWS_SECRET_ACCESS_KEY=');\n lines.push('AWS_REGION=');\n lines.push('S3_BUCKET_NAME=');\n lines.push('');\n }\n\n lines.push('# === Rate Limiting (Upstash) ===');\n lines.push('UPSTASH_REDIS_REST_URL=');\n lines.push('UPSTASH_REDIS_REST_TOKEN=');\n lines.push('');\n\n return lines.join('\\n');\n}\n\nexport function generateEnvExample(config: ProjectConfig): string {\n const envContent = generateEnvFile(config);\n return envContent.replace(\n /^JWT_SECRET=\"[^\"]*\"$/m,\n 'JWT_SECRET=\"your-secret-here-min-32-characters-long\"'\n );\n}\n","import type { FeatureFlags } from '../types.js';\nimport { log } from '../utils/logger.js';\n\ntype GeneratorFn = (projectRoot: string) => Promise<void>;\n\ninterface FeatureGenerator {\n key: keyof FeatureFlags;\n name: string;\n generate: () => Promise<{ default?: GeneratorFn } & Record<string, GeneratorFn>>;\n}\n\nconst TEMPLATE_FEATURES: Set<keyof FeatureFlags> = new Set([\n 'auth',\n 'emailVerification',\n 'admin',\n 'billing',\n 'fileUpload',\n 'seo',\n]);\n\nconst GENERATOR_REGISTRY: FeatureGenerator[] = [\n {\n key: 'blog',\n name: 'blog',\n generate: () => import('./features/blog.js'),\n },\n {\n key: 'darkMode',\n name: 'dark-mode',\n generate: () => import('./features/dark-mode.js'),\n },\n {\n key: 'notifications',\n name: 'notifications',\n generate: () => import('./features/notifications.js'),\n },\n {\n key: 'analytics',\n name: 'analytics',\n generate: () => import('./features/analytics.js'),\n },\n {\n key: 'commandPalette',\n name: 'command-palette',\n generate: () => import('./features/command-palette.js'),\n },\n {\n key: 'onboarding',\n name: 'onboarding',\n generate: () => import('./features/onboarding.js'),\n },\n {\n key: 'search',\n name: 'search',\n generate: () => import('./features/search.js'),\n },\n {\n key: 'realtime',\n name: 'realtime',\n generate: () => import('./features/realtime.js'),\n },\n {\n key: 'ai',\n name: 'ai',\n generate: () => import('./features/ai.js'),\n },\n {\n key: 'cookieConsent',\n name: 'cookie-consent',\n generate: () => import('./features/cookie-consent.js'),\n },\n {\n key: 'comingSoon',\n name: 'coming-soon',\n generate: () => import('./features/coming-soon.js'),\n },\n {\n key: 'sentry',\n name: 'sentry',\n generate: () => import('./features/sentry.js'),\n },\n {\n key: 'featureFlags',\n name: 'feature-flags',\n generate: () => import('./features/feature-flags.js'),\n },\n];\n\nconst GENERATOR_FUNCTION_MAP: Record<string, string> = {\n blog: 'generateBlog',\n 'dark-mode': 'generateDarkMode',\n notifications: 'generateNotifications',\n analytics: 'generateAnalytics',\n 'command-palette': 'generateCommandPalette',\n onboarding: 'generateOnboarding',\n search: 'generateSearch',\n realtime: 'generateRealtime',\n ai: 'generateAI',\n 'cookie-consent': 'generateCookieConsent',\n 'coming-soon': 'generateComingSoon',\n sentry: 'generateSentry',\n 'feature-flags': 'generateFeatureFlags',\n};\n\nexport async function generateSelectedFeatures(\n projectRoot: string,\n features: FeatureFlags,\n): Promise<string[]> {\n const generated: string[] = [];\n\n for (const entry of GENERATOR_REGISTRY) {\n if (!features[entry.key]) continue;\n if (TEMPLATE_FEATURES.has(entry.key)) continue;\n\n try {\n const mod = await entry.generate();\n const fnName = GENERATOR_FUNCTION_MAP[entry.name];\n const fn = fnName ? (mod as Record<string, GeneratorFn>)[fnName] : undefined;\n\n if (fn) {\n await fn(projectRoot);\n generated.push(entry.name);\n }\n } catch (error) {\n log.warn(`Failed to generate ${entry.name}: ${error instanceof Error ? error.message : String(error)}`);\n }\n }\n\n return generated;\n}\n","import fs from 'fs-extra';\nimport path from 'path';\nimport os from 'os';\n\nconst RC_PATH = path.join(os.homedir(), '.marsrc');\n\ninterface TelemetryConfig {\n enabled: boolean;\n anonymousId: string;\n}\n\n/**\n * Checks whether the user has opted in to anonymous telemetry.\n *\n * @returns True if telemetry is explicitly enabled in ~/.marsrc\n * @example\n * if (isTelemetryEnabled()) trackEvent('create');\n */\nexport function isTelemetryEnabled(): boolean {\n try {\n const config = fs.readJsonSync(RC_PATH) as TelemetryConfig;\n return config.enabled === true;\n } catch {\n return false;\n }\n}\n\n/**\n * Enables anonymous telemetry by writing `enabled: true` to ~/.marsrc.\n *\n * @example\n * enableTelemetry();\n */\nexport function enableTelemetry(): void {\n const config = loadOrCreateConfig();\n config.enabled = true;\n fs.writeJsonSync(RC_PATH, config, { spaces: 2 });\n}\n\n/**\n * Disables anonymous telemetry by writing `enabled: false` to ~/.marsrc.\n *\n * @example\n * disableTelemetry();\n */\nexport function disableTelemetry(): void {\n const config = loadOrCreateConfig();\n config.enabled = false;\n fs.writeJsonSync(RC_PATH, config, { spaces: 2 });\n}\n\nfunction loadOrCreateConfig(): TelemetryConfig {\n try {\n return fs.readJsonSync(RC_PATH) as TelemetryConfig;\n } catch {\n return { enabled: false, anonymousId: crypto.randomUUID() };\n }\n}\n\n/**\n * Records an anonymous telemetry event to a local log file.\n * No-ops silently when telemetry is disabled. Never collects PII,\n * project names, file contents, or environment variables.\n *\n * @param event - The event name (e.g. 'create', 'add', 'deploy')\n * @param properties - Optional key-value metadata (feature flags, subcommand type, etc.)\n * @example\n * trackEvent('create', { features: 'auth,blog' });\n */\nexport function trackEvent(\n event: string,\n properties?: Record<string, string | number | boolean>,\n): void {\n if (!isTelemetryEnabled()) return;\n\n const config = loadOrCreateConfig();\n const payload = {\n event,\n anonymousId: config.anonymousId,\n properties: {\n ...properties,\n cliVersion: process.env.npm_package_version ?? 'unknown',\n nodeVersion: process.version,\n os: process.platform,\n arch: process.arch,\n },\n timestamp: new Date().toISOString(),\n };\n\n const logPath = path.join(os.homedir(), '.mars-telemetry.log');\n fs.appendFile(logPath, JSON.stringify(payload) + '\\n').catch(() => {});\n}\n","import fs from 'fs-extra';\nimport path from 'node:path';\nimport { execSync } from 'node:child_process';\nimport { log } from '../utils/logger.js';\n\ninterface Check {\n name: string;\n check: () => boolean | string;\n}\n\ninterface DoctorOptions {\n upgradeCheck?: boolean;\n}\n\ninterface NpmRegistryResponse {\n version: string;\n name: string;\n}\n\nfunction commandExists(cmd: string): boolean {\n try {\n execSync(`which ${cmd}`, { stdio: 'pipe' });\n return true;\n } catch {\n return false;\n }\n}\n\nfunction getVersion(cmd: string): string {\n try {\n return execSync(`${cmd} --version`, { stdio: 'pipe' }).toString().trim().split('\\n')[0];\n } catch {\n return 'not found';\n }\n}\n\nasync function checkForUpgrades(): Promise<void> {\n log.blank();\n log.title('Upgrade Check');\n\n const packageJsonPath = path.join(process.cwd(), 'package.json');\n if (!fs.pathExistsSync(packageJsonPath)) {\n log.warn('No package.json found — skipping upgrade check.');\n return;\n }\n\n const packageJson = fs.readJsonSync(packageJsonPath) as Record<string, unknown>;\n const deps = (packageJson.dependencies ?? {}) as Record<string, string>;\n const devDeps = (packageJson.devDependencies ?? {}) as Record<string, string>;\n\n const currentRaw = deps['@mars-stack/core'] ?? devDeps['@mars-stack/core'];\n if (!currentRaw) {\n log.warn('@mars-stack/core not found in dependencies — skipping upgrade check.');\n return;\n }\n\n const currentVersion = currentRaw.replace(/^[\\^~]/, '');\n log.info(`Current @mars-stack/core version: ${currentVersion}`);\n\n log.step('Fetching latest version from npm...');\n\n let latestVersion: string;\n try {\n const response = await fetch('https://registry.npmjs.org/@mars-stack/core/latest');\n if (!response.ok) {\n log.warn(`npm registry returned status ${response.status}. Skipping upgrade check.`);\n return;\n }\n const data = (await response.json()) as NpmRegistryResponse;\n latestVersion = data.version;\n } catch (error: unknown) {\n const message = error instanceof Error ? error.message : 'Unknown error';\n log.warn(`Could not reach npm registry: ${message}`);\n log.warn('Check your network connection and try again.');\n return;\n }\n\n log.info(`Latest @mars-stack/core version: ${latestVersion}`);\n log.blank();\n\n if (currentVersion === latestVersion) {\n log.success('@mars-stack/core is up to date.');\n } else {\n log.warn(`Upgrade available: ${currentVersion} → ${latestVersion}`);\n log.info('Changelog: https://github.com/greaveselliott/mars/blob/main/CHANGELOG.md');\n log.info('Run `mars upgrade` to update all Mars packages.');\n }\n}\n\nexport async function doctorCommand(options?: DoctorOptions): Promise<void> {\n log.title('MARS Doctor');\n log.info('Checking your development environment...\\n');\n\n const checks: Check[] = [\n {\n name: 'Node.js (>=20)',\n check: () => {\n const version = process.version;\n const major = parseInt(version.slice(1).split('.')[0], 10);\n return major >= 20 ? `${version}` : `${version} (requires >=20)`;\n },\n },\n {\n name: 'Yarn',\n check: () => (commandExists('yarn') ? getVersion('yarn') : false),\n },\n {\n name: 'Docker',\n check: () => (commandExists('docker') ? getVersion('docker') : false),\n },\n {\n name: 'Git',\n check: () => (commandExists('git') ? getVersion('git') : false),\n },\n {\n name: 'package.json exists',\n check: () => fs.pathExistsSync(path.join(process.cwd(), 'package.json')),\n },\n {\n name: '.env file exists',\n check: () => fs.pathExistsSync(path.join(process.cwd(), '.env')),\n },\n {\n name: 'Prisma schema exists',\n check: () =>\n fs.pathExistsSync(path.join(process.cwd(), 'prisma', 'schema')) ||\n fs.pathExistsSync(path.join(process.cwd(), 'prisma', 'schema.prisma')),\n },\n {\n name: 'node_modules installed',\n check: () => fs.pathExistsSync(path.join(process.cwd(), 'node_modules')),\n },\n {\n name: 'DATABASE_URL set',\n check: () => {\n try {\n const envContent = fs.readFileSync(path.join(process.cwd(), '.env'), 'utf-8');\n const match = envContent.match(/^DATABASE_URL=(.+)$/m);\n return match ? match[1] !== '' : false;\n } catch {\n return false;\n }\n },\n },\n {\n name: 'JWT_SECRET set',\n check: () => {\n try {\n const envContent = fs.readFileSync(path.join(process.cwd(), '.env'), 'utf-8');\n const match = envContent.match(/^JWT_SECRET=(.+)$/m);\n if (!match || !match[1]) return false;\n return match[1].length >= 32\n ? true\n : 'set but too short (need >=32 chars)';\n } catch {\n return false;\n }\n },\n },\n ];\n\n let passed = 0;\n let failed = 0;\n let warned = 0;\n\n for (const { name, check } of checks) {\n const result = check();\n\n if (result === true) {\n log.success(name);\n passed++;\n } else if (result === false) {\n log.error(name);\n failed++;\n } else if (typeof result === 'string' && !result.includes('requires') && !result.includes('too short')) {\n log.success(`${name}: ${result}`);\n passed++;\n } else {\n log.warn(`${name}: ${result}`);\n warned++;\n }\n }\n\n log.blank();\n log.info(`${passed} passed, ${warned} warnings, ${failed} failed`);\n\n if (failed > 0) {\n log.blank();\n log.warn('Fix the issues above before running your project.');\n } else {\n log.blank();\n log.success('Your environment looks good!');\n }\n\n if (options?.upgradeCheck) {\n await checkForUpgrades();\n }\n}\n","import fs from 'fs-extra';\nimport path from 'node:path';\nimport pc from 'picocolors';\nimport { log } from '../utils/logger.js';\nimport { appendToDbSchema, updateQualityScore } from '../utils/doc-updater.js';\nimport { createRollbackContext } from '../utils/rollback.js';\nimport { trackEvent } from '../utils/telemetry.js';\n\nfunction ensureInProject(): string {\n const cwd = process.cwd();\n const configPath = path.join(cwd, 'src', 'config', 'app.config.ts');\n if (!fs.pathExistsSync(configPath)) {\n log.error('Not inside a MARS project. Run this command from the project root.');\n process.exit(1);\n }\n return cwd;\n}\n\nfunction toKebab(str: string): string {\n return str\n .replace(/([a-z])([A-Z])/g, '$1-$2')\n .replace(/[\\s_]+/g, '-')\n .toLowerCase();\n}\n\nfunction toPascal(str: string): string {\n return str\n .replace(/(^|[-_\\s])(\\w)/g, (_, _sep, c) => c.toUpperCase());\n}\n\nfunction toCamel(str: string): string {\n const pascal = toPascal(str);\n return pascal.charAt(0).toLowerCase() + pascal.slice(1);\n}\n\nfunction pluralize(word: string): string {\n if (word.endsWith('s') || word.endsWith('x') || word.endsWith('z') || word.endsWith('ch') || word.endsWith('sh')) {\n return word + 'es';\n }\n if (word.endsWith('y') && !/[aeiou]y$/i.test(word)) {\n return word.slice(0, -1) + 'ies';\n }\n return word + 's';\n}\n\nfunction stripBrackets(segment: string): string {\n return segment.replace(/[\\[\\]]/g, '');\n}\n\nexport async function addFeatureCommand(name: string): Promise<void> {\n const root = ensureInProject();\n const kebab = toKebab(name);\n const pascal = toPascal(name);\n const camel = toCamel(name);\n const featureDir = path.join(root, 'src', 'features', kebab);\n\n if (await fs.pathExists(featureDir)) {\n log.error(`Feature \"${kebab}\" already exists at src/features/${kebab}/`);\n return;\n }\n\n const files: Record<string, string> = {\n 'server/index.ts': `import 'server-only';\n\nimport { prisma } from '@/lib/prisma';\nimport type { Create${pascal}Input, Update${pascal}Input } from '../validation/schemas';\n\nexport async function findAll${pluralize(pascal)}ForUser(userId: string) {\n return prisma.${camel}.findMany({\n where: { userId },\n orderBy: { createdAt: 'desc' },\n });\n}\n\nexport async function find${pascal}ById(id: string) {\n return prisma.${camel}.findUnique({ where: { id } });\n}\n\nexport async function create${pascal}(userId: string, data: Create${pascal}Input) {\n return prisma.${camel}.create({\n data: { ...data, userId },\n });\n}\n\nexport async function update${pascal}(id: string, data: Update${pascal}Input) {\n return prisma.${camel}.update({ where: { id }, data });\n}\n\nexport async function delete${pascal}(id: string) {\n return prisma.${camel}.delete({ where: { id } });\n}\n`,\n 'validation/schemas.ts': `import { z } from 'zod';\n\nexport const ${camel}Schemas = {\n create: z.object({\n name: z.string().min(1, 'Name is required').max(100),\n }),\n update: z.object({\n name: z.string().min(1).max(100).optional(),\n }),\n};\n\nexport type Create${pascal}Input = z.infer<typeof ${camel}Schemas.create>;\nexport type Update${pascal}Input = z.infer<typeof ${camel}Schemas.update>;\n`,\n 'types.ts': `export interface ${pascal} {\n id: string;\n name: string;\n userId: string;\n createdAt: Date;\n updatedAt: Date;\n}\n`,\n 'components/.gitkeep': '',\n 'hooks/.gitkeep': '',\n };\n\n const ctx = createRollbackContext();\n\n try {\n ctx.trackCreatedFile(featureDir);\n\n let count = 0;\n for (const [filePath, content] of Object.entries(files)) {\n const fullPath = path.join(featureDir, filePath);\n await fs.ensureDir(path.dirname(fullPath));\n await fs.writeFile(fullPath, content);\n count++;\n }\n\n await ctx.commit();\n\n log.success(`Created feature ${pc.bold(kebab)} with ${count} files`);\n trackEvent('add', { type: 'feature' });\n log.blank();\n log.step(`Add a Prisma model: ${pc.dim(`mars add model ${pascal}`)}`);\n log.step(`Add API routes: ${pc.dim(`mars add page ${kebab} --protected`)}`);\n log.blank();\n\n updateQualityScore(root, pascal, 'D').catch(() => {});\n } catch (error) {\n await ctx.rollback();\n throw error;\n }\n}\n\nexport async function addPageCommand(routePath: string, options: { protected?: boolean }): Promise<void> {\n const root = ensureInProject();\n const cleanPath = routePath.startsWith('/') ? routePath.slice(1) : routePath;\n const group = options.protected ? '(protected)' : '(public)';\n const pageDir = path.join(root, 'src', 'app', group, cleanPath);\n\n if (await fs.pathExists(path.join(pageDir, 'page.tsx'))) {\n log.error(`Page already exists at src/app/${group}/${cleanPath}/page.tsx`);\n return;\n }\n\n const lastSegment = cleanPath.split('/').pop() || 'page';\n const pageName = toPascal(stripBrackets(lastSegment));\n\n const pageContent = `import { Card, CardHeader, CardBody } from '@mars-stack/ui';\nimport type { Metadata } from 'next';\n\nexport const metadata: Metadata = {\n title: '${pageName}',\n};\n\nexport default function ${pageName}Page() {\n return (\n <div className=\"mx-auto max-w-4xl space-y-6 p-6\">\n <div>\n <h1 className=\"text-4xl font-bold text-text-primary mb-4\">${pageName}</h1>\n <p className=\"text-base text-text-secondary mb-4\">\n Description goes here.\n </p>\n </div>\n\n <Card>\n <CardHeader>\n <h2 className=\"text-lg font-semibold text-text-primary\">${pageName}</h2>\n </CardHeader>\n <CardBody>\n {/* Content */}\n </CardBody>\n </Card>\n </div>\n );\n}\n`;\n\n const loadingContent = `import { Spinner } from '@mars-stack/ui';\n\nexport default function Loading() {\n return (\n <div className=\"flex min-h-[50vh] items-center justify-center\">\n <Spinner size=\"lg\" />\n </div>\n );\n}\n`;\n\n const ctx = createRollbackContext();\n\n try {\n ctx.trackCreatedFile(pageDir);\n await fs.ensureDir(pageDir);\n await fs.writeFile(path.join(pageDir, 'page.tsx'), pageContent);\n await fs.writeFile(path.join(pageDir, 'loading.tsx'), loadingContent);\n\n await ctx.commit();\n\n log.success(`Created page at ${pc.bold(`src/app/${group}/${cleanPath}/`)}`);\n trackEvent('add', { type: 'page' });\n log.step(`page.tsx`);\n log.step(`loading.tsx`);\n log.blank();\n } catch (error) {\n await ctx.rollback();\n throw error;\n }\n}\n\nexport async function addModelCommand(name: string): Promise<void> {\n const root = ensureInProject();\n const pascal = toPascal(name);\n const camel = toCamel(name);\n const kebab = toKebab(name);\n const schemaDir = path.join(root, 'prisma', 'schema');\n const schemaFile = path.join(schemaDir, `${kebab}.prisma`);\n\n if (await fs.pathExists(schemaFile)) {\n log.error(`Schema file already exists: prisma/schema/${kebab}.prisma`);\n return;\n }\n\n const content = `model ${pascal} {\n id String @id @default(cuid())\n name String\n userId String\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@index([userId])\n}\n`;\n\n const ctx = createRollbackContext();\n\n try {\n ctx.trackCreatedFile(schemaFile);\n await fs.ensureDir(schemaDir);\n await fs.writeFile(schemaFile, content);\n\n await ctx.commit();\n\n log.success(`Created model ${pc.bold(pascal)} at prisma/schema/${kebab}.prisma`);\n trackEvent('add', { type: 'model' });\n log.blank();\n log.warn(`Remember to:`);\n log.step(`Add the reverse relation to the User model in prisma/schema/auth.prisma`);\n log.step(`Run ${pc.dim('yarn db:push')} to sync the database`);\n log.blank();\n\n const defaultFields = ['id', 'name', 'userId', 'createdAt', 'updatedAt'];\n appendToDbSchema(root, pascal, defaultFields).catch(() => {});\n } catch (error) {\n await ctx.rollback();\n throw error;\n }\n}\n\nexport async function addEmailCommand(name: string): Promise<void> {\n const root = ensureInProject();\n const kebab = toKebab(name);\n const pascal = toPascal(name);\n const camel = toCamel(name);\n const templatesDir = path.join(root, 'src', 'lib', 'core', 'email', 'templates');\n const filePath = path.join(templatesDir, `${kebab}-email.ts`);\n\n if (await fs.pathExists(filePath)) {\n log.error(`Email template already exists: src/lib/core/email/templates/${kebab}-email.ts`);\n return;\n }\n\n const functionName = `${camel}EmailHtml`;\n\n const content = `import { emailLayout, emailButton } from './base-layout';\n\ninterface ${pascal}EmailOptions {\n appName: string;\n actionUrl: string;\n userName?: string;\n}\n\nexport function ${functionName}({ appName, actionUrl, userName }: ${pascal}EmailOptions): { html: string; text: string } {\n const greeting = userName ? \\`Hi \\${userName},\\` : 'Hi there,';\n\n const content = \\`\n <h1 style=\"margin: 0 0 16px 0; font-size: 24px; font-weight: 700; color: #111827;\">${pascal}</h1>\n <p style=\"margin: 0 0 8px 0;\">\\${greeting}</p>\n <p style=\"margin: 0 0 8px 0;\">Add your email content here.</p>\n \\${emailButton(actionUrl, 'Take Action')}\n <p style=\"margin: 0; font-size: 14px; color: #6b7280;\">If the button doesn't work, copy and paste this link into your browser:</p>\n <p style=\"margin: 0; font-size: 14px; word-break: break-all; color: #6366f1;\">\\${actionUrl}</p>\\`;\n\n const html = emailLayout({\n appName,\n previewText: \\`${pascal} notification from \\${appName}\\`,\n content,\n });\n\n const text = [\n '${pascal}',\n '',\n \\`\\${greeting}\\`,\n '',\n 'Add your email content here.',\n '',\n actionUrl,\n ].join('\\\\n');\n\n return { html, text };\n}\n`;\n\n const ctx = createRollbackContext();\n const indexPath = path.join(templatesDir, 'index.ts');\n\n try {\n ctx.trackCreatedFile(filePath);\n if (await fs.pathExists(indexPath)) {\n await ctx.trackModifiedFile(indexPath);\n } else {\n ctx.trackCreatedFile(indexPath);\n }\n\n await fs.ensureDir(templatesDir);\n await fs.writeFile(filePath, content);\n\n const exportLine = `export { ${functionName} } from './${kebab}-email';\\n`;\n\n if (await fs.pathExists(indexPath)) {\n const existing = await fs.readFile(indexPath, 'utf-8');\n if (!existing.includes(functionName)) {\n await fs.appendFile(indexPath, exportLine);\n }\n } else {\n await fs.writeFile(indexPath, exportLine);\n }\n\n await ctx.commit();\n\n log.success(`Created email template ${pc.bold(kebab)} at src/lib/core/email/templates/${kebab}-email.ts`);\n trackEvent('add', { type: 'email' });\n log.blank();\n log.step(`Exported ${pc.dim(functionName)} from templates/index.ts`);\n log.step(`Edit the template and customize the content, subject, and preview text`);\n log.blank();\n } catch (error) {\n await ctx.rollback();\n throw error;\n }\n}\n\nexport async function addComponentCommand(name: string, options: { type?: string }): Promise<void> {\n const root = ensureInProject();\n const pascal = toPascal(name);\n const type = options.type || 'primitive';\n const validTypes = ['primitive', 'pattern'];\n\n if (!validTypes.includes(type)) {\n log.error(`Invalid type \"${type}\". Use: ${validTypes.join(', ')}`);\n return;\n }\n\n const dir = type === 'primitive'\n ? path.join(root, 'src', 'components', 'primitives')\n : path.join(root, 'src', 'components', 'patterns');\n\n await fs.ensureDir(dir);\n const filePath = path.join(dir, `${pascal}.tsx`);\n\n if (await fs.pathExists(filePath)) {\n log.error(`Component already exists: ${pascal}.tsx`);\n return;\n }\n\n const content = type === 'primitive'\n ? `import { clsx } from 'clsx';\nimport { type ComponentPropsWithoutRef, forwardRef } from 'react';\n\nexport interface ${pascal}Props extends ComponentPropsWithoutRef<'div'> {\n variant?: 'default' | 'outlined';\n}\n\nexport const ${pascal} = forwardRef<HTMLDivElement, ${pascal}Props>(\n ({ variant = 'default', className, children, ...rest }, ref) => {\n return (\n <div\n ref={ref}\n className={clsx(\n 'rounded-lg',\n variant === 'default' && 'bg-surface-card text-text-primary',\n variant === 'outlined' && 'border border-border-default text-text-primary',\n className,\n )}\n {...rest}\n >\n {children}\n </div>\n );\n },\n);\n\n${pascal}.displayName = '${pascal}';\n`\n : `import { clsx } from 'clsx';\n\nexport interface ${pascal}Props {\n children: React.ReactNode;\n className?: string;\n}\n\nexport function ${pascal}({ children, className }: ${pascal}Props) {\n return (\n <div className={clsx('', className)}>\n {children}\n </div>\n );\n}\n`;\n\n const ctx = createRollbackContext();\n\n try {\n ctx.trackCreatedFile(filePath);\n await fs.writeFile(filePath, content);\n\n await ctx.commit();\n\n log.success(`Created ${type} component ${pc.bold(pascal)} at ${path.relative(root, filePath)}`);\n trackEvent('add', { type: 'component', componentType: type });\n log.blank();\n log.warn(`Remember to add the export to the barrel file:`);\n log.step(`src/components/${type === 'primitive' ? 'primitives' : 'patterns'}/index.ts`);\n log.blank();\n } catch (error) {\n await ctx.rollback();\n throw error;\n }\n}\n","import fs from 'fs-extra';\nimport path from 'node:path';\n\nexport async function appendToApiRoutes(\n projectDir: string,\n routePath: string,\n method: string,\n authType: string,\n): Promise<void> {\n const filePath = path.join(projectDir, 'docs', 'generated', 'api-routes.md');\n if (!(await fs.pathExists(filePath))) return;\n\n const line = `| \\`${method}\\` | \\`${routePath}\\` | ${authType} |\\n`;\n await fs.appendFile(filePath, line);\n}\n\nexport async function appendToDbSchema(\n projectDir: string,\n modelName: string,\n fields: string[],\n): Promise<void> {\n const filePath = path.join(projectDir, 'docs', 'generated', 'db-schema.md');\n if (!(await fs.pathExists(filePath))) return;\n\n const entry = [\n '',\n `### ${modelName}`,\n '',\n '| Field | Type |',\n '|-------|------|',\n ...fields.map((f) => `| ${f} | |`),\n '',\n ].join('\\n');\n\n await fs.appendFile(filePath, entry);\n}\n\nexport async function updateQualityScore(\n projectDir: string,\n domain: string,\n grade: string,\n): Promise<void> {\n const filePath = path.join(projectDir, 'docs', 'QUALITY_SCORE.md');\n if (!(await fs.pathExists(filePath))) return;\n\n const content = await fs.readFile(filePath, 'utf-8');\n const pattern = new RegExp(`^\\\\|\\\\s*${escapeRegex(domain)}\\\\s*\\\\|`, 'm');\n\n if (pattern.test(content)) {\n const updated = content.replace(pattern, (match) => {\n const parts = match.split('|').map((s) => s.trim());\n parts[2] = ` ${grade} `;\n return parts.join('|');\n });\n await fs.writeFile(filePath, updated);\n } else {\n const row = `| ${domain} | ${grade} | |\\n`;\n await fs.appendFile(filePath, row);\n }\n}\n\nfunction escapeRegex(str: string): string {\n return str.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n","import { execSync } from 'node:child_process';\nimport fs from 'fs-extra';\nimport path from 'node:path';\nimport pc from 'picocolors';\nimport prompts from 'prompts';\nimport { log } from '../utils/logger.js';\n\nfunction ensureInProject(): string {\n const cwd = process.cwd();\n const configPath = path.join(cwd, 'src', 'config', 'app.config.ts');\n if (!fs.pathExistsSync(configPath)) {\n log.error('Not inside a MARS project. Run this command from the project root.');\n process.exit(1);\n }\n return cwd;\n}\n\nconst PROVIDER_DEPENDENCIES: Record<string, string[]> = {\n 'email:sendgrid': ['@sendgrid/mail'],\n 'email:resend': ['resend'],\n 'payments:stripe': ['stripe'],\n 'storage:vercel': ['@vercel/blob'],\n 'storage:s3': ['@aws-sdk/client-s3', '@aws-sdk/s3-request-presigner'],\n};\n\nfunction updateAppConfig(\n projectDir: string,\n serviceKey: string,\n provider: string,\n featureKey?: string,\n): void {\n const configPath = path.join(projectDir, 'src', 'config', 'app.config.ts');\n let content = fs.readFileSync(configPath, 'utf-8');\n\n if (serviceKey === 'auth') {\n const boolValue = provider === 'google' ? 'true' : 'false';\n const featureRegex = new RegExp(`(googleOAuth\\\\s*:\\\\s*)(?:true|false)`);\n content = content.replace(featureRegex, `$1${boolValue}`);\n } else {\n const providerRegex = new RegExp(\n `(${serviceKey}\\\\s*:\\\\s*\\\\{[^}]*provider\\\\s*:\\\\s*)(['\"])[^'\"]*\\\\2`,\n );\n content = content.replace(providerRegex, `$1$2${provider}$2`);\n\n if (featureKey) {\n const featureRegex = new RegExp(`(${featureKey}\\\\s*:\\\\s*)(?:true|false)`);\n content = content.replace(featureRegex, `$1true`);\n }\n }\n\n fs.writeFileSync(configPath, content);\n}\n\nfunction detectPackageManager(projectDir: string): 'yarn' | 'npm' {\n if (fs.existsSync(path.join(projectDir, 'yarn.lock'))) return 'yarn';\n return 'npm';\n}\n\nfunction installDependencies(projectDir: string, deps: string[]): void {\n if (deps.length === 0) return;\n\n const pm = detectPackageManager(projectDir);\n const cmd = pm === 'yarn'\n ? `yarn add ${deps.join(' ')}`\n : `npm install ${deps.join(' ')}`;\n\n execSync(cmd, { cwd: projectDir, stdio: 'pipe' });\n}\n\nconst SERVICE_CONFIGS: Record<string, {\n providers: Array<{ value: string; title: string; envVars: string[] }>;\n configKey: string;\n featureKey?: string;\n}> = {\n email: {\n configKey: 'email',\n providers: [\n { value: 'console', title: 'Console (development only)', envVars: [] },\n { value: 'sendgrid', title: 'SendGrid', envVars: ['SENDGRID_API_KEY', 'SENDGRID_FROM_EMAIL'] },\n { value: 'resend', title: 'Resend', envVars: ['RESEND_API_KEY', 'RESEND_FROM_EMAIL'] },\n ],\n },\n payments: {\n configKey: 'payments',\n featureKey: 'billing',\n providers: [\n { value: 'none', title: 'None', envVars: [] },\n { value: 'stripe', title: 'Stripe', envVars: ['STRIPE_SECRET_KEY', 'STRIPE_WEBHOOK_SECRET', 'NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY'] },\n ],\n },\n storage: {\n configKey: 'storage',\n featureKey: 'fileUpload',\n providers: [\n { value: 'local', title: 'Local filesystem', envVars: [] },\n { value: 'vercel', title: 'Vercel Blob', envVars: ['BLOB_READ_WRITE_TOKEN'] },\n { value: 's3', title: 'AWS S3', envVars: ['AWS_ACCESS_KEY_ID', 'AWS_SECRET_ACCESS_KEY', 'AWS_REGION', 'S3_BUCKET_NAME'] },\n ],\n },\n analytics: {\n configKey: 'analytics',\n featureKey: 'analytics',\n providers: [\n { value: 'none', title: 'None', envVars: [] },\n { value: 'vercel', title: 'Vercel Analytics', envVars: [] },\n { value: 'posthog', title: 'PostHog', envVars: ['NEXT_PUBLIC_POSTHOG_KEY', 'NEXT_PUBLIC_POSTHOG_HOST'] },\n { value: 'google', title: 'Google Analytics', envVars: ['NEXT_PUBLIC_GA_MEASUREMENT_ID'] },\n ],\n },\n monitoring: {\n configKey: 'monitoring',\n featureKey: 'sentry',\n providers: [\n { value: 'none', title: 'None', envVars: [] },\n { value: 'sentry', title: 'Sentry', envVars: ['SENTRY_DSN', 'SENTRY_AUTH_TOKEN'] },\n ],\n },\n auth: {\n configKey: 'auth',\n featureKey: 'googleOAuth',\n providers: [\n { value: 'credentials', title: 'Email + Password only', envVars: [] },\n { value: 'google', title: 'Add Google OAuth', envVars: ['GOOGLE_CLIENT_ID', 'GOOGLE_CLIENT_SECRET'] },\n ],\n },\n};\n\nexport async function configureCommand(service?: string): Promise<void> {\n const root = ensureInProject();\n\n let selectedService = service;\n\n if (!selectedService) {\n const { chosen } = await prompts(\n {\n type: 'select',\n name: 'chosen',\n message: 'Which service do you want to configure?',\n choices: Object.entries(SERVICE_CONFIGS).map(([key]) => ({\n title: key.charAt(0).toUpperCase() + key.slice(1),\n value: key,\n description: `Configure ${key} provider`,\n })),\n },\n { onCancel: () => process.exit(0) },\n );\n selectedService = chosen;\n }\n\n const serviceConfig = SERVICE_CONFIGS[selectedService as string];\n if (!serviceConfig) {\n log.error(`Unknown service \"${selectedService}\". Available: ${Object.keys(SERVICE_CONFIGS).join(', ')}`);\n return;\n }\n\n const { provider } = await prompts(\n {\n type: 'select',\n name: 'provider',\n message: `Choose ${selectedService} provider`,\n choices: serviceConfig.providers.map((p) => ({\n title: p.title,\n value: p.value,\n })),\n },\n { onCancel: () => process.exit(0) },\n );\n\n const selectedProvider = serviceConfig.providers.find((p) => p.value === provider);\n if (!selectedProvider) return;\n\n log.blank();\n\n // 1. Update app.config.ts\n try {\n updateAppConfig(root, serviceConfig.configKey, provider, serviceConfig.featureKey);\n log.success(`Updated ${pc.dim('app.config.ts')} → ${pc.bold(`${serviceConfig.configKey}.provider = '${provider}'`)}`);\n } catch (error: unknown) {\n const message = error instanceof Error ? error.message : String(error);\n log.warn(`Could not update app.config.ts automatically: ${message}`);\n log.step(`Manually set ${pc.bold(`services.${serviceConfig.configKey}.provider`)} to ${pc.bold(`'${provider}'`)} in ${pc.dim('src/config/app.config.ts')}`);\n }\n\n // 2. Write .env placeholders\n if (selectedProvider.envVars.length > 0) {\n const envPath = path.join(root, '.env');\n if (await fs.pathExists(envPath)) {\n const envContent = await fs.readFile(envPath, 'utf-8');\n const missingVars = selectedProvider.envVars.filter(\n (v) => !envContent.includes(v),\n );\n\n if (missingVars.length > 0) {\n const additions = missingVars.map((v) => `${v}=\"\"`).join('\\n');\n await fs.appendFile(envPath, `\\n# ${selectedService} (${provider})\\n${additions}\\n`);\n log.success(`Added ${missingVars.length} env placeholder(s) to ${pc.dim('.env')}`);\n }\n }\n }\n\n // 3. Install SDK dependencies\n const depKey = `${selectedService}:${provider}`;\n const deps = PROVIDER_DEPENDENCIES[depKey];\n if (deps && deps.length > 0) {\n const pm = detectPackageManager(root);\n log.step(`Installing ${pc.bold(deps.join(', '))} via ${pm}…`);\n try {\n installDependencies(root, deps);\n log.success(`Installed ${deps.length} package(s)`);\n } catch (error: unknown) {\n const message = error instanceof Error ? error.message : String(error);\n log.warn(`Package install failed: ${message}`);\n log.step(`Run ${pc.bold(`${pm} add ${deps.join(' ')}`)} manually`);\n }\n }\n\n log.blank();\n log.success(`Configured ${pc.bold(selectedService as string)} → ${pc.bold(selectedProvider.title)}`);\n log.blank();\n}\n","import fs from 'fs-extra';\nimport path from 'node:path';\nimport { execSync } from 'node:child_process';\nimport pc from 'picocolors';\nimport prompts from 'prompts';\nimport { log } from '../utils/logger.js';\nimport { trackEvent } from '../utils/telemetry.js';\n\nfunction ensureInProject(): string {\n const cwd = process.cwd();\n const configPath = path.join(cwd, 'src', 'config', 'app.config.ts');\n if (!fs.pathExistsSync(configPath)) {\n log.error('Not inside a MARS project. Run this command from the project root.');\n process.exit(1);\n }\n return cwd;\n}\n\nfunction commandExists(cmd: string): boolean {\n try {\n execSync(`which ${cmd}`, { stdio: 'pipe' });\n return true;\n } catch {\n return false;\n }\n}\n\nfunction run(cmd: string, cwd: string): string {\n try {\n return execSync(cmd, { cwd, stdio: 'pipe', encoding: 'utf-8' }).trim();\n } catch (error) {\n const err = error as { stderr?: string; message?: string };\n throw new Error(err.stderr || err.message || 'Command failed');\n }\n}\n\nexport async function deployCommand(): Promise<void> {\n const root = ensureInProject();\n\n log.title('Mars Deploy');\n\n // 1. Check vercel CLI\n if (!commandExists('vercel')) {\n log.warn('Vercel CLI not found.');\n const { install } = await prompts({\n type: 'confirm',\n name: 'install',\n message: 'Install Vercel CLI globally?',\n initial: true,\n });\n\n if (install) {\n log.step('Installing Vercel CLI...');\n try {\n execSync('npm i -g vercel', { stdio: 'inherit' });\n log.success('Vercel CLI installed');\n } catch {\n log.error('Failed to install Vercel CLI. Install manually: npm i -g vercel');\n return;\n }\n } else {\n log.error('Vercel CLI is required for deployment.');\n return;\n }\n }\n\n // 2. Link project\n const vercelDir = path.join(root, '.vercel');\n if (!fs.existsSync(vercelDir)) {\n log.step('Linking project to Vercel...');\n try {\n execSync('vercel link', { cwd: root, stdio: 'inherit' });\n } catch {\n log.error('Failed to link project. Make sure you are logged into Vercel.');\n return;\n }\n } else {\n log.success('Project already linked to Vercel');\n }\n\n // 3. Detect configured services from app.config.ts\n log.blank();\n log.title('Environment Variables');\n log.info('The following env vars are required for your configured services:');\n log.blank();\n\n const requiredVars = ['JWT_SECRET', 'DATABASE_URL'];\n log.step(`Core: ${pc.dim(requiredVars.join(', '))}`);\n\n const configPath = path.join(root, 'src', 'config', 'app.config.ts');\n const configContent = await fs.readFile(configPath, 'utf-8');\n\n if (configContent.includes(\"email: { provider: 'sendgrid'\")) {\n log.step(`Email (SendGrid): ${pc.dim('SENDGRID_API_KEY, SENDGRID_FROM_EMAIL')}`);\n } else if (configContent.includes(\"email: { provider: 'resend'\")) {\n log.step(`Email (Resend): ${pc.dim('RESEND_API_KEY, RESEND_FROM_EMAIL')}`);\n }\n\n if (configContent.includes(\"payments: { provider: 'stripe'\")) {\n log.step(`Payments (Stripe): ${pc.dim('STRIPE_SECRET_KEY, NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY, STRIPE_WEBHOOK_SECRET')}`);\n }\n\n if (configContent.includes(\"storage: { provider: 'vercel'\")) {\n log.step(`Storage (Vercel Blob): ${pc.dim('BLOB_READ_WRITE_TOKEN')}`);\n }\n\n log.blank();\n log.info('Set these via the Vercel dashboard or:');\n log.step(`${pc.dim('vercel env add <NAME>')}`);\n\n // 4. Deploy\n log.blank();\n const { deploy } = await prompts({\n type: 'select',\n name: 'deploy',\n message: 'How would you like to deploy?',\n choices: [\n { title: 'Production deploy', value: 'prod' },\n { title: 'Preview deploy', value: 'preview' },\n { title: 'Setup Git integration (auto-deploy on push)', value: 'git' },\n { title: 'Skip deployment for now', value: 'skip' },\n ],\n });\n\n if (deploy === 'skip') {\n log.info('Skipping deployment. Run `mars deploy` again when ready.');\n return;\n }\n\n if (deploy === 'git') {\n log.info('To set up Git integration:');\n log.step('1. Push your code to GitHub/GitLab/Bitbucket');\n log.step('2. Visit https://vercel.com/import to import your repo');\n log.step('3. Vercel will auto-deploy on every push to main');\n return;\n }\n\n const deployCmd = deploy === 'prod' ? 'vercel deploy --prod' : 'vercel deploy';\n log.step(`Running: ${pc.dim(deployCmd)}`);\n log.blank();\n\n try {\n execSync(deployCmd, { cwd: root, stdio: 'inherit' });\n trackEvent('deploy');\n log.blank();\n log.success('Deployment complete!');\n } catch {\n log.error('Deployment failed. Check the output above for details.');\n return;\n }\n\n // 5. Post-deploy check\n log.blank();\n log.title('Post-Deploy Checklist');\n log.step('Verify env vars are set in the Vercel dashboard');\n log.step('Run database migrations: vercel env pull && yarn db:push');\n log.step('Seed the database if needed: yarn db:seed');\n log.step('Test the deployed app: visit the URL above');\n log.blank();\n}\n","import fs from 'fs-extra';\nimport path from 'node:path';\nimport { execSync } from 'node:child_process';\nimport { Command } from 'commander';\nimport { log } from '../utils/logger.js';\n\nconst MARS_PACKAGES = ['@mars-stack/core', '@mars-stack/ui'] as const;\n\nconst CHANGELOG_URL = 'https://github.com/greaveselliott/mars/blob/main/CHANGELOG.md';\n\ninterface NpmRegistryResponse {\n version: string;\n name: string;\n}\n\ninterface PackageVersionInfo {\n name: string;\n current: string | null;\n latest: string | null;\n updateAvailable: boolean;\n}\n\nasync function fetchLatestVersion(packageName: string): Promise<string | null> {\n try {\n const response = await fetch(`https://registry.npmjs.org/${packageName}/latest`);\n if (!response.ok) {\n return null;\n }\n const data = (await response.json()) as NpmRegistryResponse;\n return data.version;\n } catch {\n return null;\n }\n}\n\nfunction readCurrentVersion(\n packageJson: Record<string, unknown>,\n packageName: string,\n): string | null {\n const deps = packageJson.dependencies as Record<string, string> | undefined;\n const devDeps = packageJson.devDependencies as Record<string, string> | undefined;\n const version = deps?.[packageName] ?? devDeps?.[packageName] ?? null;\n return version ? version.replace(/^[\\^~]/, '') : null;\n}\n\nfunction detectPackageManager(projectDir: string): 'yarn' | 'npm' {\n if (fs.pathExistsSync(path.join(projectDir, 'yarn.lock'))) {\n return 'yarn';\n }\n return 'npm';\n}\n\nfunction getInstallCommand(pm: 'yarn' | 'npm'): string {\n return pm === 'yarn' ? 'yarn install' : 'npm install';\n}\n\nasync function gatherVersionInfo(\n packageJson: Record<string, unknown>,\n): Promise<PackageVersionInfo[]> {\n const results: PackageVersionInfo[] = [];\n\n for (const name of MARS_PACKAGES) {\n const current = readCurrentVersion(packageJson, name);\n const latest = await fetchLatestVersion(name);\n const updateAvailable =\n current !== null && latest !== null && current !== latest;\n\n results.push({ name, current, latest, updateAvailable });\n }\n\n return results;\n}\n\nfunction printVersionTable(versions: PackageVersionInfo[]): void {\n const colWidths = { name: 16, current: 12, latest: 12, status: 18 };\n const header = [\n 'Package'.padEnd(colWidths.name),\n 'Current'.padEnd(colWidths.current),\n 'Latest'.padEnd(colWidths.latest),\n 'Status'.padEnd(colWidths.status),\n ].join(' ');\n\n const divider = '-'.repeat(header.length);\n\n log.blank();\n log.info(header);\n log.info(divider);\n\n for (const info of versions) {\n const current = info.current ?? 'not installed';\n const latest = info.latest ?? 'unavailable';\n const status = info.current === null\n ? 'not installed'\n : info.latest === null\n ? 'registry error'\n : info.updateAvailable\n ? 'update available'\n : 'up to date';\n\n log.info(\n [\n info.name.padEnd(colWidths.name),\n current.padEnd(colWidths.current),\n latest.padEnd(colWidths.latest),\n status.padEnd(colWidths.status),\n ].join(' '),\n );\n }\n\n log.blank();\n}\n\nfunction updatePackageJsonVersions(\n packageJsonPath: string,\n packageJson: Record<string, unknown>,\n versions: PackageVersionInfo[],\n): string[] {\n const updated: string[] = [];\n const deps = (packageJson.dependencies ?? {}) as Record<string, string>;\n const devDeps = (packageJson.devDependencies ?? {}) as Record<string, string>;\n\n for (const info of versions) {\n if (!info.updateAvailable || info.latest === null) continue;\n\n if (deps[info.name] !== undefined) {\n const prefix = deps[info.name].match(/^[\\^~]/)?.[0] ?? '^';\n deps[info.name] = `${prefix}${info.latest}`;\n updated.push(`${info.name}: ${info.current} → ${info.latest}`);\n } else if (devDeps[info.name] !== undefined) {\n const prefix = devDeps[info.name].match(/^[\\^~]/)?.[0] ?? '^';\n devDeps[info.name] = `${prefix}${info.latest}`;\n updated.push(`${info.name}: ${info.current} → ${info.latest}`);\n }\n }\n\n if (updated.length > 0) {\n packageJson.dependencies = deps;\n packageJson.devDependencies = devDeps;\n fs.writeJsonSync(packageJsonPath, packageJson, { spaces: 2 });\n }\n\n return updated;\n}\n\nexport function upgradeCommand(program: Command): void {\n program\n .command('upgrade')\n .description(\n 'Upgrade @mars-stack/core, @mars-stack/ui, and @mars-stack/cli to the latest versions',\n )\n .option('--dry-run', 'Show what would be updated without making changes')\n .action(async (options: { dryRun?: boolean }) => {\n log.title('MARS Upgrade');\n\n const projectDir = process.cwd();\n const packageJsonPath = path.join(projectDir, 'package.json');\n\n if (!fs.pathExistsSync(packageJsonPath)) {\n log.error(\n 'No package.json found. Are you in a Mars project directory?',\n );\n process.exitCode = 1;\n return;\n }\n\n const packageJson = fs.readJsonSync(packageJsonPath) as Record<string, unknown>;\n\n const hasMarsPackage = MARS_PACKAGES.some(\n (name) =>\n readCurrentVersion(packageJson, name) !== null,\n );\n\n if (!hasMarsPackage) {\n log.error(\n 'No @mars-stack packages found in dependencies. This does not appear to be a Mars project.',\n );\n process.exitCode = 1;\n return;\n }\n\n log.step('Checking for updates...');\n\n const versions = await gatherVersionInfo(packageJson);\n const registryErrors = versions.filter(\n (v) => v.current !== null && v.latest === null,\n );\n\n if (registryErrors.length > 0) {\n log.warn(\n 'Could not reach the npm registry for some packages. Check your network connection.',\n );\n }\n\n printVersionTable(versions);\n\n const updatesAvailable = versions.some((v) => v.updateAvailable);\n\n if (!updatesAvailable) {\n log.success('All Mars packages are up to date.');\n return;\n }\n\n if (options.dryRun) {\n log.info('Dry run — no changes were made.');\n log.info(`Run ${`mars upgrade`} without --dry-run to apply updates.`);\n return;\n }\n\n log.step('Updating package.json...');\n const updated = updatePackageJsonVersions(\n packageJsonPath,\n packageJson,\n versions,\n );\n\n for (const change of updated) {\n log.success(change);\n }\n\n const pm = detectPackageManager(projectDir);\n const installCmd = getInstallCommand(pm);\n\n log.blank();\n log.step(`Running ${installCmd}...`);\n\n try {\n execSync(installCmd, {\n cwd: projectDir,\n stdio: 'inherit',\n });\n } catch {\n log.error(`${installCmd} failed. You may need to run it manually.`);\n process.exitCode = 1;\n return;\n }\n\n log.blank();\n log.step('Running mars doctor to verify...');\n\n try {\n execSync('npx mars doctor', {\n cwd: projectDir,\n stdio: 'inherit',\n });\n } catch {\n log.warn(\n 'mars doctor reported issues. Review the output above.',\n );\n }\n\n log.blank();\n log.title('Upgrade Summary');\n for (const change of updated) {\n log.success(change);\n }\n log.blank();\n log.info(`Changelog: ${CHANGELOG_URL}`);\n log.info(\n 'Review the changelog for any breaking changes or migration notes.',\n );\n });\n}\n"],"mappings":"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","names":["fs","path","fs","path","fs","path","fs","path","setConfigFlag","STAMP","GENERATOR_VERSION","fs","path","fs","path","types","schemas","serverLogic","componentIndex","setConfigFlag","GENERATOR_VERSION","STAMP","fs","path","types","setConfigFlag","STAMP","GENERATOR_VERSION","fs","path","types","componentIndex","setConfigFlag","STAMP","GENERATOR_VERSION","fs","path","prismaSchema","types","serverLogic","schemas","componentIndex","featureIndex","setConfigFlag","GENERATOR_VERSION","STAMP","fs","path","types","schemas","componentIndex","featureIndex","setConfigFlag","STAMP","GENERATOR_VERSION","fs","path","types","serverIndex","featureIndex","setConfigFlag","STAMP","GENERATOR_VERSION","fs","path","types","schemas","barrelExports","setConfigFlag","STAMP","GENERATOR_VERSION","fs","path","types","featureIndex","setConfigFlag","STAMP","GENERATOR_VERSION","fs","path","types","schemas","componentIndex","barrelExports","setConfigFlag","STAMP","GENERATOR_VERSION","fs","path","types","componentsIndex","barrelExports","setConfigFlag","STAMP","GENERATOR_VERSION","fs","path","types","serverIndex","componentsIndex","featureIndex","setConfigFlag","STAMP","GENERATOR_VERSION","fs","path","os","pc","prompts","prompts","prompts","prompts","fs","path","crypto","fs","path","fs","path","os","RC_PATH","path","os","fs","pc","prompts","fs","path","fs","path","pc","fs","path","path","fs","path","fs","pc","execSync","fs","path","pc","prompts","ensureInProject","fs","path","execSync","pc","prompts","ensureInProject","path","fs","commandExists","execSync","ensureInProject","commandExists","prompts","execSync","path","fs","pc","fs","path","execSync","detectPackageManager","program"]}