@donotdev/cli 0.0.15 → 0.0.16

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 (70) hide show
  1. package/dependencies-matrix.json +36 -20
  2. package/dist/bin/commands/build.js +69 -52
  3. package/dist/bin/commands/bump.js +7 -13
  4. package/dist/bin/commands/create-app.js +77 -29
  5. package/dist/bin/commands/create-project.js +109 -135
  6. package/dist/bin/commands/deploy.js +97 -45
  7. package/dist/bin/commands/dev.js +43 -24
  8. package/dist/bin/commands/doctor.d.ts +6 -0
  9. package/dist/bin/commands/doctor.d.ts.map +1 -0
  10. package/dist/bin/commands/{lint.js → doctor.js} +1178 -147
  11. package/dist/bin/commands/doctor.js.map +1 -0
  12. package/dist/bin/commands/emu.js +297 -107
  13. package/dist/bin/commands/make-admin.js +77499 -11
  14. package/dist/bin/commands/preview.js +44 -25
  15. package/dist/bin/commands/setup.d.ts +6 -0
  16. package/dist/bin/commands/setup.d.ts.map +1 -0
  17. package/dist/bin/commands/setup.js +11733 -0
  18. package/dist/bin/commands/setup.js.map +1 -0
  19. package/dist/bin/commands/type-check.js +2018 -283
  20. package/dist/bin/dndev.js +54 -58
  21. package/dist/bin/donotdev.js +28 -44
  22. package/dist/index.js +633 -416
  23. package/package.json +2 -2
  24. package/templates/app-expo/.env.example +2 -22
  25. package/templates/app-expo/README.md.example +1 -1
  26. package/templates/app-expo/assets/adaptive-icon.png +0 -0
  27. package/templates/app-expo/assets/favicon.png +0 -0
  28. package/templates/app-expo/assets/icon.png +0 -0
  29. package/templates/app-expo/assets/splash.png +0 -0
  30. package/templates/app-expo/src/config/app.ts.example +46 -0
  31. package/templates/app-expo/src/config/providers.ts.example +7 -0
  32. package/templates/app-next/src/config/providers.ts.example +7 -0
  33. package/templates/app-vite/src/config/providers.ts.example +7 -0
  34. package/templates/app-vite/src/pages/HomePage.tsx.example +1 -1
  35. package/templates/functions-firebase/README.md.example +1 -1
  36. package/templates/functions-firebase/functions-firebase/.env.example.example +1 -1
  37. package/templates/functions-firebase/functions-firebase/README.md.example +1 -1
  38. package/templates/functions-firebase/functions-firebase/tsconfig.json.example +1 -1
  39. package/templates/functions-firebase/functions.config.js.example +1 -1
  40. package/templates/functions-supabase/supabase/config.toml.example +59 -0
  41. package/templates/functions-supabase/supabase/functions/.env.example +13 -0
  42. package/templates/functions-supabase/supabase/functions/deno.json.example +8 -0
  43. package/templates/overlay-firebase/env.fragment.example +1 -1
  44. package/templates/overlay-firebase/env.fragment.expo.example +1 -1
  45. package/templates/overlay-firebase/env.fragment.nextjs.example +1 -1
  46. package/templates/overlay-supabase/env.fragment.example +8 -3
  47. package/templates/overlay-supabase/env.fragment.expo.example +8 -3
  48. package/templates/overlay-supabase/env.fragment.nextjs.example +8 -3
  49. package/templates/overlay-vercel/env.fragment.example +1 -1
  50. package/templates/overlay-vercel/env.fragment.nextjs.example +1 -1
  51. package/templates/root-consumer/AI.md.example +15 -0
  52. package/templates/root-consumer/guides/dndev/AGENT_START_HERE.md.example +2 -2
  53. package/templates/root-consumer/guides/dndev/ENV_SETUP.md.example +6 -6
  54. package/templates/root-consumer/guides/dndev/INDEX.md.example +2 -2
  55. package/templates/root-consumer/guides/dndev/SETUP_APP_CONFIG.md.example +3 -3
  56. package/templates/root-consumer/guides/dndev/SETUP_CRUD.md.example +98 -0
  57. package/templates/root-consumer/guides/dndev/SETUP_FIREBASE.md.example +4 -4
  58. package/templates/root-consumer/guides/dndev/SETUP_OAUTH_PROVIDERS.md.example +60 -0
  59. package/templates/root-consumer/guides/dndev/SETUP_STRIPE.md.example +62 -0
  60. package/templates/root-consumer/guides/dndev/SETUP_SUPABASE.md.example +3 -3
  61. package/templates/root-consumer/guides/dndev/SETUP_VERCEL.md.example +2 -2
  62. package/templates/root-consumer/guides/wai-way/WAI_WAY_CLI.md.example +7 -8
  63. package/templates/root-consumer/guides/wai-way/blueprints/1_scaffold.md.example +9 -5
  64. package/dist/bin/commands/lint.d.ts +0 -11
  65. package/dist/bin/commands/lint.d.ts.map +0 -1
  66. package/dist/bin/commands/lint.js.map +0 -1
  67. package/dist/bin/commands/staging.d.ts +0 -11
  68. package/dist/bin/commands/staging.d.ts.map +0 -1
  69. package/dist/bin/commands/staging.js +0 -12
  70. package/dist/bin/commands/staging.js.map +0 -1
