@donotdev/cli 0.0.17 → 0.0.19

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 (183) hide show
  1. package/dependencies-matrix.json +67 -60
  2. package/dist/bin/commands/coach.js +8177 -0
  3. package/dist/bin/commands/create-app.js +94 -145
  4. package/dist/bin/commands/create-project.js +98 -149
  5. package/dist/bin/commands/deploy.js +81 -59
  6. package/dist/bin/commands/doctor.js +243 -698
  7. package/dist/bin/commands/emu.js +2 -2
  8. package/dist/bin/commands/format.js +4 -1
  9. package/dist/bin/commands/get-demo.js +8351 -0
  10. package/dist/bin/commands/make-admin.js +773 -152
  11. package/dist/bin/commands/setup.js +519 -1711
  12. package/dist/bin/commands/staging.js +17852 -0
  13. package/dist/bin/commands/sync-secrets.js +2 -11
  14. package/dist/bin/commands/type-check.js +7733 -1713
  15. package/dist/bin/dndev.js +913 -182
  16. package/dist/bin/donotdev.js +913 -182
  17. package/dist/index.js +191 -211
  18. package/package.json +1 -1
  19. package/templates/app-demo/index.html.example +147 -10
  20. package/templates/app-demo/src/App.tsx.example +7 -13
  21. package/templates/app-demo/src/config/app.ts.example +12 -48
  22. package/templates/app-demo/src/entities/product.ts.example +38 -0
  23. package/templates/app-demo/src/globals.css.example +5 -1
  24. package/templates/app-demo/src/main.tsx.example +13 -7
  25. package/templates/app-demo/src/pages/ChangelogPage.tsx.example +14 -0
  26. package/templates/app-demo/src/pages/DashboardPage.tsx.example +15 -0
  27. package/templates/app-demo/src/pages/HomePage.tsx.example +3 -77
  28. package/templates/app-demo/src/pages/PricingPage.tsx.example +14 -0
  29. package/templates/app-demo/src/pages/ProductsPage.tsx.example +17 -0
  30. package/templates/app-demo/src/pages/ProfilePage.tsx.example +16 -0
  31. package/templates/app-demo/src/pages/SettingsPage.tsx.example +15 -0
  32. package/templates/app-demo/src/pages/ShowcaseDetailPage.tsx.example +112 -0
  33. package/templates/app-demo/src/pages/ShowcasePage.tsx.example +91 -0
  34. package/templates/app-demo/src/pages/legal/LegalPage.tsx.example +14 -0
  35. package/templates/app-demo/src/pages/legal/PrivacyPage.tsx.example +14 -0
  36. package/templates/app-demo/src/pages/legal/TermsPage.tsx.example +14 -0
  37. package/templates/app-demo/tsconfig.json.example +1 -1
  38. package/templates/app-demo/vite.config.ts.example +23 -48
  39. package/templates/app-expo/README.md.example +1 -1
  40. package/templates/app-expo/app/index.tsx.example +1 -1
  41. package/templates/app-vite/src/pages/HomePage.tsx.example +8 -10
  42. package/templates/overlay-firebase/env.fragment.example +1 -1
  43. package/templates/overlay-firebase/env.fragment.expo.example +1 -1
  44. package/templates/overlay-firebase/env.fragment.nextjs.example +1 -1
  45. package/templates/overlay-supabase/env.fragment.example +1 -1
  46. package/templates/overlay-supabase/env.fragment.expo.example +1 -1
  47. package/templates/overlay-supabase/env.fragment.nextjs.example +1 -1
  48. package/templates/overlay-vercel/env.fragment.example +1 -1
  49. package/templates/overlay-vercel/env.fragment.nextjs.example +1 -1
  50. package/templates/root-consumer/.claude/commands/brainstorm.md.example +15 -1
  51. package/templates/root-consumer/.claude/commands/build.md.example +24 -2
  52. package/templates/root-consumer/.claude/commands/design.md.example +17 -0
  53. package/templates/root-consumer/.claude/commands/polish.md.example +17 -0
  54. package/templates/root-consumer/AI.md.example +54 -21
  55. package/templates/root-consumer/guides/dndev/AGENT_START_HERE.md.example +21 -6
  56. package/templates/root-consumer/guides/dndev/COMPONENTS_ADV.md.example +16 -179
  57. package/templates/root-consumer/guides/dndev/ENV_SETUP.md.example +19 -21
  58. package/templates/root-consumer/guides/dndev/GOTCHAS.md.example +14 -3
  59. package/templates/root-consumer/guides/dndev/INDEX.md.example +2 -2
  60. package/templates/root-consumer/guides/dndev/SETUP_APP_CONFIG.md.example +3 -3
  61. package/templates/root-consumer/guides/dndev/SETUP_BLOG.md.example +19 -2
  62. package/templates/root-consumer/guides/dndev/SETUP_CRUD.md.example +35 -1
  63. package/templates/root-consumer/guides/dndev/SETUP_FIREBASE.md.example +17 -12
  64. package/templates/root-consumer/guides/dndev/SETUP_LAYOUTS.md.example +32 -0
  65. package/templates/root-consumer/guides/dndev/SETUP_OAUTH_PROVIDERS.md.example +1 -1
  66. package/templates/root-consumer/guides/dndev/SETUP_PAGES.md.example +74 -6
  67. package/templates/root-consumer/guides/dndev/SETUP_STRIPE.md.example +2 -2
  68. package/templates/root-consumer/guides/dndev/SETUP_SUPABASE.md.example +17 -12
  69. package/templates/root-consumer/guides/dndev/SETUP_VERCEL.md.example +37 -16
  70. package/templates/root-consumer/guides/dndev/USE_ROUTING.md.example +18 -18
  71. package/templates/root-consumer/guides/dndev/essences_reference.css.example +119 -2
  72. package/templates/root-consumer/guides/wai-way/blueprints/0_brainstorm.md.example +1 -1
  73. package/templates/root-consumer/guides/wai-way/blueprints/1_scaffold.md.example +14 -0
  74. package/templates/root-consumer/guides/wai-way/blueprints/2_entities.md.example +6 -0
  75. package/templates/root-consumer/guides/wai-way/blueprints/3_compose.md.example +14 -0
  76. package/templates/root-consumer/guides/wai-way/entity_patterns.md.example +4 -5
  77. package/templates/root-consumer/guides/wai-way/page_patterns.md.example +2 -2
  78. package/dist/bin/commands/agent-setup.d.ts +0 -6
  79. package/dist/bin/commands/agent-setup.d.ts.map +0 -1
  80. package/dist/bin/commands/agent-setup.js.map +0 -1
  81. package/dist/bin/commands/build.d.ts +0 -11
  82. package/dist/bin/commands/build.d.ts.map +0 -1
  83. package/dist/bin/commands/build.js.map +0 -1
  84. package/dist/bin/commands/bump.d.ts +0 -11
  85. package/dist/bin/commands/bump.d.ts.map +0 -1
  86. package/dist/bin/commands/bump.js.map +0 -1
  87. package/dist/bin/commands/cacheout.d.ts +0 -11
  88. package/dist/bin/commands/cacheout.d.ts.map +0 -1
  89. package/dist/bin/commands/cacheout.js.map +0 -1
  90. package/dist/bin/commands/create-app.d.ts +0 -11
  91. package/dist/bin/commands/create-app.d.ts.map +0 -1
  92. package/dist/bin/commands/create-app.js.map +0 -1
  93. package/dist/bin/commands/create-project.d.ts +0 -11
  94. package/dist/bin/commands/create-project.d.ts.map +0 -1
  95. package/dist/bin/commands/create-project.js.map +0 -1
  96. package/dist/bin/commands/deploy.d.ts +0 -11
  97. package/dist/bin/commands/deploy.d.ts.map +0 -1
  98. package/dist/bin/commands/deploy.js.map +0 -1
  99. package/dist/bin/commands/dev.d.ts +0 -11
  100. package/dist/bin/commands/dev.d.ts.map +0 -1
  101. package/dist/bin/commands/dev.js.map +0 -1
  102. package/dist/bin/commands/doctor.d.ts +0 -6
  103. package/dist/bin/commands/doctor.d.ts.map +0 -1
  104. package/dist/bin/commands/doctor.js.map +0 -1
  105. package/dist/bin/commands/emu.d.ts +0 -11
  106. package/dist/bin/commands/emu.d.ts.map +0 -1
  107. package/dist/bin/commands/emu.js.map +0 -1
  108. package/dist/bin/commands/format.d.ts +0 -11
  109. package/dist/bin/commands/format.d.ts.map +0 -1
  110. package/dist/bin/commands/format.js.map +0 -1
  111. package/dist/bin/commands/make-admin.d.ts +0 -11
  112. package/dist/bin/commands/make-admin.d.ts.map +0 -1
  113. package/dist/bin/commands/make-admin.js.map +0 -1
  114. package/dist/bin/commands/preview.d.ts +0 -11
  115. package/dist/bin/commands/preview.d.ts.map +0 -1
  116. package/dist/bin/commands/preview.js.map +0 -1
  117. package/dist/bin/commands/setup.d.ts +0 -6
  118. package/dist/bin/commands/setup.d.ts.map +0 -1
  119. package/dist/bin/commands/setup.js.map +0 -1
  120. package/dist/bin/commands/sync-secrets.d.ts +0 -11
  121. package/dist/bin/commands/sync-secrets.d.ts.map +0 -1
  122. package/dist/bin/commands/sync-secrets.js.map +0 -1
  123. package/dist/bin/commands/type-check.d.ts +0 -14
  124. package/dist/bin/commands/type-check.d.ts.map +0 -1
  125. package/dist/bin/commands/type-check.js.map +0 -1
  126. package/dist/bin/commands/wai.d.ts +0 -11
  127. package/dist/bin/commands/wai.d.ts.map +0 -1
  128. package/dist/bin/commands/wai.js.map +0 -1
  129. package/dist/index.d.ts +0 -8
  130. package/dist/index.d.ts.map +0 -1
  131. package/dist/index.js.map +0 -1
  132. package/templates/app-demo/src/components/ThemeToggle.tsx.example +0 -48
  133. package/templates/app-demo/src/pages/DetailPage.tsx.example +0 -103
  134. package/templates/app-demo/src/pages/FullPage.tsx.example +0 -142
  135. package/templates/app-demo/src/pages/components/DemoLayout.tsx.example +0 -266
  136. package/templates/app-demo/src/pages/components/LayoutRoute.tsx.example +0 -20
  137. package/templates/functions-firebase/functions-firebase/README.md.example +0 -123
  138. package/templates/functions-firebase/functions-firebase/build.mjs.example +0 -5
  139. package/templates/functions-firebase/functions-firebase/src/auth/getCustomClaims.ts.example +0 -19
  140. package/templates/functions-firebase/functions-firebase/src/auth/getUserAuthStatus.ts.example +0 -21
  141. package/templates/functions-firebase/functions-firebase/src/auth/index.ts.example +0 -11
  142. package/templates/functions-firebase/functions-firebase/src/auth/removeCustomClaims.ts.example +0 -21
  143. package/templates/functions-firebase/functions-firebase/src/auth/setCustomClaims.ts.example +0 -21
  144. package/templates/functions-firebase/functions-firebase/src/billing/handleStripeWebhook.ts.example +0 -24
  145. package/templates/functions-firebase/functions-firebase/src/billing/index.ts.example +0 -10
  146. package/templates/functions-firebase/functions-firebase/src/billing/processPaymentSuccess.ts.example +0 -14
  147. package/templates/functions-firebase/functions-firebase/src/billing/refreshSubscriptionStatus.ts.example +0 -14
  148. package/templates/functions-firebase/functions-firebase/src/index.ts.example +0 -39
  149. package/templates/functions-firebase/functions-firebase/src/oauth/checkGitHubAccess.ts.example +0 -14
  150. package/templates/functions-firebase/functions-firebase/src/oauth/disconnect.ts.example +0 -14
  151. package/templates/functions-firebase/functions-firebase/src/oauth/exchangeToken.ts.example +0 -14
  152. package/templates/functions-firebase/functions-firebase/src/oauth/getConnections.ts.example +0 -14
  153. package/templates/functions-firebase/functions-firebase/src/oauth/grantGitHubAccess.ts.example +0 -14
  154. package/templates/functions-firebase/functions-firebase/src/oauth/index.ts.example +0 -17
  155. package/templates/functions-firebase/functions-firebase/src/oauth/refreshToken.ts.example +0 -14
  156. package/templates/functions-firebase/functions-firebase/src/oauth/revokeGitHubAccess.ts.example +0 -14
  157. package/templates/functions-firebase/functions-firebase/tsconfig.json.example +0 -21
  158. package/templates/functions-vercel/functions-vercel/README.md.example +0 -116
  159. package/templates/functions-vercel/functions-vercel/build.mjs.example +0 -52
  160. package/templates/functions-vercel/functions-vercel/src/api/auth/getCustomClaims.ts.example +0 -20
  161. package/templates/functions-vercel/functions-vercel/src/api/auth/getUserAuthStatus.ts.example +0 -20
  162. package/templates/functions-vercel/functions-vercel/src/api/auth/removeCustomClaims.ts.example +0 -20
  163. package/templates/functions-vercel/functions-vercel/src/api/auth/setCustomClaims.ts.example +0 -20
  164. package/templates/functions-vercel/functions-vercel/src/api/billing/handleStripeWebhook.ts.example +0 -20
  165. package/templates/functions-vercel/functions-vercel/src/api/billing/processPaymentSuccess.ts.example +0 -20
  166. package/templates/functions-vercel/functions-vercel/src/api/billing/refreshSubscriptionStatus.ts.example +0 -20
  167. package/templates/functions-vercel/functions-vercel/src/api/crud/createEntity.ts.example +0 -20
  168. package/templates/functions-vercel/functions-vercel/src/api/crud/deleteEntity.ts.example +0 -20
  169. package/templates/functions-vercel/functions-vercel/src/api/crud/getEntity.ts.example +0 -20
  170. package/templates/functions-vercel/functions-vercel/src/api/crud/listEntities.ts.example +0 -20
  171. package/templates/functions-vercel/functions-vercel/src/api/crud/updateEntity.ts.example +0 -20
  172. package/templates/functions-vercel/functions-vercel/src/api/oauth/checkGitHubAccess.ts.example +0 -20
  173. package/templates/functions-vercel/functions-vercel/src/api/oauth/disconnect.ts.example +0 -20
  174. package/templates/functions-vercel/functions-vercel/src/api/oauth/exchangeToken.ts.example +0 -20
  175. package/templates/functions-vercel/functions-vercel/src/api/oauth/getConnections.ts.example +0 -20
  176. package/templates/functions-vercel/functions-vercel/src/api/oauth/grantGitHubAccess.ts.example +0 -20
  177. package/templates/functions-vercel/functions-vercel/src/api/oauth/refreshToken.ts.example +0 -20
  178. package/templates/functions-vercel/functions-vercel/src/api/oauth/revokeGitHubAccess.ts.example +0 -20
  179. package/templates/functions-vercel/functions-vercel/tsconfig.json.example +0 -21
  180. package/templates/functions-vercel/functions-vercel/vercel.json.example +0 -14
  181. package/templates/github/github/workflows/firebase-deploy.yml.example +0 -79
  182. /package/templates/functions-firebase/{functions-firebase/.env.example.example → .env.example} +0 -0
  183. /package/templates/functions-vercel/{functions-vercel/.env.example.example → .env.example} +0 -0
