@mars-stack/cli 2.0.1 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/dist/index.js +252 -241
  2. package/dist/index.js.map +1 -1
  3. package/package.json +1 -1
  4. package/template/.cursor/skills/mars-address-pr-comments/SKILL.md +129 -0
  5. package/template/AGENTS.md +3 -2
  6. /package/template/.cursor/rules/{composition-patterns.mdc → mars-composition-patterns.mdc} +0 -0
  7. /package/template/.cursor/rules/{data-access.mdc → mars-data-access.mdc} +0 -0
  8. /package/template/.cursor/rules/{project-structure.mdc → mars-project-structure.mdc} +0 -0
  9. /package/template/.cursor/rules/{security.mdc → mars-security.mdc} +0 -0
  10. /package/template/.cursor/rules/{testing.mdc → mars-testing.mdc} +0 -0
  11. /package/template/.cursor/rules/{ui-conventions.mdc → mars-ui-conventions.mdc} +0 -0
  12. /package/template/.cursor/skills/{add-api-route → mars-add-api-route}/SKILL.md +0 -0
  13. /package/template/.cursor/skills/{add-audit-log → mars-add-audit-log}/SKILL.md +0 -0
  14. /package/template/.cursor/skills/{add-blog → mars-add-blog}/SKILL.md +0 -0
  15. /package/template/.cursor/skills/{add-command-palette → mars-add-command-palette}/SKILL.md +0 -0
  16. /package/template/.cursor/skills/{add-component → mars-add-component}/SKILL.md +0 -0
  17. /package/template/.cursor/skills/{add-crud-routes → mars-add-crud-routes}/SKILL.md +0 -0
  18. /package/template/.cursor/skills/{add-e2e-test → mars-add-e2e-test}/SKILL.md +0 -0
  19. /package/template/.cursor/skills/{add-error-boundary → mars-add-error-boundary}/SKILL.md +0 -0
  20. /package/template/.cursor/skills/{add-feature → mars-add-feature}/SKILL.md +0 -0
  21. /package/template/.cursor/skills/{add-middleware → mars-add-middleware}/SKILL.md +0 -0
  22. /package/template/.cursor/skills/{add-page → mars-add-page}/SKILL.md +0 -0
  23. /package/template/.cursor/skills/{add-prisma-model → mars-add-prisma-model}/SKILL.md +0 -0
  24. /package/template/.cursor/skills/{add-protected-resource → mars-add-protected-resource}/SKILL.md +0 -0
  25. /package/template/.cursor/skills/{add-role → mars-add-role}/SKILL.md +0 -0
  26. /package/template/.cursor/skills/{add-server-action → mars-add-server-action}/SKILL.md +0 -0
  27. /package/template/.cursor/skills/{add-webhook → mars-add-webhook}/SKILL.md +0 -0
  28. /package/template/.cursor/skills/{build-complete-feature → mars-build-complete-feature}/SKILL.md +0 -0
  29. /package/template/.cursor/skills/{build-dashboard → mars-build-dashboard}/SKILL.md +0 -0
  30. /package/template/.cursor/skills/{build-data-table → mars-build-data-table}/SKILL.md +0 -0
  31. /package/template/.cursor/skills/{build-form → mars-build-form}/SKILL.md +0 -0
  32. /package/template/.cursor/skills/{build-landing-page → mars-build-landing-page}/SKILL.md +0 -0
  33. /package/template/.cursor/skills/{configure-ai → mars-configure-ai}/SKILL.md +0 -0
  34. /package/template/.cursor/skills/{configure-analytics → mars-configure-analytics}/SKILL.md +0 -0
  35. /package/template/.cursor/skills/{configure-dark-mode → mars-configure-dark-mode}/SKILL.md +0 -0
  36. /package/template/.cursor/skills/{configure-email → mars-configure-email}/SKILL.md +0 -0
  37. /package/template/.cursor/skills/{configure-email-verification → mars-configure-email-verification}/SKILL.md +0 -0
  38. /package/template/.cursor/skills/{configure-feature-flags → mars-configure-feature-flags}/SKILL.md +0 -0
  39. /package/template/.cursor/skills/{configure-i18n → mars-configure-i18n}/SKILL.md +0 -0
  40. /package/template/.cursor/skills/{configure-jobs → mars-configure-jobs}/SKILL.md +0 -0
  41. /package/template/.cursor/skills/{configure-magic-links → mars-configure-magic-links}/SKILL.md +0 -0
  42. /package/template/.cursor/skills/{configure-multi-tenancy → mars-configure-multi-tenancy}/SKILL.md +0 -0
  43. /package/template/.cursor/skills/{configure-notifications → mars-configure-notifications}/SKILL.md +0 -0
  44. /package/template/.cursor/skills/{configure-oauth → mars-configure-oauth}/SKILL.md +0 -0
  45. /package/template/.cursor/skills/{configure-onboarding → mars-configure-onboarding}/SKILL.md +0 -0
  46. /package/template/.cursor/skills/{configure-payments → mars-configure-payments}/SKILL.md +0 -0
  47. /package/template/.cursor/skills/{configure-realtime → mars-configure-realtime}/SKILL.md +0 -0
  48. /package/template/.cursor/skills/{configure-search → mars-configure-search}/SKILL.md +0 -0
  49. /package/template/.cursor/skills/{configure-storage → mars-configure-storage}/SKILL.md +0 -0
  50. /package/template/.cursor/skills/{configure-two-factor → mars-configure-two-factor}/SKILL.md +0 -0
  51. /package/template/.cursor/skills/{create-execution-plan → mars-create-execution-plan}/SKILL.md +0 -0
  52. /package/template/.cursor/skills/{create-seed → mars-create-seed}/SKILL.md +0 -0
  53. /package/template/.cursor/skills/{deploy-to-vercel → mars-deploy-to-vercel}/SKILL.md +0 -0
  54. /package/template/.cursor/skills/{design-tokens → mars-design-tokens}/SKILL.md +0 -0
  55. /package/template/.cursor/skills/{setup-billing → mars-setup-billing}/SKILL.md +0 -0
  56. /package/template/.cursor/skills/{setup-project → mars-setup-project}/SKILL.md +0 -0
  57. /package/template/.cursor/skills/{setup-teams → mars-setup-teams}/SKILL.md +0 -0
  58. /package/template/.cursor/skills/{test-api-route → mars-test-api-route}/SKILL.md +0 -0
  59. /package/template/.cursor/skills/{update-architecture-docs → mars-update-architecture-docs}/SKILL.md +0 -0
package/dist/index.js CHANGED
@@ -44,7 +44,7 @@ var init_logger = __esm({
44
44
  });
45
45
 
46
46
  // src/utils/rollback.ts
47
- import fs3 from "fs-extra";
47
+ import fs4 from "fs-extra";
48
48
  import path4 from "path";
49
49
  import os from "os";