@@ -8713,15 +8713,10 @@ function getMatrixPath(mode) {
8713
8713
  }
8714
8714
  const executionMode = mode || detectExecutionMode();
8715
8715
  if (executionMode === "development") {
8716
- const repoRoot = getRepoRoot();
8717
- if (repoRoot) {
8718
- const devPath = normalizePath(
8719
- repoRoot,
8720
- "packages/cli/dependencies-matrix.json"
8721
- );
8722
- if (pathExists(devPath)) {
8723
- return devPath;
8724
- }
8716
+ const templatesRoot = getTemplatesRoot();
8717
+ const devPath = normalizePath(templatesRoot, "..", "dependencies-matrix.json");
8718
+ if (pathExists(devPath)) {
8719
+ return devPath;
8725
8720
  }
8726
8721
  }
8727
8722
  return null;
@@ -8736,8 +8731,8 @@ function getCliVersion(mode) {
8736
8731
  }
8737
8732
  const executionMode = mode || detectExecutionMode();
8738
8733
  if (executionMode === "development") {
8739
- const repoRoot = getRepoRoot();
8740
- const cliPackageJson = joinPath(repoRoot, "packages/cli/package.json");
8734
+ const templatesRoot = getTemplatesRoot();
8735
+ const cliPackageJson = normalizePath(templatesRoot, "..", "package.json");
8741
8736
  if (pathExists(cliPackageJson)) {
8742
8737
  const pkg = readSync(cliPackageJson, { format: "json" });
8743
8738
  return String(pkg?.version || "0.0.0");
@@ -9026,7 +9021,7 @@ function generatePackageJson(templateName, mode, options = {}) {
9026
9021
  }
9027
9022
  if (templateName.includes("functions")) {
9028
9023
  result.main = "lib/index.js";
9029
- result.engines = { node: "20" };
9024
+ result.engines = { node: "22" };
9030
9025
  if (options.appName) {
9031
9026
  const platform = templateName.includes("vercel") ? "Vercel" : "Firebase";
9032
9027
  result.description = `${options.appName} ${platform} Functions`;
@@ -9073,15 +9068,15 @@ init_utils();
9073
9068
  var MATRIX = [
9074
9069
  { builder: "vite", backend: "none", baseTemplate: "app-vite", overlay: null, deployConfig: null, functionsTemplate: null },
9075
9070
  { builder: "vite", backend: "firebase", baseTemplate: "app-vite", overlay: "overlay-firebase", deployConfig: "firebase", functionsTemplate: "functions-firebase" },
9076
- { builder: "vite", backend: "supabase", baseTemplate: "app-vite", overlay: "overlay-supabase", deployConfig: "vercel-supabase", functionsTemplate: null },
9071
+ { builder: "vite", backend: "supabase", baseTemplate: "app-vite", overlay: "overlay-supabase", deployConfig: "vercel-supabase", functionsTemplate: "functions-supabase" },
9077
9072
  { builder: "vite", backend: "vercel", baseTemplate: "app-vite", overlay: "overlay-vercel", deployConfig: "vercel-vercel", functionsTemplate: "functions-vercel" },
9078
9073
  { builder: "nextjs", backend: "none", baseTemplate: "app-next", overlay: null, deployConfig: null, functionsTemplate: null },
9079
9074
  { builder: "nextjs", backend: "firebase", baseTemplate: "app-next", overlay: "overlay-firebase", deployConfig: "firebase", functionsTemplate: "functions-firebase" },
9080
- { builder: "nextjs", backend: "supabase", baseTemplate: "app-next", overlay: "overlay-supabase", deployConfig: "vercel-supabase", functionsTemplate: null },
9075
+ { builder: "nextjs", backend: "supabase", baseTemplate: "app-next", overlay: "overlay-supabase", deployConfig: "vercel-supabase", functionsTemplate: "functions-supabase" },
9081
9076
  { builder: "nextjs", backend: "vercel", baseTemplate: "app-next", overlay: "overlay-vercel", deployConfig: "vercel-vercel", functionsTemplate: "functions-vercel" },
9082
9077
  { builder: "expo", backend: "none", baseTemplate: "app-expo", overlay: null, deployConfig: null, functionsTemplate: null },
9083
9078
  { builder: "expo", backend: "firebase", baseTemplate: "app-expo", overlay: "overlay-firebase", deployConfig: null, functionsTemplate: "functions-firebase" },
9084
- { builder: "expo", backend: "supabase", baseTemplate: "app-expo", overlay: "overlay-supabase", deployConfig: null, functionsTemplate: null },
9079
+ { builder: "expo", backend: "supabase", baseTemplate: "app-expo", overlay: "overlay-supabase", deployConfig: null, functionsTemplate: "functions-supabase" },
9085
9080
  { builder: "demo", backend: "none", baseTemplate: "app-demo", overlay: null, deployConfig: null, functionsTemplate: null }
9086
9081
  ];
9087
9082
  function comboKey(builder, backend) {
@@ -9256,7 +9251,7 @@ async function createApp(appName, appConfig, workspaceRoot, templatesRoot) {
9256
9251
  if (providersVariant[1] !== appTemplate) continue;
9257
9252
  const destPath2 = joinPath(appDir, "src/config/providers.ts");
9258
9253
  await ensureDir(getDirname(destPath2));
9259
- await copy(joinPath(overlayDir, file), destPath2);
9254
+ await copy(joinPath(overlayDir, file), destPath2, { overwrite: true });
9260
9255
  if (await isTextFile(destPath2)) await replacePlaceholders(destPath2, replacements);
9261
9256
  continue;
9262
9257
  }
@@ -9267,7 +9262,7 @@ async function createApp(appName, appConfig, workspaceRoot, templatesRoot) {
9267
9262
  }
9268
9263
  const destPath = joinPath(appDir, destFileName);
9269
9264
  await ensureDir(getDirname(destPath));
9270
- await copy(sourcePath, destPath);
9265
+ await copy(sourcePath, destPath, { overwrite: true });
9271
9266
  if (await isTextFile(destPath)) {
9272
9267
  await replacePlaceholders(destPath, replacements);
9273
9268
  }
@@ -9310,23 +9305,26 @@ async function createApp(appName, appConfig, workspaceRoot, templatesRoot) {
9310
9305
  overwrite: true
9311
9306
  });
9312
9307
  if (row.functionsTemplate) {
9313
- const functionsRootDir = joinPath(appDir, "functions");
9314
9308
  const functionsTemplateName = row.functionsTemplate;
9315
9309
  const functionsTemplateExists = pathExists(joinPath(templatesRoot, functionsTemplateName));
9316
9310
  if (!functionsTemplateExists) {
9317
9311
  log.warn(`Functions template "${functionsTemplateName}" not found \u2014 skipping functions scaffolding.`);
9318
9312
  } else {
9319
- const functionsPackageJson = generatePackageJson(
9320
- functionsTemplateName,
9321
- executionMode,
9322
- { appName, platform: row.functionsTemplate.replace("functions-", "") }
9323
- );
9324
- const packageJsonPath2 = joinPath(functionsRootDir, "package.json");
9325
- await ensureDir(functionsRootDir);
9326
- await write(packageJsonPath2, functionsPackageJson, {
9327
- format: "json",
9328
- overwrite: true
9329
- });
9313
+ const isSupabaseFunctions = functionsTemplateName === "functions-supabase";
9314
+ const functionsRootDir = isSupabaseFunctions ? appDir : joinPath(appDir, "functions");
9315
+ if (!isSupabaseFunctions) {
9316
+ const functionsPackageJson = generatePackageJson(
9317
+ functionsTemplateName,
9318
+ executionMode,
9319
+ { appName, platform: row.functionsTemplate.replace("functions-", "") }
9320
+ );
9321
+ const packageJsonPath2 = joinPath(functionsRootDir, "package.json");
9322
+ await ensureDir(functionsRootDir);
9323
+ await write(packageJsonPath2, functionsPackageJson, {
9324
+ format: "json",
9325
+ overwrite: true
9326
+ });
9327
+ }
9330
9328
  const templateDir2 = joinPath(templatesRoot, functionsTemplateName);
9331
9329
  const templateFiles2 = await glob("**/*", {
9332
9330
  cwd: templateDir2,
@@ -9359,6 +9357,18 @@ async function createApp(appName, appConfig, workspaceRoot, templatesRoot) {
9359
9357
  await copy(firebaseJsonSource, joinPath(appDir, "firebase.json"));
9360
9358
  const firebaseJsonDest = joinPath(appDir, "firebase.json");
9361
9359
  if (await isTextFile(firebaseJsonDest)) await replacePlaceholders(firebaseJsonDest, replacements);
9360
+ if (appTemplate === "nextjs") {
9361
+ const firebaseJson = readSync(firebaseJsonDest, { format: "json" });
9362
+ if (firebaseJson.hosting?.rewrites) {
9363
+ firebaseJson.hosting.rewrites = firebaseJson.hosting.rewrites.filter(
9364
+ (r2) => r2.destination !== "/index.html"
9365
+ );
9366
+ }
9367
+ if (firebaseJson.hosting) {
9368
+ firebaseJson.hosting.public = "out";
9369
+ }
9370
+ await write(firebaseJsonDest, firebaseJson, { format: "json", overwrite: true });
9371
+ }
9362
9372
  }
9363
9373
  const firebasercSource = joinPath(deploymentTemplateDir, ".firebaserc.example");
9364
9374
  if (pathExists(firebasercSource)) {
@@ -9375,6 +9385,44 @@ async function createApp(appName, appConfig, workspaceRoot, templatesRoot) {
9375
9385
  }
9376
9386
  }
9377
9387
  }
9388
+ if (!deployConfig && backend === "firebase" && row.functionsTemplate) {
9389
+ const firebaseJsonPath = joinPath(appDir, "firebase.json");
9390
+ if (!pathExists(firebaseJsonPath)) {
9391
+ const expoFirebaseJson = {
9392
+ functions: [
9393
+ {
9394
+ source: "functions",
9395
+ codebase: "default",
9396
+ ignore: ["node_modules", ".git", "firebase-debug.log", "firebase-debug.*.log", "**/.*", "**/*.test.ts", "**/__tests__/**"],
9397
+ runtime: "nodejs22"
9398
+ }
9399
+ ],
9400
+ firestore: { rules: "firestore.rules", indexes: "firestore.indexes.json" },
9401
+ storage: { rules: "storage.rules" },
9402
+ emulators: {
9403
+ auth: { port: 9099 },
9404
+ functions: { port: 5001 },
9405
+ firestore: { port: 8080 },
9406
+ storage: { port: 9199 },
9407
+ ui: { enabled: true, port: 4e3 }
9408
+ }
9409
+ };
9410
+ await write(firebaseJsonPath, expoFirebaseJson, { format: "json", overwrite: true });
9411
+ }
9412
+ const firebasercSource = joinPath(deploymentTemplateDir, ".firebaserc.example");
9413
+ const firebasercDest = joinPath(appDir, ".firebaserc");
9414
+ if (pathExists(firebasercSource) && !pathExists(firebasercDest)) {
9415
+ await copy(firebasercSource, firebasercDest);
9416
+ if (await isTextFile(firebasercDest)) await replacePlaceholders(firebasercDest, replacements);
9417
+ }
9418
+ for (const example of ["firestore.rules.example", "firestore.indexes.json.example", "storage.rules.example"]) {
9419
+ const src = joinPath(deploymentTemplateDir, example);
9420
+ const dest = joinPath(appDir, example.replace(".example", ""));
9421
+ if (pathExists(src) && !pathExists(dest)) {
9422
+ await copy(src, dest);
9423
+ }
9424
+ }
9425
+ }
9378
9426
  if (deployConfig === "vercel-vercel") {
9379
9427
  const vercelJsonSource = joinPath(deploymentTemplateDir, "vercel.json.example");
9380
9428
  if (pathExists(vercelJsonSource)) {
@@ -9417,23 +9465,25 @@ init_cli_input();
9417
9465
  init_cli_output();
9418
9466
  init_pathResolver();
9419
9467
  var SHOW_WIP2 = process.env.SHOW_WIP === "true" || process.argv.includes("--wip");
9420
- var BACKEND_CHOICES = [
9421
- { title: "None", value: "none" },
9422
- {
9423
- title: "Firebase \u2014 Full platform (Auth, Firestore, Storage, Functions, Hosting)",
9424
- value: "firebase"
9425
- },
9426
- {
9427
- title: "Supabase \u2014 Auth, Postgres, Storage, Functions",
9428
- value: "supabase"
9429
- },
9430
- {
9431
- title: "Vercel \u2014 Serverless functions + Hosting (e.g. Next.js API routes)",
9432
- value: "vercel"
9433
- }
9434
- ];
9435
- function getDefaultBackendIndex(framework) {
9436
- return framework === "nextjs" ? 3 : 1;
9468
+ async function collectAppConfig(appName) {
9469
+ const answers = await runQuestionnaire(APP_QUESTIONNAIRE, {}, SHOW_WIP2, {
9470
+ selection: askForSelection,
9471
+ confirmation: askForConfirmation,
9472
+ input: askForInput
9473
+ });
9474
+ const framework = answers.framework || "vite";
9475
+ const needsBackend = answers.needsBackend || false;
9476
+ const defaultPlatform = framework === "nextjs" ? "vercel" : "firebase";
9477
+ return {
9478
+ template: framework,
9479
+ needsBackend,
9480
+ backendPlatform: needsBackend ? answers.backendPlatform || defaultPlatform : void 0,
9481
+ needsCRUD: false,
9482
+ selectedEntities: [],
9483
+ userAuth: "none",
9484
+ billing: false,
9485
+ features: []
9486
+ };
9437
9487
  }
9438
9488
  function calculateRelativePath(from, to) {
9439
9489
  try {
@@ -9546,71 +9596,22 @@ async function main(options) {
9546
9596
  let appNames = [];
9547
9597
  const appConfigs = {};
9548
9598
  let anyAppNeedsBackend = false;
9549
- const firstAppName = await askForInput(
9550
- "What's your first app name? (press Enter to skip)",
9551
- ""
9552
- );
9553
- if (firstAppName && firstAppName.trim() !== "") {
9554
- const trimmedName = firstAppName.trim();
9555
- if (isReservedAppName(trimmedName)) {
9556
- log.warn(`'${trimmedName}' is reserved for framework demos.`);
9557
- } else if (!isValidFileName(trimmedName)) {
9558
- log.warn(
9559
- `Invalid app name. Use only letters, numbers, dashes (-), and underscores (_).`
9560
- );
9561
- } else {
9562
- appNames.push(trimmedName);
9563
- const framework = await askForSelection(
9564
- `Builder for "${trimmedName}"?`,
9565
- [
9566
- {
9567
- title: "Vite \u2014 SPA/SaaS (client-side rendering, fast dev)",
9568
- value: "vite"
9569
- },
9570
- {
9571
- title: "Next.js \u2014 Static content/SEO (SSR, SSG) \u2014 DoNotDev support: BETA",
9572
- value: "nextjs"
9573
- },
9574
- {
9575
- title: "Expo \u2014 Mobile app (iOS + Android, single codebase)",
9576
- value: "expo"
9577
- }
9578
- ],
9579
- 0
9580
- );
9581
- const backendValue = await askForSelection(
9582
- `Backend for "${trimmedName}"?`,
9583
- [...BACKEND_CHOICES],
9584
- getDefaultBackendIndex(framework)
9585
- );
9586
- const needsBackend = backendValue !== "none";
9587
- if (needsBackend) anyAppNeedsBackend = true;
9588
- appConfigs[trimmedName] = {
9589
- template: framework,
9590
- needsBackend,
9591
- backendPlatform: needsBackend ? backendValue : void 0,
9592
- needsCRUD: false,
9593
- selectedEntities: [],
9594
- userAuth: "none",
9595
- billing: false,
9596
- features: []
9597
- };
9598
- }
9599
- }
9600
- while (appNames.length > 0) {
9601
- const appName = await askForInput("App name (press Enter to finish)", "");
9602
- if (!appName || appName.trim() === "") {
9599
+ let isFirstApp = true;
9600
+ while (true) {
9601
+ const prompt = isFirstApp ? "What's your first app name? (press Enter to skip)" : "App name (press Enter to finish)";
9602
+ const appNameInput = await askForInput(prompt, "");
9603
+ if (!appNameInput || appNameInput.trim() === "") {
9604
+ if (isFirstApp) break;
9603
9605
  break;
9604
9606
  }
9605
- const trimmedName = appName.trim();
9607
+ const trimmedName = appNameInput.trim();
9608
+ isFirstApp = false;
9606
9609
  if (appNames.includes(trimmedName)) {
9607
9610
  log.warn(`'${trimmedName}' already exists. Choose a different name.`);
9608
9611
  continue;
9609
9612
  }
9610
9613
  if (isReservedAppName(trimmedName)) {
9611
- log.warn(
9612
- `'${trimmedName}' is reserved for framework demos. Choose a different name.`
9613
- );
9614
+ log.warn(`'${trimmedName}' is reserved for framework demos.`);
9614
9615
  continue;
9615
9616
  }
9616
9617
  if (!isValidFileName(trimmedName)) {
@@ -9620,37 +9621,10 @@ async function main(options) {
9620
9621
  continue;
9621
9622
  }
9622
9623
  appNames.push(trimmedName);
9623
- const framework = await askForSelection(
9624
- `Builder for "${trimmedName}"?`,
9625
- [
9626
- {
9627
- title: "Vite \u2014 SPA/SaaS (client-side rendering, fast dev)",
9628
- value: "vite"
9629
- },
9630
- {
9631
- title: "Next.js \u2014 Static content/SEO (SSR, SSG) \u2014 DoNotDev support: BETA",
9632
- value: "nextjs"
9633
- }
9634
- ],
9635
- 0
9636
- );
9637
- const backendValue = await askForSelection(
9638
- `Backend for "${trimmedName}"?`,
9639
- [...BACKEND_CHOICES],
9640
- getDefaultBackendIndex(framework)
9641
- );
9642
- const needsBackend = backendValue !== "none";
9643
- if (needsBackend) anyAppNeedsBackend = true;
9644
- appConfigs[trimmedName] = {
9645
- template: framework,
9646
- needsBackend,
9647
- backendPlatform: needsBackend ? backendValue : void 0,
9648
- needsCRUD: false,
9649
- selectedEntities: [],
9650
- userAuth: "none",
9651
- billing: false,
9652
- features: []
9653
- };
9624
+ Me(`Configuring "${trimmedName}"...`, "\u2699\uFE0F");
9625
+ const config = await collectAppConfig(trimmedName);
9626
+ appConfigs[trimmedName] = config;
9627
+ if (config.needsBackend) anyAppNeedsBackend = true;
9654
9628
  }
9655
9629
  let installDemoApp = await askForConfirmation(
9656
9630
  "Would you like to install the demo app? (component showcase)",
@@ -8194,15 +8194,15 @@ function getCLIInstallInstructions(tool) {
8194
8194
  },
8195
8195
  [CLI_TOOLS.SUPABASE]: {
8196
8196
  win32: [
8197
- "npm install -g supabase",
8197
+ "scoop install supabase",
8198
+ "Or: winget install Supabase.CLI",
8198
8199
  "Or download from: https://github.com/supabase/cli/releases"
8199
8200
  ],
8200
8201
  darwin: [
8201
- "brew install supabase/tap/supabase",
8202
- "Or: npm install -g supabase"
8202
+ "brew install supabase/tap/supabase"
8203
8203
  ],
8204
8204
  linux: [
8205
- "npm install -g supabase",
8205
+ "brew install supabase/tap/supabase",
8206
8206
  "Or see: https://supabase.com/docs/guides/cli"
8207
8207
  ]
8208
8208
  },
@@ -8329,6 +8329,40 @@ var init_cli_tools = __esm({
8329
8329
  }
8330
8330
  });
8331
8331
 
8332
+ // packages/tooling/src/cli/setup/vercel-token.ts
8333
+ function readEnvVar(filePath, varName) {
8334
+ if (!pathExists(filePath)) return null;
8335
+ const content = readSync(filePath, { format: "text" });
8336
+ if (typeof content !== "string") return null;
8337
+ for (const line of content.split(/\r?\n/)) {
8338
+ const trimmed = line.trim();
8339
+ if (!trimmed || trimmed.startsWith("#")) continue;
8340
+ if (trimmed.startsWith(`${varName}=`)) {
8341
+ const val = trimmed.substring(`${varName}=`.length).trim();
8342
+ if (val.startsWith('"') && val.endsWith('"') || val.startsWith("'") && val.endsWith("'")) {
8343
+ return val.slice(1, -1);
8344
+ }
8345
+ return val || null;
8346
+ }
8347
+ }
8348
+ return null;
8349
+ }
8350
+ function resolveVercelToken(appDir) {
8351
+ if (process.env.VERCEL_TOKEN) return process.env.VERCEL_TOKEN;
8352
+ const fromEnv = readEnvVar(joinPath(appDir, ".env"), "VERCEL_TOKEN");
8353
+ if (fromEnv) return fromEnv;
8354
+ const fromLocal = readEnvVar(joinPath(appDir, ".env.local"), "VERCEL_TOKEN");
8355
+ if (fromLocal) return fromLocal;
8356
+ return null;
8357
+ }
8358
+ var init_vercel_token = __esm({
8359
+ "packages/tooling/src/cli/setup/vercel-token.ts"() {
8360
+ "use strict";
8361
+ init_utils();
8362
+ init_pathResolver();
8363
+ }
8364
+ });
8365
+
8332
8366
  // node_modules/.bun/yaml@2.8.2/node_modules/yaml/dist/nodes/identity.js
8333
8367
  var require_identity = __commonJS({
8334
8368
  "node_modules/.bun/yaml@2.8.2/node_modules/yaml/dist/nodes/identity.js"(exports) {
@@ -15690,13 +15724,36 @@ var require_dist = __commonJS({
15690
15724
  }
15691
15725
  });
15692
15726
 
15727
+ // packages/tooling/src/utils/error-handling.ts
15728
+ function isError(error2) {
15729
+ return error2 instanceof Error;
15730
+ }
15731
+ function getErrorMessage(error2) {
15732
+ if (isError(error2)) {
15733
+ return error2.message;
15734
+ }
15735
+ if (typeof error2 === "string") {
15736
+ return error2;
15737
+ }
15738
+ if (error2 && typeof error2 === "object" && "message" in error2) {
15739
+ return String(error2.message);
15740
+ }
15741
+ return String(error2);
15742
+ }
15743
+ var init_error_handling = __esm({
15744
+ "packages/tooling/src/utils/error-handling.ts"() {
15745
+ "use strict";
15746
+ init_utils();
15747
+ }
15748
+ });
15749
+
15693
15750
  // packages/tooling/src/apps/sync-secrets.ts
15694
15751
  var sync_secrets_exports = {};
15695
15752
  __export(sync_secrets_exports, {
15696
15753
  default: () => sync_secrets_default,
15697
15754
  main: () => main
15698
15755
  });
15699
- import { spawnSync as spawnSync5 } from "node:child_process";
15756
+ import { spawnSync as spawnSync6 } from "node:child_process";
15700
15757
  function parseEnvFile(filePath) {
15701
15758
  if (!pathExists(filePath)) {
15702
15759
  throw new DoNotDevError(
@@ -15889,7 +15946,7 @@ async function setFirebaseSecret(key, value, projectId, dryRun = false, cwd) {
15889
15946
  NODE_OPTIONS: ""
15890
15947
  // Clear to avoid conflicts
15891
15948
  };
15892
- const result = spawnSync5(firebaseCmd, args, {
15949
+ const result = spawnSync6(firebaseCmd, args, {
15893
15950
  input: value,
15894
15951
  encoding: "utf8",
15895
15952
  stdio: ["pipe", "pipe", "pipe"],
@@ -15985,7 +16042,7 @@ function setVercelSecret(key, value, projectId, dryRun = false) {
15985
16042
  if (projectId) {
15986
16043
  args.push("--project", projectId);
15987
16044
  }
15988
- const result = spawnSync5("vercel", args, {
16045
+ const result = spawnSync6("vercel", args, {
15989
16046
  input: value,
15990
16047
  encoding: "utf8",
15991
16048
  stdio: ["pipe", "inherit", "inherit"]
@@ -16014,7 +16071,7 @@ function setVercelSecret(key, value, projectId, dryRun = false) {
16014
16071
  }
16015
16072
  function detectGitHubRepo() {
16016
16073
  try {
16017
- const result = spawnSync5("git", ["remote", "get-url", "origin"], {
16074
+ const result = spawnSync6("git", ["remote", "get-url", "origin"], {
16018
16075
  encoding: "utf8",
16019
16076
  stdio: ["pipe", "pipe", "pipe"]
16020
16077
  });
@@ -16042,7 +16099,7 @@ function setGitHubSecret(key, value, repo, dryRun = false) {
16042
16099
  if (repo) {
16043
16100
  args.push("--repo", repo);
16044
16101
  }
16045
- const result = spawnSync5("gh", args, {
16102
+ const result = spawnSync6("gh", args, {
16046
16103
  input: value,
16047
16104
  encoding: "utf8",
16048
16105
  stdio: ["pipe", "pipe", "pipe"]
@@ -16294,7 +16351,7 @@ var deploy_supabase_functions_exports = {};
16294
16351
  __export(deploy_supabase_functions_exports, {
16295
16352
  deploySupabaseFunctions: () => deploySupabaseFunctions
16296
16353
  });
16297
- import { execSync as execSync4 } from "node:child_process";
16354
+ import { execSync as execSync3 } from "node:child_process";
16298
16355
  async function deploySupabaseFunctions(appDir, config) {
16299
16356
  const supabaseDir = joinPath(appDir, "supabase");
16300
16357
  const functionsDir = joinPath(supabaseDir, "functions");
@@ -16323,7 +16380,7 @@ async function deploySupabaseFunctions(appDir, config) {
16323
16380
  for (const functionName of functionDirs) {
16324
16381
  s.start(`Deploying Edge Function: ${functionName}...`);
16325
16382
  try {
16326
- execSync4(`supabase functions deploy ${functionName}`, {
16383
+ execSync3(`supabase functions deploy ${functionName}`, {
16327
16384
  cwd: supabaseDir,
16328
16385
  stdio: config.verbose ? "inherit" : "pipe",
16329
16386
  env: {
@@ -16484,7 +16541,7 @@ function safeRemove(path, options = {}) {
16484
16541
 
16485
16542
  // packages/tooling/src/apps/deploy.ts
16486
16543
  init_utils();
16487
- import { execSync as execSync5 } from "node:child_process";
16544
+ import { execSync as execSync4 } from "node:child_process";
16488
16545
 
16489
16546
  // packages/tooling/src/apps/deploy-frontend.ts
16490
16547
  init_utils();
@@ -16515,15 +16572,31 @@ async function deployFrontend(appDir, serviceAccountPath, projectId, config) {
16515
16572
 
16516
16573
  // packages/tooling/src/apps/deploy-vercel-frontend.ts
16517
16574
  init_utils();
16518
- import { execSync as execSync2 } from "node:child_process";
16575
+ init_cli_output();
16576
+ init_vercel_token();
16577
+ import { spawnSync as spawnSync3 } from "node:child_process";
16519
16578
  async function deployVercelFrontend(appDir, _config) {
16520
16579
  const s = Y2();
16521
16580
  s.start("Deploying frontend to Vercel...");
16581
+ const token = resolveVercelToken(appDir);
16582
+ if (token) {
16583
+ log.debug("Using VERCEL_TOKEN from .env (token-based auth)");
16584
+ }
16585
+ const args = ["vercel", "--prod", "--yes"];
16586
+ if (token) {
16587
+ args.push("--token", token);
16588
+ }
16522
16589
  try {
16523
- execSync2("npx vercel --prod --yes", {
16590
+ const result = spawnSync3("bunx", args, {
16524
16591
  cwd: appDir,
16525
- stdio: "inherit"
16592
+ stdio: "pipe",
16593
+ encoding: "utf-8"
16526
16594
  });
16595
+ if (result.status !== 0) {
16596
+ s.stop("Vercel deployment failed");
16597
+ const errOutput = result.stderr?.trim();
16598
+ throw new Error(errOutput || `Vercel deploy exited with code ${result.status}`);
16599
+ }
16527
16600
  s.stop("Frontend deployed to Vercel");
16528
16601
  } catch (err) {
16529
16602
  s.stop("Vercel deployment failed");
@@ -16534,7 +16607,7 @@ async function deployVercelFrontend(appDir, _config) {
16534
16607
  // packages/tooling/src/apps/deploy-functions.ts
16535
16608
  init_utils();
16536
16609
  var import_yaml = __toESM(require_dist(), 1);
16537
- import { execSync as execSync3, spawnSync as spawnSync3 } from "node:child_process";
16610
+ import { execSync as execSync2, spawnSync as spawnSync4 } from "node:child_process";
16538
16611
  init_pathResolver();
16539
16612
  init_cli_tools();
16540
16613
  init_typed_file_operations();
@@ -16703,7 +16776,7 @@ function updateCloudRunIAM(functionNames, projectId, region, serviceAccountPath,
16703
16776
  let failCount = 0;
16704
16777
  for (const funcName of functionNames) {
16705
16778
  try {
16706
- const result = spawnSync3(
16779
+ const result = spawnSync4(
16707
16780
  "gcloud",
16708
16781
  [
16709
16782
  "run",
@@ -16821,7 +16894,7 @@ async function autoSyncSecrets(functionsDir, projectId, config) {
16821
16894
  let failCount = 0;
16822
16895
  for (const { key, value } of secrets) {
16823
16896
  try {
16824
- const result = spawnSync3(
16897
+ const result = spawnSync4(
16825
16898
  firebaseCmd,
16826
16899
  ["functions:secrets:set", key, "--project", projectId],
16827
16900
  {
@@ -16903,7 +16976,7 @@ To fix this, run:
16903
16976
  const s2 = Y2();
16904
16977
  s2.start("Building functions...");
16905
16978
  try {
16906
- execSync3("bun run build", {
16979
+ execSync2("bun run build", {
16907
16980
  cwd: functionsDir,
16908
16981
  stdio: config.verbose ? "inherit" : "pipe"
16909
16982
  });
@@ -17003,29 +17076,10 @@ async function deployRules(appDir, serviceAccountPath, projectId, config, option
17003
17076
 
17004
17077
  // packages/tooling/src/apps/deploy-utils.ts
17005
17078
  init_utils();
17006
- import { spawnSync as spawnSync4 } from "node:child_process";
17079
+ import { spawnSync as spawnSync5 } from "node:child_process";
17007
17080
  init_pathResolver();
17008
17081
  init_typed_file_operations();
17009
-
17010
- // packages/tooling/src/utils/error-handling.ts
17011
- init_utils();
17012
- function isError(error2) {
17013
- return error2 instanceof Error;
17014
- }
17015
- function getErrorMessage(error2) {
17016
- if (isError(error2)) {
17017
- return error2.message;
17018
- }
17019
- if (typeof error2 === "string") {
17020
- return error2;
17021
- }
17022
- if (error2 && typeof error2 === "object" && "message" in error2) {
17023
- return String(error2.message);
17024
- }
17025
- return String(error2);
17026
- }
17027
-
17028
- // packages/tooling/src/apps/deploy-utils.ts
17082
+ init_error_handling();
17029
17083
  function detectAvailableApps() {
17030
17084
  const currentDir = process.cwd();
17031
17085
  const appsDir = joinPath(currentDir, "apps");
@@ -17210,7 +17264,7 @@ How to fix:
17210
17264
  if (shouldOpen) {
17211
17265
  try {
17212
17266
  const openCommand = process.platform === "win32" ? "start" : process.platform === "darwin" ? "open" : "xdg-open";
17213
- spawnSync4(openCommand, [consoleUrl], { shell: true });
17267
+ spawnSync5(openCommand, [consoleUrl], { shell: true });
17214
17268
  log.success("Opening Firebase Console...");
17215
17269
  } catch {
17216
17270
  log.warn("Could not open browser. Please open the URL manually.");
@@ -17281,7 +17335,7 @@ function detectProvider(appDir) {
17281
17335
  if (hasFirebase) {
17282
17336
  try {
17283
17337
  const config = readSync(firebaseJsonPath, { format: "json" });
17284
- if (config && typeof config === "object" && "projectId" in config) {
17338
+ if (config && typeof config === "object") {
17285
17339
  const firebaseConfigObj = config;
17286
17340
  firebaseConfig = {
17287
17341
  projectId: firebaseConfigObj.projectId,
@@ -17290,8 +17344,6 @@ function detectProvider(appDir) {
17290
17344
  hasFirestoreRules: !!firebaseConfigObj.firestore?.rules,
17291
17345
  hasStorageRules: !!firebaseConfigObj.storage?.rules
17292
17346
  };
17293
- } else {
17294
- throw new Error("Invalid firebase.json structure");
17295
17347
  }
17296
17348
  } catch {
17297
17349
  firebaseConfig = {
@@ -17599,7 +17651,7 @@ async function main2(options = {}) {
17599
17651
  isStaging ? "Building (staging mode)..." : "Building application..."
17600
17652
  );
17601
17653
  try {
17602
- execSync5(buildCmd, {
17654
+ execSync4(buildCmd, {
17603
17655
  cwd: appDir,
17604
17656
  stdio: "inherit",
17605
17657
  env: {