package/dist/index.js CHANGED
@@ -8859,21 +8859,21 @@ function getCLIInstallInstructions(tool) {
8859
8859
  ]
8860
8860
  },
8861
8861
  [CLI_TOOLS.YARN]: {
8862
- win32: ["npm install -g yarn", "Or: choco install yarn"],
8863
- darwin: ["npm install -g yarn", "Or: brew install yarn"],
8864
- linux: ["npm install -g yarn", "Or check your package manager"]
8862
+ win32: ["bun install -g yarn", "Or: choco install yarn"],
8863
+ darwin: ["bun install -g yarn", "Or: brew install yarn"],
8864
+ linux: ["bun install -g yarn", "Or check your package manager"]
8865
8865
  },
8866
8866
  [CLI_TOOLS.FIREBASE]: {
8867
8867
  win32: [
8868
- "npm install -g firebase-tools",
8868
+ "bun install -g firebase-tools",
8869
8869
  "Or download standalone binary: https://firebase.google.com/docs/cli#windows-standalone-binary"
8870
8870
  ],
8871
8871
  darwin: [
8872
- "npm install -g firebase-tools",
8872
+ "bun install -g firebase-tools",
8873
8873
  "Or: brew install firebase-cli"
8874
8874
  ],
8875
8875
  linux: [
8876
- "npm install -g firebase-tools",
8876
+ "bun install -g firebase-tools",
8877
8877
  "Or check your package manager (dnf, apt, pacman, etc.)"
8878
8878
  ]
8879
8879
  },