50
50
  function createRollbackContext() {
@@ -58,10 +58,10 @@ function createRollbackContext() {
58
58
  manifest.filesCreated.push(filePath);
59
59
  }
60
60
  async function trackModifiedFile(filePath) {
61
- if (!await fs3.pathExists(filePath)) return;
62
- await fs3.ensureDir(backupDir);
61
+ if (!await fs4.pathExists(filePath)) return;
62
+ await fs4.ensureDir(backupDir);
63
63
  const backupPath = path4.join(backupDir, `${manifest.filesModified.length}-${path4.basename(filePath)}`);
64
- await fs3.copy(filePath, backupPath);
64
+ await fs4.copy(filePath, backupPath);
65
65
  manifest.filesModified.push({ path: filePath, backup: backupPath });
66
66
  }
67
67
  function trackInstalledDep(depName) {
@@ -70,13 +70,13 @@ function createRollbackContext() {
70
70
  async function rollback() {
71
71
  for (const filePath of manifest.filesCreated.reverse()) {
72
72
  try {
73
- await fs3.remove(filePath);
73
+ await fs4.remove(filePath);
74
74
  } catch {
75
75
  }
76
76
  }
77
77
  for (const { path: originalPath, backup } of manifest.filesModified) {
78
78
  try {
79
- await fs3.copy(backup, originalPath, { overwrite: true });
79
+ await fs4.copy(backup, originalPath, { overwrite: true });
80
80
  } catch {
81
81
  }
82
82
  }
@@ -86,9 +86,9 @@ function createRollbackContext() {
86
86
  await cleanupBackups();
87
87
  }
88
88
  async function cleanupBackups() {
89
- if (await fs3.pathExists(backupDir)) {
89
+ if (await fs4.pathExists(backupDir)) {
90
90
  try {
91
- await fs3.remove(backupDir);
91
+ await fs4.remove(backupDir);
92
92
  } catch {
93
93
  }
94
94
  }
@@ -108,15 +108,15 @@ var init_rollback = __esm({
108
108
  });
109
109
 
110
110
  // src/utils/dependencies.ts
111
- import fs4 from "fs-extra";
111
+ import fs5 from "fs-extra";
112
112
  import path5 from "path";
113
113
  async function addDependencies(projectRoot, deps, dev = false) {
114
114
  const pkgPath = path5.join(projectRoot, "package.json");
115
- if (!await fs4.pathExists(pkgPath)) return;
116
- const pkg = await fs4.readJson(pkgPath);
115
+ if (!await fs5.pathExists(pkgPath)) return;
116
+ const pkg = await fs5.readJson(pkgPath);
117
117
  const key = dev ? "devDependencies" : "dependencies";
118
118
  pkg[key] = { ...pkg[key], ...deps };
119
- await fs4.writeJson(pkgPath, pkg, { spaces: 2 });
119
+ await fs5.writeJson(pkgPath, pkg, { spaces: 2 });
120
120
  }
121
121
  var init_dependencies = __esm({
122
122
  "src/utils/dependencies.ts"() {
@@ -125,12 +125,12 @@ var init_dependencies = __esm({
125
125
  });
126
126
 
127
127
  // src/utils/routes.ts
128
- import fs5 from "fs-extra";
128
+ import fs6 from "fs-extra";
129
129
  import path6 from "path";
130
130
  async function registerRoute(projectRoot, key, routePath, ctx) {
131
131
  const routesFile = path6.join(projectRoot, "src", "config", "routes.ts");
132
- if (!await fs5.pathExists(routesFile)) return;
133
- let content = await fs5.readFile(routesFile, "utf-8");
132
+ if (!await fs6.pathExists(routesFile)) return;
133
+ let content = await fs6.readFile(routesFile, "utf-8");
134
134
  if (content.includes(`${key}:`)) return;
135
135
  if (ctx) {
136
136
  await ctx.trackModifiedFile(routesFile);
@@ -140,7 +140,7 @@ async function registerRoute(projectRoot, key, routePath, ctx) {
140
140
  ` ${key}: '${routePath}',
141
141
  } as const;`
142
142
  );
143
- await fs5.writeFile(routesFile, content);
143
+ await fs6.writeFile(routesFile, content);
144
144
  }
145
145
  var init_routes = __esm({
146
146
  "src/utils/routes.ts"() {
@@ -153,11 +153,11 @@ var blog_exports = {};
153
153
  __export(blog_exports, {
154
154
  generateBlog: () => generateBlog
155
155
  });
156
- import fs6 from "fs-extra";
156
+ import fs7 from "fs-extra";
157
157
  import path7 from "path";
158
158
  async function generateBlog(projectRoot) {
159
159
  const featureDir = path7.join(projectRoot, "src", "features", "blog");
160
- if (await fs6.pathExists(featureDir)) {
160
+ if (await fs7.pathExists(featureDir)) {
161
161
  log.error("Blog feature already exists at src/features/blog/");
162
162
  return;
163
163
  }
@@ -180,8 +180,8 @@ async function generateBlog(projectRoot) {
180
180
  for (const [filePath, content] of Object.entries(files)) {
181
181
  const fullPath = path7.join(projectRoot, filePath);
182
182
  ctx.trackCreatedFile(fullPath);
183
- await fs6.ensureDir(path7.dirname(fullPath));
184
- await fs6.writeFile(fullPath, content);
183
+ await fs7.ensureDir(path7.dirname(fullPath));
184
+ await fs7.writeFile(fullPath, content);
185
185
  count++;
186
186
  }
187
187
  await addDependencies(projectRoot, {
@@ -209,11 +209,11 @@ async function generateBlog(projectRoot) {
209
209
  }
210
210
  async function setConfigFlag(projectRoot, ctx) {
211
211
  const configPath = path7.join(projectRoot, "src", "config", "app.config.ts");
212
- if (!await fs6.pathExists(configPath)) return;
212
+ if (!await fs7.pathExists(configPath)) return;
213
213
  await ctx.trackModifiedFile(configPath);
214
- const content = await fs6.readFile(configPath, "utf-8");
214
+ const content = await fs7.readFile(configPath, "utf-8");
215
215
  const updated = content.replace(/blog:\s*false/, "blog: true");
216
- await fs6.writeFile(configPath, updated);
216
+ await fs7.writeFile(configPath, updated);
217
217
  }
218
218
  function schemas() {
219
219
  return `${STAMP}
@@ -732,11 +732,11 @@ var dark_mode_exports = {};
732
732
  __export(dark_mode_exports, {
733
733
  generateDarkMode: () => generateDarkMode
734
734
  });
735
- import fs7 from "fs-extra";
735
+ import fs8 from "fs-extra";
736
736
  import path8 from "path";
737
737
  async function generateDarkMode(projectRoot) {
738
738
  const featureDir = path8.join(projectRoot, "src", "features", "dark-mode");
739
- if (await fs7.pathExists(featureDir)) {
739
+ if (await fs8.pathExists(featureDir)) {
740
740
  log.error("Dark mode feature already exists at src/features/dark-mode/");
741
741
  return;
742
742
  }
@@ -753,8 +753,8 @@ async function generateDarkMode(projectRoot) {
753
753
  for (const [filePath, content] of Object.entries(files)) {
754
754
  const fullPath = path8.join(projectRoot, filePath);
755
755
  ctx.trackCreatedFile(fullPath);
756
- await fs7.ensureDir(path8.dirname(fullPath));
757
- await fs7.writeFile(fullPath, content);
756
+ await fs8.ensureDir(path8.dirname(fullPath));
757
+ await fs8.writeFile(fullPath, content);
758
758
  count++;
759
759
  }
760
760
  await wireLayout(projectRoot, ctx);
@@ -785,17 +785,17 @@ async function generateDarkMode(projectRoot) {
785
785
  }
786
786
  async function setConfigFlag2(projectRoot, ctx) {
787
787
  const configPath = path8.join(projectRoot, "src", "config", "app.config.ts");
788
- if (!await fs7.pathExists(configPath)) return;
788
+ if (!await fs8.pathExists(configPath)) return;
789
789
  await ctx.trackModifiedFile(configPath);
790
- const content = await fs7.readFile(configPath, "utf-8");
790
+ const content = await fs8.readFile(configPath, "utf-8");
791
791
  const updated = content.replace(/darkMode:\s*false/, "darkMode: true");
792
- await fs7.writeFile(configPath, updated);
792
+ await fs8.writeFile(configPath, updated);
793
793
  }
794
794
  async function wireLayout(projectRoot, ctx) {
795
795
  const layoutPath = path8.join(projectRoot, "src", "app", "layout.tsx");
796
- if (!await fs7.pathExists(layoutPath)) return;
796
+ if (!await fs8.pathExists(layoutPath)) return;
797
797
  await ctx.trackModifiedFile(layoutPath);
798
- let content = await fs7.readFile(layoutPath, "utf-8");
798
+ let content = await fs8.readFile(layoutPath, "utf-8");
799
799
  if (!content.includes("getThemeScript")) {
800
800
  content = `import { getThemeScript } from '@/features/dark-mode';
801
801
  ${content}`;
@@ -809,13 +809,13 @@ ${content}`;
809
809
  "$1\n <head>\n <script dangerouslySetInnerHTML={{ __html: getThemeScript() }} />\n </head>\n$2"
810
810
  );
811
811
  }
812
- await fs7.writeFile(layoutPath, content);
812
+ await fs8.writeFile(layoutPath, content);
813
813
  }
814
814
  async function wireProviders(projectRoot, ctx) {
815
815
  const providersPath = path8.join(projectRoot, "src", "app", "providers.tsx");
816
- if (!await fs7.pathExists(providersPath)) return;
816
+ if (!await fs8.pathExists(providersPath)) return;
817
817
  await ctx.trackModifiedFile(providersPath);
818
- let content = await fs7.readFile(providersPath, "utf-8");
818
+ let content = await fs8.readFile(providersPath, "utf-8");
819
819
  if (content.includes("ThemeProvider")) return;
820
820
  content = insertImportAfterDirectives(
821
821
  content,
@@ -834,13 +834,13 @@ async function wireProviders(projectRoot, ctx) {
834
834
  );`;
835
835
  }
836
836
  );
837
- await fs7.writeFile(providersPath, content);
837
+ await fs8.writeFile(providersPath, content);
838
838
  }
839
839
  async function wireProtectedNav(projectRoot, ctx) {
840
840
  const navPath = path8.join(projectRoot, "src", "app", "(protected)", "layout.tsx");
841
- if (!await fs7.pathExists(navPath)) return;
841
+ if (!await fs8.pathExists(navPath)) return;
842
842
  await ctx.trackModifiedFile(navPath);
843
- let content = await fs7.readFile(navPath, "utf-8");
843
+ let content = await fs8.readFile(navPath, "utf-8");
844
844
  if (content.includes("ThemeToggleSimple")) return;
845
845
  content = insertImportAfterDirectives(
846
846
  content,
@@ -855,19 +855,19 @@ async function wireProtectedNav(projectRoot, ctx) {
855
855
  /(<div className="border-t border-border-default px-4 py-3">\s*\n\s*<UserMenu \/>)/,
856
856
  '$1\n <div className="mt-2">\n <ThemeToggleSimple />\n </div>'
857
857
  );
858
- await fs7.writeFile(navPath, content);
858
+ await fs8.writeFile(navPath, content);
859
859
  }
860
860
  async function wireTailwindDarkMode(projectRoot, ctx) {
861
861
  const globalsPath = path8.join(projectRoot, "src", "styles", "globals.css");
862
- if (!await fs7.pathExists(globalsPath)) return;
862
+ if (!await fs8.pathExists(globalsPath)) return;
863
863
  await ctx.trackModifiedFile(globalsPath);
864
- let content = await fs7.readFile(globalsPath, "utf-8");
864
+ let content = await fs8.readFile(globalsPath, "utf-8");
865
865
  if (content.includes("@custom-variant dark")) return;
866
866
  content = content.replace(
867
867
  /@import 'tailwindcss';/,
868
868
  "@import 'tailwindcss';\n@custom-variant dark (&:where(.dark, .dark *));"
869
869
  );
870
- await fs7.writeFile(globalsPath, content);
870
+ await fs8.writeFile(globalsPath, content);
871
871
  }
872
872
  function themeProvider() {
873
873
  return `${STAMP2}
@@ -1147,19 +1147,19 @@ var init_dark_mode = __esm({
1147
1147
  });
1148
1148
 
1149
1149
  // src/utils/prisma.ts
1150
- import fs8 from "fs-extra";
1150
+ import fs9 from "fs-extra";
1151
1151
  import path9 from "path";
1152
1152
  async function addUserRelation(projectRoot, field, ctx) {
1153
1153
  const authPath = path9.join(projectRoot, "prisma", "schema", "auth.prisma");
1154
- if (!await fs8.pathExists(authPath)) return;
1154
+ if (!await fs9.pathExists(authPath)) return;
1155
1155
  await ctx.trackModifiedFile(authPath);
1156
- let content = await fs8.readFile(authPath, "utf-8");
1156
+ let content = await fs9.readFile(authPath, "utf-8");
1157
1157
  if (content.includes(field)) return;
1158
1158
  const insertBefore = " @@index([email])";
1159
1159
  content = content.replace(insertBefore, ` ${field}
1160
1160
 
1161
1161
  ${insertBefore}`);
1162
- await fs8.writeFile(authPath, content);
1162
+ await fs9.writeFile(authPath, content);
1163
1163
  }
1164
1164
  var init_prisma = __esm({
1165
1165
  "src/utils/prisma.ts"() {
@@ -1172,11 +1172,11 @@ var notifications_exports = {};
1172
1172
  __export(notifications_exports, {
1173
1173
  generateNotifications: () => generateNotifications
1174
1174
  });
1175
- import fs9 from "fs-extra";
1175
+ import fs10 from "fs-extra";
1176
1176
  import path10 from "path";
1177
1177
  async function generateNotifications(projectRoot) {
1178
1178
  const featureDir = path10.join(projectRoot, "src", "features", "notifications");
1179
- if (await fs9.pathExists(featureDir)) {
1179
+ if (await fs10.pathExists(featureDir)) {
1180
1180
  log.error("Notifications feature already exists at src/features/notifications/");
1181
1181
  return;
1182
1182
  }
@@ -1201,8 +1201,8 @@ async function generateNotifications(projectRoot) {
1201
1201
  for (const [filePath, content] of Object.entries(files)) {
1202
1202
  const fullPath = path10.join(projectRoot, filePath);
1203
1203
  ctx.trackCreatedFile(fullPath);
1204
- await fs9.ensureDir(path10.dirname(fullPath));
1205
- await fs9.writeFile(fullPath, content);
1204
+ await fs10.ensureDir(path10.dirname(fullPath));
1205
+ await fs10.writeFile(fullPath, content);
1206
1206
  count++;
1207
1207
  }
1208
1208
  await addUserRelation(projectRoot, "notifications Notification[]", ctx);
@@ -1230,9 +1230,9 @@ async function generateNotifications(projectRoot) {
1230
1230
  }
1231
1231
  async function wireProtectedNav2(projectRoot, ctx) {
1232
1232
  const navPath = path10.join(projectRoot, "src", "app", "(protected)", "layout.tsx");
1233
- if (!await fs9.pathExists(navPath)) return;
1233
+ if (!await fs10.pathExists(navPath)) return;
1234
1234
  await ctx.trackModifiedFile(navPath);
1235
- let content = await fs9.readFile(navPath, "utf-8");
1235
+ let content = await fs10.readFile(navPath, "utf-8");
1236
1236
  if (content.includes("NotificationBell")) return;
1237
1237
  content = insertImportAfterDirectives(
1238
1238
  content,
@@ -1243,15 +1243,15 @@ async function wireProtectedNav2(projectRoot, ctx) {
1243
1243
  /(<div className="flex items-center gap-3">)\s*\n(\s*)(<div className="hidden md:block">)/,
1244
1244
  "$1\n$2<NotificationBell />\n$2$3"
1245
1245
  );
1246
- await fs9.writeFile(navPath, content);
1246
+ await fs10.writeFile(navPath, content);
1247
1247
  }
1248
1248
  async function setConfigFlag3(projectRoot, ctx) {
1249
1249
  const configPath = path10.join(projectRoot, "src", "config", "app.config.ts");
1250
- if (!await fs9.pathExists(configPath)) return;
1250
+ if (!await fs10.pathExists(configPath)) return;
1251
1251
  await ctx.trackModifiedFile(configPath);
1252
- const content = await fs9.readFile(configPath, "utf-8");
1252
+ const content = await fs10.readFile(configPath, "utf-8");
1253
1253
  const updated = content.replace(/notifications:\s*false/, "notifications: true");
1254
- await fs9.writeFile(configPath, updated);
1254
+ await fs10.writeFile(configPath, updated);
1255
1255
  }
1256
1256
  function prismaSchema() {
1257
1257
  return `// Generated by mars generate notifications (notifications@${GENERATOR_VERSION3})
@@ -1847,11 +1847,11 @@ var analytics_exports = {};
1847
1847
  __export(analytics_exports, {
1848
1848
  generateAnalytics: () => generateAnalytics
1849
1849
  });
1850
- import fs10 from "fs-extra";
1850
+ import fs11 from "fs-extra";
1851
1851
  import path11 from "path";
1852
1852
  async function generateAnalytics(projectRoot) {
1853
1853
  const featureDir = path11.join(projectRoot, "src", "features", "analytics");
1854
- if (await fs10.pathExists(featureDir)) {
1854
+ if (await fs11.pathExists(featureDir)) {
1855
1855
  log.error("Analytics feature already exists at src/features/analytics/");
1856
1856
  return;
1857
1857
  }
@@ -1868,8 +1868,8 @@ async function generateAnalytics(projectRoot) {
1868
1868
  for (const [filePath, content] of Object.entries(files)) {
1869
1869
  const fullPath = path11.join(projectRoot, filePath);
1870
1870
  ctx.trackCreatedFile(fullPath);
1871
- await fs10.ensureDir(path11.dirname(fullPath));
1872
- await fs10.writeFile(fullPath, content);
1871
+ await fs11.ensureDir(path11.dirname(fullPath));
1872
+ await fs11.writeFile(fullPath, content);
1873
1873
  count++;
1874
1874
  }
1875
1875
  await wireProviders2(projectRoot, ctx);
@@ -1901,9 +1901,9 @@ async function generateAnalytics(projectRoot) {
1901
1901
  }
1902
1902
  async function wireProviders2(projectRoot, ctx) {
1903
1903
  const providersPath = path11.join(projectRoot, "src", "app", "providers.tsx");
1904
- if (!await fs10.pathExists(providersPath)) return;
1904
+ if (!await fs11.pathExists(providersPath)) return;
1905
1905
  await ctx.trackModifiedFile(providersPath);
1906
- let content = await fs10.readFile(providersPath, "utf-8");
1906
+ let content = await fs11.readFile(providersPath, "utf-8");
1907
1907
  if (content.includes("AnalyticsProvider")) return;
1908
1908
  content = insertImportAfterDirectives(
1909
1909
  content,
@@ -1918,8 +1918,8 @@ async function wireProviders2(projectRoot, ctx) {
1918
1918
  );`;
1919
1919
  }
1920
1920
  );
1921
- await fs10.writeFile(providersPath, content);
1922
- const written = await fs10.readFile(providersPath, "utf-8");
1921
+ await fs11.writeFile(providersPath, content);
1922
+ const written = await fs11.readFile(providersPath, "utf-8");
1923
1923
  if (!written.includes("AnalyticsProvider")) {
1924
1924
  throw new Error(
1925
1925
  "wireProviders: AnalyticsProvider was not inserted into providers.tsx \u2014 the return statement pattern did not match. Review the template file structure."
@@ -1928,11 +1928,11 @@ async function wireProviders2(projectRoot, ctx) {
1928
1928
  }
1929
1929
  async function setConfigFlag4(projectRoot, ctx) {
1930
1930
  const configPath = path11.join(projectRoot, "src", "config", "app.config.ts");
1931
- if (!await fs10.pathExists(configPath)) return;
1931
+ if (!await fs11.pathExists(configPath)) return;
1932
1932
  await ctx.trackModifiedFile(configPath);
1933
- const content = await fs10.readFile(configPath, "utf-8");
1933
+ const content = await fs11.readFile(configPath, "utf-8");
1934
1934
  const updated = content.replace(/analytics:\s*false/, "analytics: true");
1935
- await fs10.writeFile(configPath, updated);
1935
+ await fs11.writeFile(configPath, updated);
1936
1936
  }
1937
1937
  function types3() {
1938
1938
  return `${STAMP4}
@@ -2291,11 +2291,11 @@ var command_palette_exports = {};
2291
2291
  __export(command_palette_exports, {
2292
2292
  generateCommandPalette: () => generateCommandPalette
2293
2293
  });
2294
- import fs11 from "fs-extra";
2294
+ import fs12 from "fs-extra";
2295
2295
  import path12 from "path";
2296
2296
  async function generateCommandPalette(projectRoot) {
2297
2297
  const featureDir = path12.join(projectRoot, "src", "features", "command-palette");
2298
- if (await fs11.pathExists(featureDir)) {
2298
+ if (await fs12.pathExists(featureDir)) {
2299
2299
  log.error("Command palette feature already exists at src/features/command-palette/");
2300
2300
  return;
2301
2301
  }
@@ -2315,8 +2315,8 @@ async function generateCommandPalette(projectRoot) {
2315
2315
  for (const [filePath, content] of Object.entries(files)) {
2316
2316
  const fullPath = path12.join(projectRoot, filePath);
2317
2317
  ctx.trackCreatedFile(fullPath);
2318
- await fs11.ensureDir(path12.dirname(fullPath));
2319
- await fs11.writeFile(fullPath, content);
2318
+ await fs12.ensureDir(path12.dirname(fullPath));
2319
+ await fs12.writeFile(fullPath, content);
2320
2320
  count++;
2321
2321
  }
2322
2322
  await addDependencies(projectRoot, { cmdk: "^1.0.0" });
@@ -2340,8 +2340,8 @@ async function generateCommandPalette(projectRoot) {
2340
2340
  }
2341
2341
  async function wireLayout2(projectRoot, ctx) {
2342
2342
  const layoutPath = path12.join(projectRoot, "src", "app", "layout.tsx");
2343
- if (!await fs11.pathExists(layoutPath)) return;
2344
- let content = await fs11.readFile(layoutPath, "utf-8");
2343
+ if (!await fs12.pathExists(layoutPath)) return;
2344
+ let content = await fs12.readFile(layoutPath, "utf-8");
2345
2345
  if (content.includes("CommandPalette")) return;
2346
2346
  await ctx.trackModifiedFile(layoutPath);
2347
2347
  content = `import { CommandPalette } from '@/features/command-palette';
@@ -2350,15 +2350,15 @@ ${content}`;
2350
2350
  /(\s*)(<Providers>[\s\S]*?<\/Providers>)/,
2351
2351
  "$1$2\n$1<CommandPalette />"
2352
2352
  );
2353
- await fs11.writeFile(layoutPath, content);
2353
+ await fs12.writeFile(layoutPath, content);
2354
2354
  }
2355
2355
  async function setConfigFlag5(projectRoot, ctx) {
2356
2356
  const configPath = path12.join(projectRoot, "src", "config", "app.config.ts");
2357
- if (!await fs11.pathExists(configPath)) return;
2357
+ if (!await fs12.pathExists(configPath)) return;
2358
2358
  await ctx.trackModifiedFile(configPath);
2359
- const content = await fs11.readFile(configPath, "utf-8");
2359
+ const content = await fs12.readFile(configPath, "utf-8");
2360
2360
  const updated = content.replace(/commandPalette:\s*false/, "commandPalette: true");
2361
- await fs11.writeFile(configPath, updated);
2361
+ await fs12.writeFile(configPath, updated);
2362
2362
  }
2363
2363
  function types4() {
2364
2364
  return `${STAMP5}
@@ -2774,11 +2774,11 @@ var onboarding_exports = {};
2774
2774
  __export(onboarding_exports, {
2775
2775
  generateOnboarding: () => generateOnboarding
2776
2776
  });
2777
- import fs12 from "fs-extra";
2777
+ import fs13 from "fs-extra";
2778
2778
  import path13 from "path";
2779
2779
  async function generateOnboarding(projectRoot) {
2780
2780
  const featureDir = path13.join(projectRoot, "src", "features", "onboarding");
2781
- if (await fs12.pathExists(featureDir)) {
2781
+ if (await fs13.pathExists(featureDir)) {
2782
2782
  log.error("Onboarding feature already exists at src/features/onboarding/");
2783
2783
  return;
2784
2784
  }
@@ -2802,8 +2802,8 @@ async function generateOnboarding(projectRoot) {
2802
2802
  for (const [filePath, content] of Object.entries(files)) {
2803
2803
  const fullPath = path13.join(projectRoot, filePath);
2804
2804
  ctx.trackCreatedFile(fullPath);
2805
- await fs12.ensureDir(path13.dirname(fullPath));
2806
- await fs12.writeFile(fullPath, content);
2805
+ await fs13.ensureDir(path13.dirname(fullPath));
2806
+ await fs13.writeFile(fullPath, content);
2807
2807
  count++;
2808
2808
  }
2809
2809
  await addUserRelation(projectRoot, "onboardingProgress OnboardingProgress?", ctx);
@@ -2829,11 +2829,11 @@ async function generateOnboarding(projectRoot) {
2829
2829
  }
2830
2830
  async function setConfigFlag6(projectRoot, ctx) {
2831
2831
  const configPath = path13.join(projectRoot, "src", "config", "app.config.ts");
2832
- if (!await fs12.pathExists(configPath)) return;
2832
+ if (!await fs13.pathExists(configPath)) return;
2833
2833
  await ctx.trackModifiedFile(configPath);
2834
- const content = await fs12.readFile(configPath, "utf-8");
2834
+ const content = await fs13.readFile(configPath, "utf-8");
2835
2835
  const updated = content.replace(/onboarding:\s*false/, "onboarding: true");
2836
- await fs12.writeFile(configPath, updated);
2836
+ await fs13.writeFile(configPath, updated);
2837
2837
  }
2838
2838
  function prismaSchema2() {
2839
2839
  return `// Generated by mars generate onboarding (onboarding@${GENERATOR_VERSION6})
@@ -3360,11 +3360,11 @@ var search_exports = {};
3360
3360
  __export(search_exports, {
3361
3361
  generateSearch: () => generateSearch
3362
3362
  });
3363
- import fs13 from "fs-extra";
3363
+ import fs14 from "fs-extra";
3364
3364
  import path14 from "path";
3365
3365
  async function generateSearch(projectRoot) {
3366
3366
  const featureDir = path14.join(projectRoot, "src", "features", "search");
3367
- if (await fs13.pathExists(featureDir)) {
3367
+ if (await fs14.pathExists(featureDir)) {
3368
3368
  log.error("Search feature already exists at src/features/search/");
3369
3369
  return;
3370
3370
  }
@@ -3386,8 +3386,8 @@ async function generateSearch(projectRoot) {
3386
3386
  for (const [filePath, content] of Object.entries(files)) {
3387
3387
  const fullPath = path14.join(projectRoot, filePath);
3388
3388
  ctx.trackCreatedFile(fullPath);
3389
- await fs13.ensureDir(path14.dirname(fullPath));
3390
- await fs13.writeFile(fullPath, content);
3389
+ await fs14.ensureDir(path14.dirname(fullPath));
3390
+ await fs14.writeFile(fullPath, content);
3391
3391
  count++;
3392
3392
  }
3393
3393
  await wireProtectedNav3(projectRoot, ctx);
@@ -3416,8 +3416,8 @@ async function generateSearch(projectRoot) {
3416
3416
  }
3417
3417
  async function wireProtectedNav3(projectRoot, ctx) {
3418
3418
  const navPath = path14.join(projectRoot, "src", "app", "(protected)", "layout.tsx");
3419
- if (!await fs13.pathExists(navPath)) return;
3420
- let content = await fs13.readFile(navPath, "utf-8");
3419
+ if (!await fs14.pathExists(navPath)) return;
3420
+ let content = await fs14.readFile(navPath, "utf-8");
3421
3421
  if (content.includes("NavSearch")) return;
3422
3422
  await ctx.trackModifiedFile(navPath);
3423
3423
  content = insertImportAfterDirectives(
@@ -3429,15 +3429,15 @@ async function wireProtectedNav3(projectRoot, ctx) {
3429
3429
  /(<div className="flex items-center gap-3">)\s*\n(\s*)(<)/,
3430
3430
  "$1\n$2<NavSearch />\n$2$3"
3431
3431
  );
3432
- await fs13.writeFile(navPath, content);
3432
+ await fs14.writeFile(navPath, content);
3433
3433
  }
3434
3434
  async function setConfigFlag7(projectRoot, ctx) {
3435
3435
  const configPath = path14.join(projectRoot, "src", "config", "app.config.ts");
3436
- if (!await fs13.pathExists(configPath)) return;
3436
+ if (!await fs14.pathExists(configPath)) return;
3437
3437
  await ctx.trackModifiedFile(configPath);
3438
- const content = await fs13.readFile(configPath, "utf-8");
3438
+ const content = await fs14.readFile(configPath, "utf-8");
3439
3439
  const updated = content.replace(/search:\s*false/, "search: true");
3440
- await fs13.writeFile(configPath, updated);
3440
+ await fs14.writeFile(configPath, updated);
3441
3441
  }
3442
3442
  function types6() {
3443
3443
  return `${STAMP7}
@@ -3791,11 +3791,11 @@ var realtime_exports = {};
3791
3791
  __export(realtime_exports, {
3792
3792
  generateRealtime: () => generateRealtime
3793
3793
  });
3794
- import fs14 from "fs-extra";
3794
+ import fs15 from "fs-extra";
3795
3795
  import path15 from "path";
3796
3796
  async function generateRealtime(projectRoot) {
3797
3797
  const featureDir = path15.join(projectRoot, "src", "features", "realtime");
3798
- if (await fs14.pathExists(featureDir)) {
3798
+ if (await fs15.pathExists(featureDir)) {
3799
3799
  log.error("Realtime feature already exists at src/features/realtime/");
3800
3800
  return;
3801
3801
  }
@@ -3814,8 +3814,8 @@ async function generateRealtime(projectRoot) {
3814
3814
  for (const [filePath, content] of Object.entries(files)) {
3815
3815
  const fullPath = path15.join(projectRoot, filePath);
3816
3816
  ctx.trackCreatedFile(fullPath);
3817
- await fs14.ensureDir(path15.dirname(fullPath));
3818
- await fs14.writeFile(fullPath, content);
3817
+ await fs15.ensureDir(path15.dirname(fullPath));
3818
+ await fs15.writeFile(fullPath, content);
3819
3819
  count++;
3820
3820
  }
3821
3821
  await setConfigFlag8(projectRoot, ctx);
@@ -3841,11 +3841,11 @@ async function generateRealtime(projectRoot) {
3841
3841
  }
3842
3842
  async function setConfigFlag8(projectRoot, ctx) {
3843
3843
  const configPath = path15.join(projectRoot, "src", "config", "app.config.ts");
3844
- if (!await fs14.pathExists(configPath)) return;
3844
+ if (!await fs15.pathExists(configPath)) return;
3845
3845
  await ctx.trackModifiedFile(configPath);
3846
- const content = await fs14.readFile(configPath, "utf-8");
3846
+ const content = await fs15.readFile(configPath, "utf-8");
3847
3847
  const updated = content.replace(/realtime:\s*false/, "realtime: true");
3848
- await fs14.writeFile(configPath, updated);
3848
+ await fs15.writeFile(configPath, updated);
3849
3849
  }
3850
3850
  function types7() {
3851
3851
  return `${STAMP8}
@@ -4154,11 +4154,11 @@ var ai_exports = {};
4154
4154
  __export(ai_exports, {
4155
4155
  generateAI: () => generateAI
4156
4156
  });
4157
- import fs15 from "fs-extra";
4157
+ import fs16 from "fs-extra";
4158
4158
  import path16 from "path";
4159
4159
  async function generateAI(projectRoot) {
4160
4160
  const featureDir = path16.join(projectRoot, "src", "features", "ai");
4161
- if (await fs15.pathExists(featureDir)) {
4161
+ if (await fs16.pathExists(featureDir)) {
4162
4162
  log.error("AI feature already exists at src/features/ai/");
4163
4163
  return;
4164
4164
  }
@@ -4178,8 +4178,8 @@ async function generateAI(projectRoot) {
4178
4178
  for (const [filePath, content] of Object.entries(files)) {
4179
4179
  const fullPath = path16.join(projectRoot, filePath);
4180
4180
  ctx.trackCreatedFile(fullPath);
4181
- await fs15.ensureDir(path16.dirname(fullPath));
4182
- await fs15.writeFile(fullPath, content);
4181
+ await fs16.ensureDir(path16.dirname(fullPath));
4182
+ await fs16.writeFile(fullPath, content);
4183
4183
  count++;
4184
4184
  }
4185
4185
  await addDependencies(projectRoot, {
@@ -4206,11 +4206,11 @@ async function generateAI(projectRoot) {
4206
4206
  }
4207
4207
  async function setConfigFlag9(projectRoot, ctx) {
4208
4208
  const configPath = path16.join(projectRoot, "src", "config", "app.config.ts");
4209
- if (!await fs15.pathExists(configPath)) return;
4209
+ if (!await fs16.pathExists(configPath)) return;
4210
4210
  await ctx.trackModifiedFile(configPath);
4211
- const content = await fs15.readFile(configPath, "utf-8");
4211
+ const content = await fs16.readFile(configPath, "utf-8");
4212
4212
  const updated = content.replace(/ai:\s*false/, "ai: true");
4213
- await fs15.writeFile(configPath, updated);
4213
+ await fs16.writeFile(configPath, updated);
4214
4214
  }
4215
4215
  function types8() {
4216
4216
  return `${STAMP9}
@@ -4649,11 +4649,11 @@ var cookie_consent_exports = {};
4649
4649
  __export(cookie_consent_exports, {
4650
4650
  generateCookieConsent: () => generateCookieConsent
4651
4651
  });
4652
- import fs16 from "fs-extra";
4652
+ import fs17 from "fs-extra";
4653
4653
  import path17 from "path";
4654
4654
  async function generateCookieConsent(projectRoot) {
4655
4655
  const featureDir = path17.join(projectRoot, "src", "features", "cookie-consent");
4656
- if (await fs16.pathExists(featureDir)) {
4656
+ if (await fs17.pathExists(featureDir)) {
4657
4657
  log.error("Cookie consent feature already exists at src/features/cookie-consent/");
4658
4658
  return;
4659
4659
  }
@@ -4671,8 +4671,8 @@ async function generateCookieConsent(projectRoot) {
4671
4671
  for (const [filePath, content] of Object.entries(files)) {
4672
4672
  const fullPath = path17.join(projectRoot, filePath);
4673
4673
  ctx.trackCreatedFile(fullPath);
4674
- await fs16.ensureDir(path17.dirname(fullPath));
4675
- await fs16.writeFile(fullPath, content);
4674
+ await fs17.ensureDir(path17.dirname(fullPath));
4675
+ await fs17.writeFile(fullPath, content);
4676
4676
  count++;
4677
4677
  }
4678
4678
  await wireLayout3(projectRoot, ctx);
@@ -4698,8 +4698,8 @@ async function generateCookieConsent(projectRoot) {
4698
4698
  }
4699
4699
  async function wireLayout3(projectRoot, ctx) {
4700
4700
  const layoutPath = path17.join(projectRoot, "src", "app", "layout.tsx");
4701
- if (!await fs16.pathExists(layoutPath)) return;
4702
- let content = await fs16.readFile(layoutPath, "utf-8");
4701
+ if (!await fs17.pathExists(layoutPath)) return;
4702
+ let content = await fs17.readFile(layoutPath, "utf-8");
4703
4703
  if (content.includes("CookieConsentBanner")) return;
4704
4704
  await ctx.trackModifiedFile(layoutPath);
4705
4705
  content = `import { CookieConsentBanner } from '@/features/cookie-consent';
@@ -4708,15 +4708,15 @@ ${content}`;
4708
4708
  /(\s*)(<Providers>[\s\S]*?<\/Providers>)/,
4709
4709
  "$1$2\n$1<CookieConsentBanner />"
4710
4710
  );
4711
- await fs16.writeFile(layoutPath, content);
4711
+ await fs17.writeFile(layoutPath, content);
4712
4712
  }
4713
4713
  async function setConfigFlag10(projectRoot, ctx) {
4714
4714
  const configPath = path17.join(projectRoot, "src", "config", "app.config.ts");
4715
- if (!await fs16.pathExists(configPath)) return;
4715
+ if (!await fs17.pathExists(configPath)) return;
4716
4716
  await ctx.trackModifiedFile(configPath);
4717
- const content = await fs16.readFile(configPath, "utf-8");
4717
+ const content = await fs17.readFile(configPath, "utf-8");
4718
4718
  const updated = content.replace(/cookieConsent:\s*false/, "cookieConsent: true");
4719
- await fs16.writeFile(configPath, updated);
4719
+ await fs17.writeFile(configPath, updated);
4720
4720
  }
4721
4721
  function types9() {
4722
4722
  return `${STAMP10}
@@ -5001,11 +5001,11 @@ var coming_soon_exports = {};
5001
5001
  __export(coming_soon_exports, {
5002
5002
  generateComingSoon: () => generateComingSoon
5003
5003
  });
5004
- import fs17 from "fs-extra";
5004
+ import fs18 from "fs-extra";
5005
5005
  import path18 from "path";
5006
5006
  async function generateComingSoon(projectRoot) {
5007
5007
  const featureDir = path18.join(projectRoot, "src", "features", "coming-soon");
5008
- if (await fs17.pathExists(featureDir)) {
5008
+ if (await fs18.pathExists(featureDir)) {
5009
5009
  log.error("Coming soon feature already exists at src/features/coming-soon/");
5010
5010
  return;
5011
5011
  }
@@ -5024,8 +5024,8 @@ async function generateComingSoon(projectRoot) {
5024
5024
  for (const [filePath, content] of Object.entries(files)) {
5025
5025
  const fullPath = path18.join(projectRoot, filePath);
5026
5026
  ctx.trackCreatedFile(fullPath);
5027
- await fs17.ensureDir(path18.dirname(fullPath));
5028
- await fs17.writeFile(fullPath, content);
5027
+ await fs18.ensureDir(path18.dirname(fullPath));
5028
+ await fs18.writeFile(fullPath, content);
5029
5029
  count++;
5030
5030
  }
5031
5031
  await registerRoute(projectRoot, "comingSoon", "/coming-soon", ctx);
@@ -5048,11 +5048,11 @@ async function generateComingSoon(projectRoot) {
5048
5048
  }
5049
5049
  async function setConfigFlag11(projectRoot, ctx) {
5050
5050
  const configPath = path18.join(projectRoot, "src", "config", "app.config.ts");
5051
- if (!await fs17.pathExists(configPath)) return;
5051
+ if (!await fs18.pathExists(configPath)) return;
5052
5052
  await ctx.trackModifiedFile(configPath);
5053
- const content = await fs17.readFile(configPath, "utf-8");
5053
+ const content = await fs18.readFile(configPath, "utf-8");
5054
5054
  const updated = content.replace(/comingSoon:\s*false/, "comingSoon: true");
5055
- await fs17.writeFile(configPath, updated);
5055
+ await fs18.writeFile(configPath, updated);
5056
5056
  }
5057
5057
  function types10() {
5058
5058
  return `${STAMP11}
@@ -5240,11 +5240,11 @@ var sentry_exports = {};
5240
5240
  __export(sentry_exports, {
5241
5241
  generateSentry: () => generateSentry
5242
5242
  });
5243
- import fs18 from "fs-extra";
5243
+ import fs19 from "fs-extra";
5244
5244
  import path19 from "path";
5245
5245
  async function generateSentry(projectRoot) {
5246
5246
  const featureDir = path19.join(projectRoot, "src", "features", "sentry");
5247
- if (await fs18.pathExists(featureDir)) {
5247
+ if (await fs19.pathExists(featureDir)) {
5248
5248
  log.error("Sentry feature already exists at src/features/sentry/");
5249
5249
  return;
5250
5250
  }
@@ -5262,8 +5262,8 @@ async function generateSentry(projectRoot) {
5262
5262
  for (const [filePath, content] of Object.entries(files)) {
5263
5263
  const fullPath = path19.join(projectRoot, filePath);
5264
5264
  ctx.trackCreatedFile(fullPath);
5265
- await fs18.ensureDir(path19.dirname(fullPath));
5266
- await fs18.writeFile(fullPath, content);
5265
+ await fs19.ensureDir(path19.dirname(fullPath));
5266
+ await fs19.writeFile(fullPath, content);
5267
5267
  count++;
5268
5268
  }
5269
5269
  await addDependencies(projectRoot, { "@sentry/nextjs": "^8.0.0" });
@@ -5290,8 +5290,8 @@ async function generateSentry(projectRoot) {
5290
5290
  }
5291
5291
  async function wireRootLayout(projectRoot, ctx) {
5292
5292
  const layoutPath = path19.join(projectRoot, "src", "app", "layout.tsx");
5293
- if (!await fs18.pathExists(layoutPath)) return;
5294
- let content = await fs18.readFile(layoutPath, "utf-8");
5293
+ if (!await fs19.pathExists(layoutPath)) return;
5294
+ let content = await fs19.readFile(layoutPath, "utf-8");
5295
5295
  if (content.includes("ErrorBoundary")) return;
5296
5296
  await ctx.trackModifiedFile(layoutPath);
5297
5297
  content = `import { ErrorBoundary } from '@/features/sentry';
@@ -5300,15 +5300,15 @@ ${content}`;
5300
5300
  /(<Providers>)\{children\}(<\/Providers>)/,
5301
5301
  "$1<ErrorBoundary>{children}</ErrorBoundary>$2"
5302
5302
  );
5303
- await fs18.writeFile(layoutPath, content);
5303
+ await fs19.writeFile(layoutPath, content);
5304
5304
  }
5305
5305
  async function setConfigFlag12(projectRoot, ctx) {
5306
5306
  const configPath = path19.join(projectRoot, "src", "config", "app.config.ts");
5307
- if (!await fs18.pathExists(configPath)) return;
5307
+ if (!await fs19.pathExists(configPath)) return;
5308
5308
  await ctx.trackModifiedFile(configPath);
5309
- const content = await fs18.readFile(configPath, "utf-8");
5309
+ const content = await fs19.readFile(configPath, "utf-8");
5310
5310
  const updated = content.replace(/sentry:\s*false/, "sentry: true");
5311
- await fs18.writeFile(configPath, updated);
5311
+ await fs19.writeFile(configPath, updated);
5312
5312
  }
5313
5313
  function types11() {
5314
5314
  return `${STAMP12}
@@ -5453,11 +5453,11 @@ var feature_flags_exports = {};
5453
5453
  __export(feature_flags_exports, {
5454
5454
  generateFeatureFlags: () => generateFeatureFlags
5455
5455
  });
5456
- import fs19 from "fs-extra";
5456
+ import fs20 from "fs-extra";
5457
5457
  import path20 from "path";
5458
5458
  async function generateFeatureFlags(projectRoot) {
5459
5459
  const featureDir = path20.join(projectRoot, "src", "features", "feature-flags");
5460
- if (await fs19.pathExists(featureDir)) {
5460
+ if (await fs20.pathExists(featureDir)) {
5461
5461
  log.error("Feature flags feature already exists at src/features/feature-flags/");
5462
5462
  return;
5463
5463
  }
@@ -5478,8 +5478,8 @@ async function generateFeatureFlags(projectRoot) {
5478
5478
  for (const [filePath, content] of Object.entries(files)) {
5479
5479
  const fullPath = path20.join(projectRoot, filePath);
5480
5480
  ctx.trackCreatedFile(fullPath);
5481
- await fs19.ensureDir(path20.dirname(fullPath));
5482
- await fs19.writeFile(fullPath, content);
5481
+ await fs20.ensureDir(path20.dirname(fullPath));
5482
+ await fs20.writeFile(fullPath, content);
5483
5483
  count++;
5484
5484
  }
5485
5485
  await setConfigFlag13(projectRoot, ctx);
@@ -5500,11 +5500,11 @@ async function generateFeatureFlags(projectRoot) {
5500
5500
  }
5501
5501
  async function setConfigFlag13(projectRoot, ctx) {
5502
5502
  const configPath = path20.join(projectRoot, "src", "config", "app.config.ts");
5503
- if (!await fs19.pathExists(configPath)) return;
5503
+ if (!await fs20.pathExists(configPath)) return;
5504
5504
  await ctx.trackModifiedFile(configPath);
5505
- const content = await fs19.readFile(configPath, "utf-8");
5505
+ const content = await fs20.readFile(configPath, "utf-8");
5506
5506
  const updated = content.replace(/featureFlags:\s*false/, "featureFlags: true");
5507
- await fs19.writeFile(configPath, updated);
5507
+ await fs20.writeFile(configPath, updated);
5508
5508
  }
5509
5509
  function types12() {
5510
5510
  return `${STAMP13}
@@ -5746,6 +5746,7 @@ import { Command } from "commander";
5746
5746
  import { createRequire } from "module";
5747
5747
  import path from "path";
5748
5748
  import { fileURLToPath } from "url";
5749
+ import fs from "fs-extra";
5749
5750
  var __dirname = path.dirname(fileURLToPath(import.meta.url));
5750
5751
  function readVersionFromPackageJson(packageDir) {
5751
5752
  const require2 = createRequire(import.meta.url);
@@ -5754,13 +5755,23 @@ function readVersionFromPackageJson(packageDir) {
5754
5755
  return v ? v : "0.0.0";
5755
5756
  }
5756
5757
  function getCliVersion() {
5757
- const packageRoot = path.resolve(__dirname, "..", "..");
5758
- return readVersionFromPackageJson(packageRoot);
5758
+ const candidates = [
5759
+ // Built bundle: __dirname = packages/cli/dist/
5760
+ path.resolve(__dirname, ".."),
5761
+ // Source (vitest): __dirname = packages/cli/src/utils/
5762
+ path.resolve(__dirname, "..", "..")
5763
+ ];
5764
+ for (const candidate of candidates) {
5765
+ if (fs.existsSync(path.join(candidate, "package.json"))) {
5766
+ return readVersionFromPackageJson(candidate);
5767
+ }
5768
+ }
5769
+ return "0.0.0";
5759
5770
  }
5760
5771
 
5761
5772
  // src/commands/create.ts
5762
5773
  init_logger();
5763
- import fs21 from "fs-extra";
5774
+ import fs22 from "fs-extra";
5764
5775
  import path22 from "path";
5765
5776
  import os3 from "os";
5766
5777
  import ora from "ora";
@@ -5770,7 +5781,7 @@ import prompts5 from "prompts";
5770
5781
  // src/utils/template.ts
5771
5782
  import path2 from "path";
5772
5783
  import { fileURLToPath as fileURLToPath2 } from "url";
5773
- import fs from "fs-extra";
5784
+ import fs2 from "fs-extra";
5774
5785
  var __dirname2 = path2.dirname(fileURLToPath2(import.meta.url));
5775
5786
  function getTemplatePath() {
5776
5787
  const candidates = [
@@ -5781,7 +5792,7 @@ function getTemplatePath() {
5781
5792
  path2.resolve(__dirname2, "..", "..", "..", "..", "template")
5782
5793
  ];
5783
5794
  for (const candidate of candidates) {
5784
- if (fs.existsSync(candidate)) {
5795
+ if (fs2.existsSync(candidate)) {
5785
5796
  return candidate;
5786
5797
  }
5787
5798
  }
@@ -6187,7 +6198,7 @@ async function promptTheme() {
6187
6198
 
6188
6199
  // src/generators/scaffold.ts
6189
6200
  init_logger();
6190
- import fs2 from "fs-extra";
6201
+ import fs3 from "fs-extra";
6191
6202
  import path3 from "path";
6192
6203
  import { generateBrandCss } from "@mars-stack/ui/utils";
6193
6204
 
@@ -6372,17 +6383,17 @@ var IGNORED_FILES = [
6372
6383
  async function copyTemplateFiles(templateDir, targetDir) {
6373
6384
  let fileCount = 0;
6374
6385
  async function walkAndCopy(src, dest) {
6375
- const entries = await fs2.readdir(src, { withFileTypes: true });
6386
+ const entries = await fs3.readdir(src, { withFileTypes: true });
6376
6387
  for (const entry of entries) {
6377
6388
  const srcPath = path3.join(src, entry.name);
6378
6389
  const destPath = path3.join(dest, entry.name);
6379
6390
  if (entry.isDirectory()) {
6380
6391
  if (IGNORED_DIRS.includes(entry.name)) continue;
6381
- await fs2.ensureDir(destPath);
6392
+ await fs3.ensureDir(destPath);
6382
6393
  await walkAndCopy(srcPath, destPath);
6383
6394
  } else {
6384
6395
  if (IGNORED_FILES.includes(entry.name)) continue;
6385
- await fs2.copy(srcPath, destPath);
6396
+ await fs3.copy(srcPath, destPath);
6386
6397
  fileCount++;
6387
6398
  }
6388
6399
  }
@@ -6397,15 +6408,15 @@ function resolveMarsPackageRange(packageName, templateDir) {
6397
6408
  path3.resolve(templateDir, "..", "..", "packages", shortName, "package.json")
6398
6409
  ];
6399
6410
  for (const candidate of candidates) {
6400
- if (fs2.existsSync(candidate)) {
6401
- const pkg = fs2.readJsonSync(candidate);
6411
+ if (fs3.existsSync(candidate)) {
6412
+ const pkg = fs3.readJsonSync(candidate);
6402
6413
  if (typeof pkg.version === "string") {
6403
6414
  const [major, minor] = pkg.version.split(".");
6404
6415
  return `^${major}.${minor}.0`;
6405
6416
  }
6406
6417
  }
6407
6418
  }
6408
- const templatePkg = fs2.readJsonSync(path3.join(templateDir, "package.json"));
6419
+ const templatePkg = fs3.readJsonSync(path3.join(templateDir, "package.json"));
6409
6420
  const existing = templatePkg.dependencies?.[packageName];
6410
6421
  if (existing && existing !== "*") {
6411
6422
  if (/^[\^~>=]/.test(existing)) return existing;
@@ -6417,7 +6428,7 @@ function resolveMarsPackageRange(packageName, templateDir) {
6417
6428
  function generatePackageJson(config) {
6418
6429
  const templateDir = getTemplatePath();
6419
6430
  const templatePkg = path3.join(templateDir, "package.json");
6420
- const pkg = fs2.readJsonSync(templatePkg);
6431
+ const pkg = fs3.readJsonSync(templatePkg);
6421
6432
  pkg.name = config.name;
6422
6433
  pkg.version = "0.1.0";
6423
6434
  pkg.private = true;
@@ -6617,8 +6628,8 @@ async function pruneDisabledFeatures(features, targetDir) {
6617
6628
  if (flagValue !== false) continue;
6618
6629
  for (const relativePath of paths) {
6619
6630
  const fullPath = path3.join(targetDir, relativePath);
6620
- if (await fs2.pathExists(fullPath)) {
6621
- await fs2.remove(fullPath);
6631
+ if (await fs3.pathExists(fullPath)) {
6632
+ await fs3.remove(fullPath);
6622
6633
  log.step(`Pruned disabled feature path: ${relativePath}`);
6623
6634
  }
6624
6635
  }
@@ -6628,42 +6639,42 @@ async function pruneDisabledFeatures(features, targetDir) {
6628
6639
  }
6629
6640
  if (relationsToRemove.length > 0) {
6630
6641
  const authPath = path3.join(targetDir, "prisma", "schema", "auth.prisma");
6631
- if (await fs2.pathExists(authPath)) {
6632
- let content = await fs2.readFile(authPath, "utf-8");
6642
+ if (await fs3.pathExists(authPath)) {
6643
+ let content = await fs3.readFile(authPath, "utf-8");
6633
6644
  for (const field of relationsToRemove) {
6634
6645
  content = content.replace(new RegExp(`\\s*${field}\\s+\\S+.*\\n`, "g"), "\n");
6635
6646
  }
6636
- await fs2.writeFile(authPath, content);
6647
+ await fs3.writeFile(authPath, content);
6637
6648
  }
6638
6649
  }
6639
6650
  }
6640
6651
  async function scaffoldProject(targetDir, config) {
6641
6652
  const templateDir = getTemplatePath();
6642
- if (!await fs2.pathExists(templateDir)) {
6653
+ if (!await fs3.pathExists(templateDir)) {
6643
6654
  throw new Error(`Template directory not found: ${templateDir}`);
6644
6655
  }
6645
- await fs2.ensureDir(targetDir);
6656
+ await fs3.ensureDir(targetDir);
6646
6657
  const fileCount = await copyTemplateFiles(templateDir, targetDir);
6647
6658
  await pruneDisabledFeatures(config.features, targetDir);
6648
- await fs2.writeFile(path3.join(targetDir, "package.json"), generatePackageJson(config));
6649
- await fs2.writeFile(
6659
+ await fs3.writeFile(path3.join(targetDir, "package.json"), generatePackageJson(config));
6660
+ await fs3.writeFile(
6650
6661
  path3.join(targetDir, "src", "config", "app.config.ts"),
6651
6662
  generateAppConfig(config)
6652
6663
  );
6653
- await fs2.writeFile(path3.join(targetDir, "docker-compose.yml"), generateDockerCompose(config));
6654
- await fs2.writeFile(path3.join(targetDir, "src", "app", "layout.tsx"), generateLayout(config));
6655
- await fs2.writeFile(path3.join(targetDir, ".env"), generateEnvFile(config));
6656
- await fs2.writeFile(path3.join(targetDir, ".env.example"), generateEnvExample(config));
6657
- await fs2.writeFile(path3.join(targetDir, ".gitignore"), generateGitignore());
6664
+ await fs3.writeFile(path3.join(targetDir, "docker-compose.yml"), generateDockerCompose(config));
6665
+ await fs3.writeFile(path3.join(targetDir, "src", "app", "layout.tsx"), generateLayout(config));
6666
+ await fs3.writeFile(path3.join(targetDir, ".env"), generateEnvFile(config));
6667
+ await fs3.writeFile(path3.join(targetDir, ".env.example"), generateEnvExample(config));
6668
+ await fs3.writeFile(path3.join(targetDir, ".gitignore"), generateGitignore());
6658
6669
  await patchGlobalsCssForScaffoldedProject(targetDir, config);
6659
6670
  await generateBrandCssForProject(targetDir, config);
6660
6671
  return { fileCount };
6661
6672
  }
6662
6673
  async function generateBrandCssForProject(targetDir, config) {
6663
6674
  const brandPath = path3.join(targetDir, "src", "styles", "brand.css");
6664
- if (!await fs2.pathExists(brandPath)) return;
6675
+ if (!await fs3.pathExists(brandPath)) return;
6665
6676
  const css = generateBrandCss(config.theme.primaryColor);
6666
- await fs2.writeFile(brandPath, css);
6677
+ await fs3.writeFile(brandPath, css);
6667
6678
  }
6668
6679
  var VALID_DESIGN_DIRECTIONS = [
6669
6680
  "modern-saas",
@@ -6674,8 +6685,8 @@ var VALID_DESIGN_DIRECTIONS = [
6674
6685
  ];
6675
6686
  async function patchGlobalsCssForScaffoldedProject(targetDir, config) {
6676
6687
  const globalsPath = path3.join(targetDir, "src", "styles", "globals.css");
6677
- if (!await fs2.pathExists(globalsPath)) return;
6678
- let content = await fs2.readFile(globalsPath, "utf-8");
6688
+ if (!await fs3.pathExists(globalsPath)) return;
6689
+ let content = await fs3.readFile(globalsPath, "utf-8");
6679
6690
  content = content.replace(
6680
6691
  '@source "../../../node_modules/@mars-stack/ui/dist/**/*.js";',
6681
6692
  '@source "../../node_modules/@mars-stack/ui/dist/**/*.js";'
@@ -6694,7 +6705,7 @@ async function patchGlobalsCssForScaffoldedProject(targetDir, config) {
6694
6705
  ${newImport}`
6695
6706
  );
6696
6707
  }
6697
- await fs2.writeFile(globalsPath, content);
6708
+ await fs3.writeFile(globalsPath, content);
6698
6709
  }
6699
6710
 
6700
6711
  // src/generators/generate-selected.ts
@@ -6810,13 +6821,13 @@ async function generateSelectedFeatures(projectRoot, features) {
6810
6821
  }
6811
6822
 
6812
6823
  // src/utils/telemetry.ts
6813
- import fs20 from "fs-extra";
6824
+ import fs21 from "fs-extra";
6814
6825
  import path21 from "path";
6815
6826
  import os2 from "os";
6816
6827
  var RC_PATH = path21.join(os2.homedir(), ".marsrc");
6817
6828
  function isTelemetryEnabled() {
6818
6829
  try {
6819
- const config = fs20.readJsonSync(RC_PATH);
6830
+ const config = fs21.readJsonSync(RC_PATH);
6820
6831
  return config.enabled === true;
6821
6832
  } catch {
6822
6833
  return false;
@@ -6825,16 +6836,16 @@ function isTelemetryEnabled() {
6825
6836
  function enableTelemetry() {
6826
6837
  const config = loadOrCreateConfig();
6827
6838
  config.enabled = true;
6828
- fs20.writeJsonSync(RC_PATH, config, { spaces: 2 });
6839
+ fs21.writeJsonSync(RC_PATH, config, { spaces: 2 });
6829
6840
  }
6830
6841
  function disableTelemetry() {
6831
6842
  const config = loadOrCreateConfig();
6832
6843
  config.enabled = false;
6833
- fs20.writeJsonSync(RC_PATH, config, { spaces: 2 });
6844
+ fs21.writeJsonSync(RC_PATH, config, { spaces: 2 });
6834
6845
  }
6835
6846
  function loadOrCreateConfig() {
6836
6847
  try {
6837
- return fs20.readJsonSync(RC_PATH);
6848
+ return fs21.readJsonSync(RC_PATH);
6838
6849
  } catch {
6839
6850
  return { enabled: false, anonymousId: crypto.randomUUID() };
6840
6851
  }
@@ -6855,7 +6866,7 @@ function trackEvent(event, properties) {
6855
6866
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
6856
6867
  };
6857
6868
  const logPath = path21.join(os2.homedir(), ".mars-telemetry.log");
6858
- fs20.appendFile(logPath, JSON.stringify(payload) + "\n").catch(() => {
6869
+ fs21.appendFile(logPath, JSON.stringify(payload) + "\n").catch(() => {
6859
6870
  });
6860
6871
  }
6861
6872
 
@@ -6887,8 +6898,8 @@ async function createCommand(projectName, options) {
6887
6898
  const projectInfo = useDefaults ? getDefaultProjectInfo(projectName) : await promptProjectInfo(projectName);
6888
6899
  if (!projectInfo) return;
6889
6900
  const targetDir = resolveProjectPath(projectInfo.name);
6890
- if (await fs21.pathExists(targetDir)) {
6891
- const entries = await fs21.readdir(targetDir);
6901
+ if (await fs22.pathExists(targetDir)) {
6902
+ const entries = await fs22.readdir(targetDir);
6892
6903
  if (entries.length > 0) {
6893
6904
  log.error(`Directory "${projectInfo.name}" already exists and is not empty.`);
6894
6905
  return;
@@ -6929,7 +6940,7 @@ async function createCommand(projectName, options) {
6929
6940
  log.info("Scaffolding cancelled.");
6930
6941
  process.exit(0);
6931
6942
  }
6932
- if (!fs21.pathExistsSync(RC_PATH2)) {
6943
+ if (!fs22.pathExistsSync(RC_PATH2)) {
6933
6944
  const { telemetryOptIn } = await prompts5(
6934
6945
  {
6935
6946
  type: "confirm",
@@ -6968,10 +6979,10 @@ async function createCommand(projectName, options) {
6968
6979
  } catch (err) {
6969
6980
  spinner.fail("Failed to scaffold project");
6970
6981
  log.error(err instanceof Error ? err.message : String(err));
6971
- if (await fs21.pathExists(targetDir)) {
6982
+ if (await fs22.pathExists(targetDir)) {
6972
6983
  const cleanupSpinner = ora("Cleaning up...").start();
6973
6984
  try {
6974
- await fs21.remove(targetDir);
6985
+ await fs22.remove(targetDir);
6975
6986
  cleanupSpinner.succeed("Cleaned up partial scaffold");
6976
6987
  } catch {
6977
6988
  cleanupSpinner.warn(`Could not clean up ${targetDir}. You may need to remove it manually.`);
@@ -6986,7 +6997,7 @@ function countEnabled(flags) {
6986
6997
 
6987
6998
  // src/commands/doctor.ts
6988
6999
  init_logger();
6989
- import fs22 from "fs-extra";
7000
+ import fs23 from "fs-extra";
6990
7001
  import path23 from "path";
6991
7002
  import { execSync } from "child_process";
6992
7003
  function commandExists(cmd) {
@@ -7008,11 +7019,11 @@ async function checkForUpgrades() {
7008
7019
  log.blank();
7009
7020
  log.title("Upgrade Check");
7010
7021
  const packageJsonPath = path23.join(process.cwd(), "package.json");
7011
- if (!fs22.pathExistsSync(packageJsonPath)) {
7022
+ if (!fs23.pathExistsSync(packageJsonPath)) {
7012
7023
  log.warn("No package.json found \u2014 skipping upgrade check.");
7013
7024
  return;
7014
7025
  }
7015
- const packageJson = fs22.readJsonSync(packageJsonPath);
7026
+ const packageJson = fs23.readJsonSync(packageJsonPath);
7016
7027
  const deps = packageJson.dependencies ?? {};
7017
7028
  const devDeps = packageJson.devDependencies ?? {};
7018
7029
  const currentRaw = deps["@mars-stack/core"] ?? devDeps["@mars-stack/core"];
@@ -7074,25 +7085,25 @@ async function doctorCommand(options) {
7074
7085
  },
7075
7086
  {
7076
7087
  name: "package.json exists",
7077
- check: () => fs22.pathExistsSync(path23.join(process.cwd(), "package.json"))
7088
+ check: () => fs23.pathExistsSync(path23.join(process.cwd(), "package.json"))
7078
7089
  },
7079
7090
  {
7080
7091
  name: ".env file exists",
7081
- check: () => fs22.pathExistsSync(path23.join(process.cwd(), ".env"))
7092
+ check: () => fs23.pathExistsSync(path23.join(process.cwd(), ".env"))
7082
7093
  },
7083
7094
  {
7084
7095
  name: "Prisma schema exists",
7085
- check: () => fs22.pathExistsSync(path23.join(process.cwd(), "prisma", "schema")) || fs22.pathExistsSync(path23.join(process.cwd(), "prisma", "schema.prisma"))
7096
+ check: () => fs23.pathExistsSync(path23.join(process.cwd(), "prisma", "schema")) || fs23.pathExistsSync(path23.join(process.cwd(), "prisma", "schema.prisma"))
7086
7097
  },
7087
7098
  {
7088
7099
  name: "node_modules installed",
7089
- check: () => fs22.pathExistsSync(path23.join(process.cwd(), "node_modules"))
7100
+ check: () => fs23.pathExistsSync(path23.join(process.cwd(), "node_modules"))
7090
7101
  },
7091
7102
  {
7092
7103
  name: "DATABASE_URL set",
7093
7104
  check: () => {
7094
7105
  try {
7095
- const envContent = fs22.readFileSync(path23.join(process.cwd(), ".env"), "utf-8");
7106
+ const envContent = fs23.readFileSync(path23.join(process.cwd(), ".env"), "utf-8");
7096
7107
  const match = envContent.match(/^DATABASE_URL=(.+)$/m);
7097
7108
  return match ? match[1] !== "" : false;
7098
7109
  } catch {
@@ -7104,7 +7115,7 @@ async function doctorCommand(options) {
7104
7115
  name: "JWT_SECRET set",
7105
7116
  check: () => {
7106
7117
  try {
7107
- const envContent = fs22.readFileSync(path23.join(process.cwd(), ".env"), "utf-8");
7118
+ const envContent = fs23.readFileSync(path23.join(process.cwd(), ".env"), "utf-8");
7108
7119
  const match = envContent.match(/^JWT_SECRET=(.+)$/m);
7109
7120
  if (!match || !match[1]) return false;
7110
7121
  return match[1].length >= 32 ? true : "set but too short (need >=32 chars)";
@@ -7149,16 +7160,16 @@ async function doctorCommand(options) {
7149
7160
 
7150
7161
  // src/commands/add.ts
7151
7162
  init_logger();
7152
- import fs24 from "fs-extra";
7163
+ import fs25 from "fs-extra";
7153
7164
  import path25 from "path";
7154
7165
  import pc3 from "picocolors";
7155
7166
 
7156
7167
  // src/utils/doc-updater.ts
7157
- import fs23 from "fs-extra";
7168
+ import fs24 from "fs-extra";
7158
7169
  import path24 from "path";
7159
7170
  async function appendToDbSchema(projectDir, modelName, fields) {
7160
7171
  const filePath = path24.join(projectDir, "docs", "generated", "db-schema.md");
7161
- if (!await fs23.pathExists(filePath)) return;
7172
+ if (!await fs24.pathExists(filePath)) return;
7162
7173
  const entry = [
7163
7174
  "",
7164
7175
  `### ${modelName}`,
@@ -7168,12 +7179,12 @@ async function appendToDbSchema(projectDir, modelName, fields) {
7168
7179
  ...fields.map((f) => `| ${f} | |`),
7169
7180
  ""
7170
7181
  ].join("\n");
7171
- await fs23.appendFile(filePath, entry);
7182
+ await fs24.appendFile(filePath, entry);
7172
7183
  }
7173
7184
  async function updateQualityScore(projectDir, domain, grade) {
7174
7185
  const filePath = path24.join(projectDir, "docs", "QUALITY_SCORE.md");
7175
- if (!await fs23.pathExists(filePath)) return;
7176
- const content = await fs23.readFile(filePath, "utf-8");
7186
+ if (!await fs24.pathExists(filePath)) return;
7187
+ const content = await fs24.readFile(filePath, "utf-8");
7177
7188
  const pattern = new RegExp(`^\\|\\s*${escapeRegex(domain)}\\s*\\|`, "m");
7178
7189
  if (pattern.test(content)) {
7179
7190
  const updated = content.replace(pattern, (match) => {
@@ -7181,11 +7192,11 @@ async function updateQualityScore(projectDir, domain, grade) {
7181
7192
  parts[2] = ` ${grade} `;
7182
7193
  return parts.join("|");
7183
7194
  });
7184
- await fs23.writeFile(filePath, updated);
7195
+ await fs24.writeFile(filePath, updated);
7185
7196
  } else {
7186
7197
  const row = `| ${domain} | ${grade} | |
7187
7198
  `;
7188
- await fs23.appendFile(filePath, row);
7199
+ await fs24.appendFile(filePath, row);
7189
7200
  }
7190
7201
  }
7191
7202
  function escapeRegex(str) {
@@ -7197,7 +7208,7 @@ init_rollback();
7197
7208
  function ensureInProject() {
7198
7209
  const cwd = process.cwd();
7199
7210
  const configPath = path25.join(cwd, "src", "config", "app.config.ts");
7200
- if (!fs24.pathExistsSync(configPath)) {
7211
+ if (!fs25.pathExistsSync(configPath)) {
7201
7212
  log.error("Not inside a MARS project. Run this command from the project root.");
7202
7213
  process.exit(1);
7203
7214
  }
@@ -7231,7 +7242,7 @@ async function addFeatureCommand(name) {
7231
7242
  const pascal = toPascal(name);
7232
7243
  const camel = toCamel(name);
7233
7244
  const featureDir = path25.join(root, "src", "features", kebab);
7234
- if (await fs24.pathExists(featureDir)) {
7245
+ if (await fs25.pathExists(featureDir)) {
7235
7246
  log.error(`Feature "${kebab}" already exists at src/features/${kebab}/`);
7236
7247
  return;
7237
7248
  }
@@ -7297,8 +7308,8 @@ export type Update${pascal}Input = z.infer<typeof ${camel}Schemas.update>;
7297
7308
  let count = 0;
7298
7309
  for (const [filePath, content] of Object.entries(files)) {
7299
7310
  const fullPath = path25.join(featureDir, filePath);
7300
- await fs24.ensureDir(path25.dirname(fullPath));
7301
- await fs24.writeFile(fullPath, content);
7311
+ await fs25.ensureDir(path25.dirname(fullPath));
7312
+ await fs25.writeFile(fullPath, content);
7302
7313
  count++;
7303
7314
  }
7304
7315
  await ctx.commit();
@@ -7320,7 +7331,7 @@ async function addPageCommand(routePath, options) {
7320
7331
  const cleanPath = routePath.startsWith("/") ? routePath.slice(1) : routePath;
7321
7332
  const group = options.protected ? "(protected)" : "(public)";
7322
7333
  const pageDir = path25.join(root, "src", "app", group, cleanPath);
7323
- if (await fs24.pathExists(path25.join(pageDir, "page.tsx"))) {
7334
+ if (await fs25.pathExists(path25.join(pageDir, "page.tsx"))) {
7324
7335
  log.error(`Page already exists at src/app/${group}/${cleanPath}/page.tsx`);
7325
7336
  return;
7326
7337
  }
@@ -7368,9 +7379,9 @@ export default function Loading() {
7368
7379
  const ctx = createRollbackContext();
7369
7380
  try {
7370
7381
  ctx.trackCreatedFile(pageDir);
7371
- await fs24.ensureDir(pageDir);
7372
- await fs24.writeFile(path25.join(pageDir, "page.tsx"), pageContent);
7373
- await fs24.writeFile(path25.join(pageDir, "loading.tsx"), loadingContent);
7382
+ await fs25.ensureDir(pageDir);
7383
+ await fs25.writeFile(path25.join(pageDir, "page.tsx"), pageContent);
7384
+ await fs25.writeFile(path25.join(pageDir, "loading.tsx"), loadingContent);
7374
7385
  await ctx.commit();
7375
7386
  log.success(`Created page at ${pc3.bold(`src/app/${group}/${cleanPath}/`)}`);
7376
7387
  trackEvent("add", { type: "page" });
@@ -7389,7 +7400,7 @@ async function addModelCommand(name) {
7389
7400
  const kebab = toKebab(name);
7390
7401
  const schemaDir = path25.join(root, "prisma", "schema");
7391
7402
  const schemaFile = path25.join(schemaDir, `${kebab}.prisma`);
7392
- if (await fs24.pathExists(schemaFile)) {
7403
+ if (await fs25.pathExists(schemaFile)) {
7393
7404
  log.error(`Schema file already exists: prisma/schema/${kebab}.prisma`);
7394
7405
  return;
7395
7406
  }
@@ -7407,8 +7418,8 @@ async function addModelCommand(name) {
7407
7418
  const ctx = createRollbackContext();
7408
7419
  try {
7409
7420
  ctx.trackCreatedFile(schemaFile);
7410
- await fs24.ensureDir(schemaDir);
7411
- await fs24.writeFile(schemaFile, content);
7421
+ await fs25.ensureDir(schemaDir);
7422
+ await fs25.writeFile(schemaFile, content);
7412
7423
  await ctx.commit();
7413
7424
  log.success(`Created model ${pc3.bold(pascal)} at prisma/schema/${kebab}.prisma`);
7414
7425
  trackEvent("add", { type: "model" });
@@ -7432,7 +7443,7 @@ async function addEmailCommand(name) {
7432
7443
  const camel = toCamel(name);
7433
7444
  const templatesDir = path25.join(root, "src", "lib", "core", "email", "templates");
7434
7445
  const filePath = path25.join(templatesDir, `${kebab}-email.ts`);
7435
- if (await fs24.pathExists(filePath)) {
7446
+ if (await fs25.pathExists(filePath)) {
7436
7447
  log.error(`Email template already exists: src/lib/core/email/templates/${kebab}-email.ts`);
7437
7448
  return;
7438
7449
  }
@@ -7479,22 +7490,22 @@ export function ${functionName}({ appName, actionUrl, userName }: ${pascal}Email
7479
7490
  const indexPath = path25.join(templatesDir, "index.ts");
7480
7491
  try {
7481
7492
  ctx.trackCreatedFile(filePath);
7482
- if (await fs24.pathExists(indexPath)) {
7493
+ if (await fs25.pathExists(indexPath)) {
7483
7494
  await ctx.trackModifiedFile(indexPath);
7484
7495
  } else {
7485
7496
  ctx.trackCreatedFile(indexPath);
7486
7497
  }
7487
- await fs24.ensureDir(templatesDir);
7488
- await fs24.writeFile(filePath, content);
7498
+ await fs25.ensureDir(templatesDir);
7499
+ await fs25.writeFile(filePath, content);
7489
7500
  const exportLine = `export { ${functionName} } from './${kebab}-email';
7490
7501
  `;
7491
- if (await fs24.pathExists(indexPath)) {
7492
- const existing = await fs24.readFile(indexPath, "utf-8");
7502
+ if (await fs25.pathExists(indexPath)) {
7503
+ const existing = await fs25.readFile(indexPath, "utf-8");
7493
7504
  if (!existing.includes(functionName)) {
7494
- await fs24.appendFile(indexPath, exportLine);
7505
+ await fs25.appendFile(indexPath, exportLine);
7495
7506
  }
7496
7507
  } else {
7497
- await fs24.writeFile(indexPath, exportLine);
7508
+ await fs25.writeFile(indexPath, exportLine);
7498
7509
  }
7499
7510
  await ctx.commit();
7500
7511
  log.success(`Created email template ${pc3.bold(kebab)} at src/lib/core/email/templates/${kebab}-email.ts`);
@@ -7518,9 +7529,9 @@ async function addComponentCommand(name, options) {
7518
7529
  return;
7519
7530
  }
7520
7531
  const dir = type === "primitive" ? path25.join(root, "src", "components", "primitives") : path25.join(root, "src", "components", "patterns");
7521
- await fs24.ensureDir(dir);
7532
+ await fs25.ensureDir(dir);
7522
7533
  const filePath = path25.join(dir, `${pascal}.tsx`);
7523
- if (await fs24.pathExists(filePath)) {
7534
+ if (await fs25.pathExists(filePath)) {
7524
7535
  log.error(`Component already exists: ${pascal}.tsx`);
7525
7536
  return;
7526
7537
  }
@@ -7569,7 +7580,7 @@ export function ${pascal}({ children, className }: ${pascal}Props) {
7569
7580
  const ctx = createRollbackContext();
7570
7581
  try {
7571
7582
  ctx.trackCreatedFile(filePath);
7572
- await fs24.writeFile(filePath, content);
7583
+ await fs25.writeFile(filePath, content);
7573
7584
  await ctx.commit();
7574
7585
  log.success(`Created ${type} component ${pc3.bold(pascal)} at ${path25.relative(root, filePath)}`);
7575
7586
  trackEvent("add", { type: "component", componentType: type });
@@ -7586,14 +7597,14 @@ export function ${pascal}({ children, className }: ${pascal}Props) {
7586
7597
  // src/commands/configure.ts
7587
7598
  init_logger();
7588
7599
  import { execSync as execSync2 } from "child_process";
7589
- import fs25 from "fs-extra";
7600
+ import fs26 from "fs-extra";
7590
7601
  import path26 from "path";
7591
7602
  import pc4 from "picocolors";
7592
7603
  import prompts6 from "prompts";
7593
7604
  function ensureInProject2() {
7594
7605
  const cwd = process.cwd();
7595
7606
  const configPath = path26.join(cwd, "src", "config", "app.config.ts");
7596
- if (!fs25.pathExistsSync(configPath)) {
7607
+ if (!fs26.pathExistsSync(configPath)) {
7597
7608
  log.error("Not inside a MARS project. Run this command from the project root.");
7598
7609
  process.exit(1);
7599
7610
  }
@@ -7608,7 +7619,7 @@ var PROVIDER_DEPENDENCIES = {
7608
7619
  };
7609
7620
  function updateAppConfig(projectDir, serviceKey, provider, featureKey) {
7610
7621
  const configPath = path26.join(projectDir, "src", "config", "app.config.ts");
7611
- let content = fs25.readFileSync(configPath, "utf-8");
7622
+ let content = fs26.readFileSync(configPath, "utf-8");
7612
7623
  if (serviceKey === "auth") {
7613
7624
  const boolValue = provider === "google" ? "true" : "false";
7614
7625
  const featureRegex = new RegExp(`(googleOAuth\\s*:\\s*)(?:true|false)`);
@@ -7623,10 +7634,10 @@ function updateAppConfig(projectDir, serviceKey, provider, featureKey) {
7623
7634
  content = content.replace(featureRegex, `$1true`);
7624
7635
  }
7625
7636
  }
7626
- fs25.writeFileSync(configPath, content);
7637
+ fs26.writeFileSync(configPath, content);
7627
7638
  }
7628
7639
  function detectPackageManager(projectDir) {
7629
- if (fs25.existsSync(path26.join(projectDir, "yarn.lock"))) return "yarn";
7640
+ if (fs26.existsSync(path26.join(projectDir, "yarn.lock"))) return "yarn";
7630
7641
  return "npm";
7631
7642
  }
7632
7643
  function installDependencies(projectDir, deps) {
@@ -7737,14 +7748,14 @@ async function configureCommand(service) {
7737
7748
  }
7738
7749
  if (selectedProvider.envVars.length > 0) {
7739
7750
  const envPath = path26.join(root, ".env");
7740
- if (await fs25.pathExists(envPath)) {
7741
- const envContent = await fs25.readFile(envPath, "utf-8");
7751
+ if (await fs26.pathExists(envPath)) {
7752
+ const envContent = await fs26.readFile(envPath, "utf-8");
7742
7753
  const missingVars = selectedProvider.envVars.filter(
7743
7754
  (v) => !envContent.includes(v)
7744
7755
  );
7745
7756
  if (missingVars.length > 0) {
7746
7757
  const additions = missingVars.map((v) => `${v}=""`).join("\n");
7747
- await fs25.appendFile(envPath, `
7758
+ await fs26.appendFile(envPath, `
7748
7759
  # ${selectedService} (${provider})
7749
7760
  ${additions}
7750
7761
  `);
@@ -7773,7 +7784,7 @@ ${additions}
7773
7784
 
7774
7785
  // src/commands/deploy.ts
7775
7786
  init_logger();
7776
- import fs26 from "fs-extra";
7787
+ import fs27 from "fs-extra";
7777
7788
  import path27 from "path";
7778
7789
  import { execSync as execSync3 } from "child_process";
7779
7790
  import pc5 from "picocolors";
@@ -7781,7 +7792,7 @@ import prompts7 from "prompts";
7781
7792
  function ensureInProject3() {
7782
7793
  const cwd = process.cwd();
7783
7794
  const configPath = path27.join(cwd, "src", "config", "app.config.ts");
7784
- if (!fs26.pathExistsSync(configPath)) {
7795
+ if (!fs27.pathExistsSync(configPath)) {
7785
7796
  log.error("Not inside a MARS project. Run this command from the project root.");
7786
7797
  process.exit(1);
7787
7798
  }
@@ -7821,7 +7832,7 @@ async function deployCommand() {
7821
7832
  }
7822
7833
  }
7823
7834
  const vercelDir = path27.join(root, ".vercel");
7824
- if (!fs26.existsSync(vercelDir)) {
7835
+ if (!fs27.existsSync(vercelDir)) {
7825
7836
  log.step("Linking project to Vercel...");
7826
7837
  try {
7827
7838
  execSync3("vercel link", { cwd: root, stdio: "inherit" });
@@ -7839,7 +7850,7 @@ async function deployCommand() {
7839
7850
  const requiredVars = ["JWT_SECRET", "DATABASE_URL"];
7840
7851
  log.step(`Core: ${pc5.dim(requiredVars.join(", "))}`);
7841
7852
  const configPath = path27.join(root, "src", "config", "app.config.ts");
7842
- const configContent = await fs26.readFile(configPath, "utf-8");
7853
+ const configContent = await fs27.readFile(configPath, "utf-8");
7843
7854
  if (configContent.includes("email: { provider: 'sendgrid'")) {
7844
7855
  log.step(`Email (SendGrid): ${pc5.dim("SENDGRID_API_KEY, SENDGRID_FROM_EMAIL")}`);
7845
7856
  } else if (configContent.includes("email: { provider: 'resend'")) {
@@ -7900,7 +7911,7 @@ async function deployCommand() {
7900
7911
 
7901
7912
  // src/commands/upgrade.ts
7902
7913
  init_logger();
7903
- import fs27 from "fs-extra";
7914
+ import fs28 from "fs-extra";
7904
7915
  import path28 from "path";
7905
7916
  import { execSync as execSync4 } from "child_process";
7906
7917
  var MARS_PACKAGES = ["@mars-stack/core", "@mars-stack/ui"];
@@ -7924,7 +7935,7 @@ function readCurrentVersion(packageJson, packageName) {
7924
7935
  return version ? version.replace(/^[\^~]/, "") : null;
7925
7936
  }
7926
7937
  function detectPackageManager2(projectDir) {
7927
- if (fs27.pathExistsSync(path28.join(projectDir, "yarn.lock"))) {
7938
+ if (fs28.pathExistsSync(path28.join(projectDir, "yarn.lock"))) {
7928
7939
  return "yarn";
7929
7940
  }
7930
7941
  return "npm";
@@ -7988,7 +7999,7 @@ function updatePackageJsonVersions(packageJsonPath, packageJson, versions) {
7988
7999
  if (updated.length > 0) {
7989
8000
  packageJson.dependencies = deps;
7990
8001
  packageJson.devDependencies = devDeps;
7991
- fs27.writeJsonSync(packageJsonPath, packageJson, { spaces: 2 });
8002
+ fs28.writeJsonSync(packageJsonPath, packageJson, { spaces: 2 });
7992
8003
  }
7993
8004
  return updated;
7994
8005
  }
@@ -7999,14 +8010,14 @@ function upgradeCommand(program2) {
7999
8010
  log.title("MARS Upgrade");
8000
8011
  const projectDir = process.cwd();
8001
8012
  const packageJsonPath = path28.join(projectDir, "package.json");
8002
- if (!fs27.pathExistsSync(packageJsonPath)) {
8013
+ if (!fs28.pathExistsSync(packageJsonPath)) {
8003
8014
  log.error(
8004
8015
  "No package.json found. Are you in a Mars project directory?"
8005
8016
  );
8006
8017
  process.exitCode = 1;
8007
8018
  return;
8008
8019
  }
8009
- const packageJson = fs27.readJsonSync(packageJsonPath);
8020
+ const packageJson = fs28.readJsonSync(packageJsonPath);
8010
8021
  const hasMarsPackage = MARS_PACKAGES.some(
8011
8022
  (name) => readCurrentVersion(packageJson, name) !== null
8012
8023
  );