@@ -8890,25 +8890,25 @@ function getCLIInstallInstructions(tool) {
8890
8890
  ]
8891
8891
  },
8892
8892
  [CLI_TOOLS.VERCEL]: {
8893
- win32: ["npm install -g vercel", "Or: npx vercel (no install)"],
8893
+ win32: ["bun install -g vercel", "Or: bunx vercel (no install)"],
8894
8894
  darwin: [
8895
- "npm install -g vercel",
8895
+ "bun install -g vercel",
8896
8896
  "Or: brew install vercel",
8897
- "Or: npx vercel"
8897
+ "Or: bunx vercel"
8898
8898
  ],
8899
- linux: ["npm install -g vercel", "Or: npx vercel"]
8899
+ linux: ["bun install -g vercel", "Or: bunx vercel"]
8900
8900
  },
8901
8901
  [CLI_TOOLS.SENTRY_CLI]: {
8902
8902
  win32: [
8903
- "npm install -g @sentry/cli",
8903
+ "bun install -g @sentry/cli",
8904
8904
  "Or download from: https://github.com/getsentry/sentry-cli/releases"
8905
8905
  ],
8906
8906
  darwin: [
8907
- "npm install -g @sentry/cli",
8907
+ "bun install -g @sentry/cli",
8908
8908
  "Or: brew install getsentry/tools/sentry-cli"
8909
8909
  ],
8910
8910
  linux: [
8911
- "npm install -g @sentry/cli",
8911
+ "bun install -g @sentry/cli",
8912
8912
  "Or: curl -sL https://sentry.io/get-cli/ | bash"
8913
8913
  ]
8914
8914
  },
@@ -8937,9 +8937,9 @@ function getCLIInstallInstructions(tool) {
8937
8937
  ]
8938
8938
  },
8939
8939
  [CLI_TOOLS.TSX]: {
8940
- win32: ["npm install -g tsx"],
8941
- darwin: ["npm install -g tsx"],
8942
- linux: ["npm install -g tsx"]
8940
+ win32: ["bun install -g tsx"],
8941
+ darwin: ["bun install -g tsx"],
8942
+ linux: ["bun install -g tsx"]
8943
8943
  }
8944
8944
  };
8945
8945
  const platformInstructions = instructions[tool]?.[platform6] || instructions[tool]?.linux || [];
@@ -9034,14 +9034,27 @@ function readEnvVar(filePath, varName) {
9034
9034
  }
9035
9035
  return null;
9036
9036
  }
9037
- function resolveVercelToken(appDir) {
9038
- if (process.env.VERCEL_TOKEN) return process.env.VERCEL_TOKEN;
9039
- const fromEnv = readEnvVar(joinPath(appDir, ".env"), "VERCEL_TOKEN");
9040
- if (fromEnv) return fromEnv;
9041
- const fromLocal = readEnvVar(joinPath(appDir, ".env.local"), "VERCEL_TOKEN");
9037
+ function resolveVercelVar(appDir, varName) {
9038
+ if (process.env[varName]) return process.env[varName];
9039
+ const fromLocal = readEnvVar(joinPath(appDir, ".env.local"), varName);
9042
9040
  if (fromLocal) return fromLocal;
9041
+ const fromEnv = readEnvVar(joinPath(appDir, ".env"), varName);
9042
+ if (fromEnv) return fromEnv;
9043
9043
  return null;
9044
9044
  }
9045
+ function resolveVercelCredentials(appDir) {
9046
+ const token = resolveVercelVar(appDir, "VERCEL_TOKEN");
9047
+ const orgId = resolveVercelVar(appDir, "VERCEL_ORG_ID");
9048
+ const projectId = resolveVercelVar(appDir, "VERCEL_PROJECT_ID");
9049
+ const missing = [];
9050
+ if (!token) missing.push("VERCEL_TOKEN");
9051
+ if (!orgId) missing.push("VERCEL_ORG_ID");
9052
+ if (!projectId) missing.push("VERCEL_PROJECT_ID");
9053
+ if (missing.length > 0) return { missing };
9054
+ return {
9055
+ credentials: { token, orgId, projectId }
9056
+ };
9057
+ }
9045
9058
  var init_vercel_token = __esm({
9046
9059
  "packages/tooling/src/cli/setup/vercel-token.ts"() {
9047
9060
  "use strict";
@@ -16621,10 +16634,7 @@ async function setFirebaseSecret(key, value, projectId, dryRun = false, cwd) {
16621
16634
  }
16622
16635
  try {
16623
16636
  log.info(`Setting Firebase secret: ${key} (project: ${finalProjectId})`);
16624
- const tempDir = joinPath(process.cwd(), ".tmp");
16625
- await ensureDir(tempDir);
16626
- const tempFile = joinPath(tempDir, `secret-${key}-${Date.now()}.txt`);
16627
- await write(tempFile, value);
16637
+ const tempFile = "";
16628
16638
  try {
16629
16639
  const args = ["functions:secrets:set", key, "--project", finalProjectId];
16630
16640
  const firebaseCmd = process.platform === "win32" ? "firebase.cmd" : "firebase";
@@ -16699,9 +16709,6 @@ ${errorOutput}`
16699
16709
  }
16700
16710
  log.success(`Firebase secret ${key} set successfully`);
16701
16711
  } finally {
16702
- if (pathExists(tempFile)) {
16703
- await remove(tempFile);
16704
- }
16705
16712
  }
16706
16713
  } catch (err) {
16707
16714
  log.error(`Failed to set Firebase secret ${key}:`, err);
@@ -17934,7 +17941,7 @@ async function startSupabase(app, _projectRoot) {
17934
17941
  execSync5("supabase --version", { stdio: "pipe" });
17935
17942
  } catch {
17936
17943
  log.error("Supabase CLI not found. Install it:");
17937
- log.error(" npm install -g supabase\n");
17944
+ log.error(" bun install -g supabase\n");
17938
17945
  return 1;
17939
17946
  }
17940
17947
  const isWindows = platform3() === "win32";
@@ -18004,7 +18011,7 @@ async function startVercel(app, _projectRoot) {
18004
18011
  execSync6("vercel --version", { stdio: "pipe" });
18005
18012
  } catch {
18006
18013
  log.error("Vercel CLI not found. Install it:");
18007
- log.error(" npm install -g vercel\n");
18014
+ log.error(" bun install -g vercel\n");
18008
18015
  return 1;
18009
18016
  }
18010
18017
  const isWindows = platform4() === "win32";
@@ -18617,34 +18624,67 @@ var APP_QUESTIONNAIRE = [
18617
18624
  ]
18618
18625
  },
18619
18626
  {
18620
- id: "needsBackend",
18621
- question: "Include backend functions?",
18622
- type: "confirm",
18623
- defaultValue: false
18627
+ id: "host",
18628
+ question: "Where will you host?",
18629
+ type: "select",
18630
+ condition: (answers) => answers.framework !== "expo",
18631
+ defaultValue: (answers) => {
18632
+ return answers.framework === "nextjs" ? "vercel" : "none";
18633
+ },
18634
+ choices: [
18635
+ { title: "None \u2014 no hosting config", value: "none" },
18636
+ { title: "Vercel \u2014 edge CDN + serverless", value: "vercel" },
18637
+ { title: "Firebase Hosting \u2014 Google CDN", value: "firebase" }
18638
+ ]
18639
+ },
18640
+ {
18641
+ id: "functions",
18642
+ question: "Serverless functions?",
18643
+ type: "select",
18644
+ defaultValue: "none",
18645
+ // Choices filtered dynamically based on host
18646
+ choices: [
18647
+ { title: "None", value: "none" },
18648
+ { title: "Vercel Functions \u2014 edge + node.js", value: "vercel" },
18649
+ { title: "Firebase Functions \u2014 Google Cloud", value: "firebase" },
18650
+ { title: "Supabase Edge Functions \u2014 Deno", value: "supabase" }
18651
+ ],
18652
+ choicesFilter: (answers) => {
18653
+ const host = answers.host ?? "none";
18654
+ const framework = answers.framework;
18655
+ if (framework === "expo") return ["none", "firebase", "supabase"];
18656
+ if (host === "firebase") return ["none", "firebase"];
18657
+ if (host === "vercel") return ["none", "vercel", "supabase"];
18658
+ return ["none", "vercel", "firebase", "supabase"];
18659
+ }
18624
18660
  },
18625
18661
  {
18626
- id: "backendPlatform",
18627
- question: "Which backend platform?",
18662
+ id: "backend",
18663
+ question: "Backend / BaaS provider?",
18628
18664
  type: "select",
18629
- dependsOn: "needsBackend",
18630
- condition: (answers) => answers.needsBackend === true,
18631
18665
  defaultValue: (answers) => {
18632
- return answers.framework === "nextjs" ? "vercel" : "firebase";
18666
+ if (answers.functions === "firebase") return "firebase";
18667
+ if (answers.functions === "supabase") return "supabase";
18668
+ return "none";
18633
18669
  },
18634
18670
  choices: [
18671
+ { title: "None \u2014 frontend only", value: "none" },
18635
18672
  {
18636
- title: "Firebase \u2014 Full-stack platform (hosting + functions + auth + firestore)",
18673
+ title: "Firebase \u2014 Auth + Firestore + Storage",
18637
18674
  value: "firebase"
18638
18675
  },
18639
- {
18640
- title: "Vercel \u2014 Serverless functions (edge + node.js)",
18641
- value: "vercel"
18642
- },
18643
18676
  {
18644
18677
  title: "Supabase \u2014 Postgres + Auth + Storage",
18645
18678
  value: "supabase"
18646
18679
  }
18647
- ]
18680
+ ],
18681
+ choicesFilter: (answers) => {
18682
+ const functions = answers.functions ?? "none";
18683
+ if (functions === "firebase") return ["none", "firebase"];
18684
+ if (functions === "supabase") return ["none", "supabase"];
18685
+ if (functions === "vercel") return ["none"];
18686
+ return ["none", "firebase", "supabase"];
18687
+ }
18648
18688
  }
18649
18689
  ];
18650
18690
  var PROJECT_QUESTIONNAIRE = [
@@ -18662,12 +18702,13 @@ var PROJECT_QUESTIONNAIRE = [
18662
18702
  }
18663
18703
  ];
18664
18704
  function aggregateRequirements(answers) {
18705
+ const hasBackend = answers.backend && answers.backend !== "none" || answers.functions && answers.functions !== "none";
18665
18706
  const requirements = {
18666
18707
  entities: [],
18667
18708
  // Entities created in apps/<app>/entities/ (v1), root entities/ for v2
18668
18709
  billing: true,
18669
18710
  // Always on (useStripeBillingSafe handles missing package)
18670
- backend: answers.needsBackend || false,
18711
+ backend: hasBackend,
18671
18712
  features: [],
18672
18713
  template: "vite",
18673
18714
  // Only Vite for now
@@ -18691,6 +18732,10 @@ async function runQuestionnaire(questions, initialAnswers, showWIP, askFor) {
18691
18732
  if (!showWIP) {
18692
18733
  choices = choices.filter((choice) => !choice.wip);
18693
18734
  }
18735
+ if (question.choicesFilter) {
18736
+ const allowed = question.choicesFilter(answers);
18737
+ choices = choices.filter((c) => allowed.includes(c.value));
18738
+ }
18694
18739
  if (choices.length === 0) continue;
18695
18740
  answer = await askFor.selection(question.question, choices);
18696
18741
  break;
@@ -18744,33 +18789,39 @@ init_cli_output();
18744
18789
  init_vercel_token();
18745
18790
  import { spawnSync as spawnSync6 } from "node:child_process";
18746
18791
  async function deployVercelFrontend(appDir, _config) {
18747
- const s = Y2();
18748
- s.start("Deploying frontend to Vercel...");
18749
- const token = resolveVercelToken(appDir);
18750
- if (token) {
18751
- log.debug("Using VERCEL_TOKEN from .env (token-based auth)");
18752
- }
18753
- const args = ["vercel", "--prod", "--yes"];
18754
- if (token) {
18755
- args.push("--token", token);
18792
+ const result = resolveVercelCredentials(appDir);
18793
+ if (result.missing) {
18794
+ throw new Error(
18795
+ `Missing Vercel credentials in .env.local: ${result.missing.join(", ")}
18796
+ Add them to apps/<app>/.env.local \u2014 see guides/dndev/SETUP_VERCEL.md`
18797
+ );
18756
18798
  }
18757
- try {
18758
- const result = spawnSync6("bunx", args, {
18799
+ const { token, orgId, projectId } = result.credentials;
18800
+ log.debug("Using Vercel credentials from .env (token-based auth)");
18801
+ log.info("Deploying to Vercel...");
18802
+ const deployResult = spawnSync6(
18803
+ "bunx",
18804
+ ["vercel", "deploy", "--prod", "--yes", "--token", token],
18805
+ {
18759
18806
  cwd: appDir,
18760
- stdio: "pipe",
18761
- encoding: "utf-8"
18762
- });
18763
- if (result.status !== 0) {
18764
- s.stop("Vercel deployment failed");
18765
- const errOutput = result.stderr?.trim();
18766
- throw new Error(
18767
- errOutput || `Vercel deploy exited with code ${result.status}`
18768
- );
18807
+ // stdout piped to capture deployment URL, stderr inherits for progress
18808
+ stdio: ["inherit", "pipe", "inherit"],
18809
+ encoding: "utf-8",
18810
+ env: {
18811
+ ...process.env,
18812
+ VERCEL_ORG_ID: orgId,
18813
+ VERCEL_PROJECT_ID: projectId
18814
+ }
18769
18815
  }
18770
- s.stop("Frontend deployed to Vercel");
18771
- } catch (err) {
18772
- s.stop("Vercel deployment failed");
18773
- throw err;
18816
+ );
18817
+ if (deployResult.status !== 0) {
18818
+ throw new Error(`vercel deploy exited with code ${deployResult.status}`);
18819
+ }
18820
+ const deployUrl = deployResult.stdout?.trim();
18821
+ if (deployUrl) {
18822
+ log.success(`Production: ${deployUrl}`);
18823
+ } else {
18824
+ log.success("Frontend deployed to Vercel");
18774
18825
  }
18775
18826
  }
18776
18827
 
@@ -19132,7 +19183,7 @@ async function deployFunctions(appDir, serviceAccountPath, projectId, config) {
19132
19183
 
19133
19184
  To fix this, run:
19134
19185
  cd ${functionsDir}
19135
- npm install --production`,
19186
+ bun install --production`,
19136
19187
  "file-not-found",
19137
19188
  { context: { missingPackages, functionsDir } }
19138
19189
  );
@@ -19497,7 +19548,19 @@ function detectProvider(appDir) {
19497
19548
  const supabaseFunctionsDir = joinPath(supabaseDir, "functions");
19498
19549
  const supabaseMigrationsDir = joinPath(supabaseDir, "migrations");
19499
19550
  const hasFirebase = pathExists(firebaseJsonPath);
19500
- const hasSupabase = pathExists(supabaseDir) || pathExists(supabaseConfigPath);
19551
+ let hasSupabase = pathExists(supabaseDir) || pathExists(supabaseConfigPath);
19552
+ if (!hasSupabase) {
19553
+ try {
19554
+ const envPath = joinPath(appDir, ".env");
19555
+ if (pathExists(envPath)) {
19556
+ const envContent = readSync(envPath);
19557
+ if (envContent.match(/VITE_SUPABASE_URL=.+/)) {
19558
+ hasSupabase = true;
19559
+ }
19560
+ }
19561
+ } catch {
19562
+ }
19563
+ }
19501
19564
  let provider = "unknown";
19502
19565
  if (hasFirebase && hasSupabase) {
19503
19566
  provider = "both";
@@ -19861,7 +19924,7 @@ async function main6(options = {}) {
19861
19924
  if (shouldDeployVercelFrontend) {
19862
19925
  requireCLI(
19863
19926
  CLI_TOOLS.VERCEL,
19864
- "Vercel CLI is required to deploy the frontend.\nInstall: npm i -g vercel or use npx vercel"
19927
+ "Vercel CLI is required to deploy the frontend.\nInstall: bun install -g vercel"
19865
19928
  );
19866
19929
  }
19867
19930
  if (shouldDeployFirebaseFrontend && serviceAccountPath && config.project) {
@@ -19976,10 +20039,10 @@ function generateScripts(templateName, options) {
19976
20039
  scripts.lint = "eslint .";
19977
20040
  scripts["type-check"] = "tsc --noEmit";
19978
20041
  } else if (templateName === "consumer-root") {
19979
- scripts.dev = "turbo run dev";
20042
+ scripts.dev = "dndev dev";
19980
20043
  scripts.build = "turbo run build";
19981
20044
  scripts.lint = "turbo run lint";
19982
- scripts["type-check"] = "turbo run type-check";
20045
+ scripts["type-check"] = "dndev tc";
19983
20046
  } else if (templateName.includes("functions")) {
19984
20047
  scripts.build = "node build.mjs";
19985
20048
  scripts["build:tsc"] = "tsc";
@@ -19990,9 +20053,9 @@ function generateScripts(templateName, options) {
19990
20053
  scripts.dev = "vercel dev";
19991
20054
  }
19992
20055
  } else if (templateName === "demo") {
19993
- scripts.dev = "bunx vite";
19994
- scripts.build = "tsc --noEmit && bunx vite build";
19995
- scripts.preview = "bunx vite preview";
20056
+ scripts.dev = "vite";
20057
+ scripts.build = "tsc --noEmit && vite build --mode production";
20058
+ scripts.preview = "vite preview";
19996
20059
  scripts["type-check"] = "tsc --noEmit";
19997
20060
  } else if (templateName === "entities") {
19998
20061
  }
@@ -20114,120 +20177,22 @@ init_pathResolver();
20114
20177
 
20115
20178
  // packages/tooling/src/scaffolding/scaffold-matrix.ts
20116
20179
  init_utils();
20117
- var MATRIX = [
20118
- {
20119
- builder: "vite",
20120
- backend: "none",
20121
- baseTemplate: "app-vite",
20122
- overlay: null,
20123
- deployConfig: null,
20124
- functionsTemplate: null
20125
- },
20126
- {
20127
- builder: "vite",
20128
- backend: "firebase",
20129
- baseTemplate: "app-vite",
20130
- overlay: "overlay-firebase",
20131
- deployConfig: "firebase",
20132
- functionsTemplate: "functions-firebase"
20133
- },
20134
- {
20135
- builder: "vite",
20136
- backend: "supabase",
20137
- baseTemplate: "app-vite",
20138
- overlay: "overlay-supabase",
20139
- deployConfig: "vercel-supabase",
20140
- functionsTemplate: "functions-supabase"
20141
- },
20142
- {
20143
- builder: "vite",
20144
- backend: "vercel",
20145
- baseTemplate: "app-vite",
20146
- overlay: "overlay-vercel",
20147
- deployConfig: "vercel-vercel",
20148
- functionsTemplate: "functions-vercel"
20149
- },
20150
- {
20151
- builder: "nextjs",
20152
- backend: "none",
20153
- baseTemplate: "app-next",
20154
- overlay: null,
20155
- deployConfig: null,
20156
- functionsTemplate: null
20157
- },
20158
- {
20159
- builder: "nextjs",
20160
- backend: "firebase",
20161
- baseTemplate: "app-next",
20162
- overlay: "overlay-firebase",
20163
- deployConfig: "firebase",
20164
- functionsTemplate: "functions-firebase"
20165
- },
20166
- {
20167
- builder: "nextjs",
20168
- backend: "supabase",
20169
- baseTemplate: "app-next",
20170
- overlay: "overlay-supabase",
20171
- deployConfig: "vercel-supabase",
20172
- functionsTemplate: "functions-supabase"
20173
- },
20174
- {
20175
- builder: "nextjs",
20176
- backend: "vercel",
20177
- baseTemplate: "app-next",
20178
- overlay: "overlay-vercel",
20179
- deployConfig: "vercel-vercel",
20180
- functionsTemplate: "functions-vercel"
20181
- },
20182
- {
20183
- builder: "expo",
20184
- backend: "none",
20185
- baseTemplate: "app-expo",
20186
- overlay: null,
20187
- deployConfig: null,
20188
- functionsTemplate: null
20189
- },
20190
- {
20191
- builder: "expo",
20192
- backend: "firebase",
20193
- baseTemplate: "app-expo",
20194
- overlay: "overlay-firebase",
20195
- deployConfig: null,
20196
- functionsTemplate: "functions-firebase"
20197
- },
20198
- {
20199
- builder: "expo",
20200
- backend: "supabase",
20201
- baseTemplate: "app-expo",
20202
- overlay: "overlay-supabase",
20203
- deployConfig: null,
20204
- functionsTemplate: "functions-supabase"
20205
- },
20206
- {
20207
- builder: "demo",
20208
- backend: "none",
20209
- baseTemplate: "app-demo",
20210
- overlay: null,
20211
- deployConfig: null,
20212
- functionsTemplate: null
20213
- }
20214
- ];
20215
- function comboKey(builder, backend) {
20216
- return `${builder}-${backend}`;
20217
- }
20218
- var ROWS_BY_KEY = /* @__PURE__ */ new Map();
20219
- for (const row of MATRIX) {
20220
- ROWS_BY_KEY.set(comboKey(row.builder, row.backend), row);
20180
+ function resolveDeployConfig(host, backend) {
20181
+ if (host === "none") return null;
20182
+ if (host === "firebase") return "firebase";
20183
+ if (backend === "supabase") return "vercel-supabase";
20184
+ return "vercel-vercel";
20221
20185
  }
20222
- function getScaffoldRow(builder, backend) {
20223
- const key = comboKey(builder, backend);
20224
- const row = ROWS_BY_KEY.get(key);
20225
- if (!row) {
20226
- throw new Error(
20227
- `Unsupported scaffold combo: ${key}. Supported: ${[...ROWS_BY_KEY.keys()].join(", ")}`
20228
- );
20229
- }
20230
- return row;
20186
+ function getScaffoldParts(builder, host, functions, backend) {
20187
+ const baseTemplate = builder === "nextjs" ? "app-next" : builder === "demo" ? "app-demo" : `app-${builder}`;
20188
+ return {
20189
+ builder,
20190
+ backend,
20191
+ baseTemplate,
20192
+ overlay: backend !== "none" ? `overlay-${backend}` : null,
20193
+ deployConfig: resolveDeployConfig(host, backend),
20194
+ functionsTemplate: functions !== "none" ? `functions-${functions}` : null
20195
+ };
20231
20196
  }
20232
20197
 
20233
20198
  // packages/tooling/src/scaffolding/create-app.ts
@@ -20267,11 +20232,15 @@ async function createApp(appName, appConfig, workspaceRoot, templatesRoot) {
20267
20232
  input: askForInput
20268
20233
  });
20269
20234
  const requirements = aggregateRequirements(answers);
20270
- const defaultPlatform = answers.framework === "nextjs" ? "vercel" : "firebase";
20235
+ const framework = answers.framework || "vite";
20236
+ const host2 = answers.host || "none";
20237
+ const functions2 = answers.functions || "none";
20238
+ const backend2 = answers.backend || "none";
20271
20239
  appConfig = {
20272
- template: answers.framework || "vite",
20273
- needsBackend: answers.needsBackend || false,
20274
- backendPlatform: answers.needsBackend ? answers.backendPlatform || defaultPlatform : void 0,
20240
+ template: framework,
20241
+ host: host2,
20242
+ functions: functions2,
20243
+ backend: backend2,
20275
20244
  needsCRUD: true,
20276
20245
  // Always on
20277
20246
  selectedEntities: [],
@@ -20317,12 +20286,14 @@ async function createApp(appName, appConfig, workspaceRoot, templatesRoot) {
20317
20286
  s.start(`Creating app: ${appName}`);
20318
20287
  await ensureDir(appDir);
20319
20288
  const builder = appTemplate;
20320
- const backend = appConfig.needsBackend && appConfig.backendPlatform ? appConfig.backendPlatform : "none";
20321
- const row = getScaffoldRow(builder, backend);
20289
+ const host = appConfig.host ?? "none";
20290
+ const functions = appConfig.functions ?? "none";
20291
+ const backend = appConfig.backend ?? "none";
20292
+ const row = getScaffoldParts(builder, host, functions, backend);
20322
20293
  const templateDir = row.baseTemplate;
20323
20294
  const firebaseProjectId = (appConfig?.firebaseProjectId ?? "").trim() || appName.toLowerCase().replace(/\s+/g, "-");
20324
20295
  const firebaseRegion = appConfig?.firebaseRegion ?? "europe-west1";
20325
- const backendPlatform = appConfig.backendPlatform ?? "firebase";
20296
+ const backendPlatform = backend !== "none" ? backend : "firebase";
20326
20297
  const deployConfig = row.deployConfig;
20327
20298
  const replacements = {
20328
20299
  projectName: appName,
@@ -20660,11 +20631,13 @@ Happy coding!`,
20660
20631
  }
20661
20632
  async function main8(options) {
20662
20633
  try {
20663
- const hasExplicitFlags = options?.builder !== void 0 || options?.functions !== void 0;
20634
+ const hasExplicitFlags = options?.builder !== void 0 || options?.host !== void 0 || options?.functions !== void 0 || options?.backend !== void 0;
20664
20635
  if (hasExplicitFlags && options?.name) {
20665
20636
  const appName = options.name;
20666
20637
  const builder = options.builder || "vite";
20667
- const includeFunctions = options.functions ?? false;
20638
+ const hostOpt = options.host ?? "none";
20639
+ const functionsOpt = options.functions ?? "none";
20640
+ const backendOpt = options.backend ?? "none";
20668
20641
  if (!isValidFileName(appName)) {
20669
20642
  throw new Error(
20670
20643
  `Invalid app name "${appName}". Use only letters, numbers, dashes (-), and underscores (_).`
@@ -20677,8 +20650,9 @@ async function main8(options) {
20677
20650
  }
20678
20651
  const appConfig = {
20679
20652
  template: builder === "next" ? "nextjs" : builder === "expo" ? "expo" : "vite",
20680
- needsBackend: includeFunctions,
20681
- backendPlatform: includeFunctions ? "firebase" : void 0,
20653
+ host: hostOpt,
20654
+ functions: functionsOpt,
20655
+ backend: backendOpt,
20682
20656
  needsCRUD: true,
20683
20657
  selectedEntities: [],
20684
20658
  userAuth: "social",
@@ -20710,12 +20684,11 @@ async function collectAppConfig(appName) {
20710
20684
  input: askForInput
20711
20685
  });
20712
20686
  const framework = answers.framework || "vite";
20713
- const needsBackend = answers.needsBackend || false;
20714
- const defaultPlatform = framework === "nextjs" ? "vercel" : "firebase";
20715
20687
  return {
20716
20688
  template: framework,
20717
- needsBackend,
20718
- backendPlatform: needsBackend ? answers.backendPlatform || defaultPlatform : void 0,
20689
+ host: answers.host || "none",
20690
+ functions: answers.functions || "none",
20691
+ backend: answers.backend || "none",
20719
20692
  needsCRUD: false,
20720
20693
  selectedEntities: [],
20721
20694
  userAuth: "none",
@@ -20862,7 +20835,8 @@ async function main9(options) {
20862
20835
  Me(`Configuring "${trimmedName}"...`, "\u2699\uFE0F");
20863
20836
  const config = await collectAppConfig(trimmedName);
20864
20837
  appConfigs[trimmedName] = config;
20865
- if (config.needsBackend) anyAppNeedsBackend = true;
20838
+ if (config.backend !== "none" || config.functions !== "none")
20839
+ anyAppNeedsBackend = true;
20866
20840
  }
20867
20841
  let installDemoApp = await askForConfirmation(
20868
20842
  "Would you like to install the demo app? (component showcase)",
@@ -20938,8 +20912,9 @@ async function main9(options) {
20938
20912
  log.warn(`Missing config for app "${appName}", using defaults`);
20939
20913
  appConfigs[appName] = {
20940
20914
  template: "vite",
20941
- needsBackend: false,
20942
- backendPlatform: void 0,
20915
+ host: "none",
20916
+ functions: "none",
20917
+ backend: "none",
20943
20918
  needsCRUD: false,
20944
20919
  selectedEntities: [],
20945
20920
  userAuth: "none",
@@ -20987,7 +20962,9 @@ async function main9(options) {
20987
20962
  overwrite: true
20988
20963
  });
20989
20964
  const relativeMonorepoPath = executionMode === "development" ? calculateRelativePath(projectDirNormalized, monorepoRoot) : "";
20990
- const primaryPlatform = Object.values(appConfigs).find((c) => c.backendPlatform)?.backendPlatform ?? "firebase";
20965
+ const primaryPlatform = Object.values(appConfigs).find(
20966
+ (c) => c.backend !== "none"
20967
+ )?.backend ?? "firebase";
20991
20968
  const rootPackageJson = generatePackageJson(
20992
20969
  "consumer-root",
20993
20970
  executionMode,
@@ -21348,13 +21325,16 @@ async function addPathComments(files, rootDir, dryRun, verbose) {
21348
21325
  let useClientLine = -1;
21349
21326
  let useClientValue = "";
21350
21327
  if (!isCss) {
21351
- for (let i = 0; i < Math.min(5, contentLines.length); i++) {
21328
+ for (let i = 0; i < contentLines.length; i++) {
21352
21329
  const line = contentLines[i]?.trim();
21353
21330
  if (line === '"use client";' || line === "'use client';") {
21354
21331
  useClientLine = i;
21355
21332
  useClientValue = line;
21356
21333
  break;
21357
21334
  }
21335
+ if (line?.startsWith("import ") || line?.startsWith("export ") || line?.startsWith("function ") || line?.startsWith("class ") || line?.startsWith("const ") || line?.startsWith("let ") || line?.startsWith("var ")) {
21336
+ break;
21337
+ }
21358
21338
  }
21359
21339
  }
21360
21340
  const invalidFormat = isCss ? COMMENT_FORMATS[".ts"] : null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@donotdev/cli",
3
- "version": "0.0.17",
3
+ "version": "0.0.19",
4
4
  "description": "Command-line interface for DoNotDev Framework",
5
5
  "type": "module",
6
6
  "private": false,