@donotdev/cli 0.0.16 → 0.0.17

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 (32) hide show
  1. package/dependencies-matrix.json +33 -129
  2. package/dist/bin/commands/bump.js +9 -2
  3. package/dist/bin/commands/create-app.js +195 -40
  4. package/dist/bin/commands/create-project.js +195 -40
  5. package/dist/bin/commands/deploy.js +51 -20
  6. package/dist/bin/commands/doctor.js +249 -56
  7. package/dist/bin/commands/emu.js +18 -20
  8. package/dist/bin/commands/make-admin.js +30 -10
  9. package/dist/bin/commands/setup.js +512 -122
  10. package/dist/bin/commands/type-check.d.ts.map +1 -1
  11. package/dist/bin/commands/type-check.js +7 -3
  12. package/dist/bin/commands/type-check.js.map +1 -1
  13. package/dist/bin/donotdev.js +26 -14
  14. package/dist/index.js +264 -80
  15. package/package.json +1 -1
  16. package/templates/root-consumer/guides/dndev/ENV_SETUP.md.example +6 -6
  17. package/templates/root-consumer/guides/dndev/INDEX.md.example +2 -2
  18. package/templates/root-consumer/guides/dndev/SETUP_AUTH.md.example +13 -6
  19. package/templates/root-consumer/guides/dndev/SETUP_CRUD.md.example +149 -1086
  20. package/templates/root-consumer/guides/dndev/SETUP_FIREBASE.md.example +68 -16
  21. package/templates/root-consumer/guides/dndev/SETUP_FUNCTIONS.md.example +6 -111
  22. package/templates/root-consumer/guides/dndev/SETUP_SUPABASE.md.example +123 -32
  23. package/templates/root-consumer/guides/dndev/SETUP_VERCEL.md.example +108 -91
  24. package/templates/root-consumer/guides/dndev/advanced/EMULATORS.md.example +2 -2
  25. package/dist/bin/commands/firebase-setup.d.ts +0 -6
  26. package/dist/bin/commands/firebase-setup.d.ts.map +0 -1
  27. package/dist/bin/commands/firebase-setup.js +0 -7
  28. package/dist/bin/commands/firebase-setup.js.map +0 -1
  29. package/dist/bin/commands/supabase-setup.d.ts +0 -6
  30. package/dist/bin/commands/supabase-setup.d.ts.map +0 -1
  31. package/dist/bin/commands/supabase-setup.js +0 -7
  32. package/dist/bin/commands/supabase-setup.js.map +0 -1
package/dist/index.js CHANGED
@@ -8469,7 +8469,14 @@ function readServiceAccountKey(filePath) {
8469
8469
  throw new DoNotDevError(
8470
8470
  `Invalid service account key: missing required fields`,
8471
8471
  DO_NOT_DEV_ERROR_CODES.CONFIG_INVALID,
8472
- { context: { filePath, missingFields: ["project_id", "private_key", "client_email"].filter((f) => !key[f]) } }
8472
+ {
8473
+ context: {
8474
+ filePath,
8475
+ missingFields: ["project_id", "private_key", "client_email"].filter(
8476
+ (f) => !key[f]
8477
+ )
8478
+ }
8479
+ }
8473
8480
  );
8474
8481
  }
8475
8482
  return content;
@@ -8876,9 +8883,7 @@ function getCLIInstallInstructions(tool) {
8876
8883
  "Or: winget install Supabase.CLI",
8877
8884
  "Or download from: https://github.com/supabase/cli/releases"
8878
8885
  ],
8879
- darwin: [
8880
- "brew install supabase/tap/supabase"
8881
- ],
8886
+ darwin: ["brew install supabase/tap/supabase"],
8882
8887
  linux: [
8883
8888
  "brew install supabase/tap/supabase",
8884
8889
  "Or see: https://supabase.com/docs/guides/cli"
@@ -8886,7 +8891,11 @@ function getCLIInstallInstructions(tool) {
8886
8891
  },
8887
8892
  [CLI_TOOLS.VERCEL]: {
8888
8893
  win32: ["npm install -g vercel", "Or: npx vercel (no install)"],
8889
- darwin: ["npm install -g vercel", "Or: brew install vercel", "Or: npx vercel"],
8894
+ darwin: [
8895
+ "npm install -g vercel",
8896
+ "Or: brew install vercel",
8897
+ "Or: npx vercel"
8898
+ ],
8890
8899
  linux: ["npm install -g vercel", "Or: npx vercel"]
8891
8900
  },
8892
8901
  [CLI_TOOLS.SENTRY_CLI]: {
@@ -17034,7 +17043,9 @@ async function deploySupabaseFunctions(appDir, config) {
17034
17043
  const supabaseDir = joinPath(appDir, "supabase");
17035
17044
  const functionsDir = joinPath(supabaseDir, "functions");
17036
17045
  if (!pathExists(functionsDir)) {
17037
- log.warn("No supabase/functions/ directory found. Skipping Supabase functions deployment.");
17046
+ log.warn(
17047
+ "No supabase/functions/ directory found. Skipping Supabase functions deployment."
17048
+ );
17038
17049
  return;
17039
17050
  }
17040
17051
  requireCLI(
@@ -17050,10 +17061,14 @@ async function deploySupabaseFunctions(appDir, config) {
17050
17061
  return pathExists(indexPath);
17051
17062
  });
17052
17063
  if (functionDirs.length === 0) {
17053
- log.warn("No Edge Functions found in supabase/functions/. Skipping deployment.");
17064
+ log.warn(
17065
+ "No Edge Functions found in supabase/functions/. Skipping deployment."
17066
+ );
17054
17067
  return;
17055
17068
  }
17056
- log.info(`Found ${functionDirs.length} Edge Function(s): ${functionDirs.join(", ")}`);
17069
+ log.info(
17070
+ `Found ${functionDirs.length} Edge Function(s): ${functionDirs.join(", ")}`
17071
+ );
17057
17072
  const s = Y2();
17058
17073
  for (const functionName of functionDirs) {
17059
17074
  s.start(`Deploying Edge Function: ${functionName}...`);
@@ -17072,7 +17087,12 @@ async function deploySupabaseFunctions(appDir, config) {
17072
17087
  throw new DoNotDevError(
17073
17088
  `Failed to deploy Supabase Edge Function: ${functionName}`,
17074
17089
  "deployment-failed",
17075
- { context: { functionName, error: error2 instanceof Error ? error2.message : String(error2) } }
17090
+ {
17091
+ context: {
17092
+ functionName,
17093
+ error: error2 instanceof Error ? error2.message : String(error2)
17094
+ }
17095
+ }
17076
17096
  );
17077
17097
  }
17078
17098
  }
@@ -17892,10 +17912,7 @@ FIREBASE_AUTH_EMULATOR_HOST=${authEmulatorHost}
17892
17912
  // packages/tooling/src/apps/emu-supabase.ts
17893
17913
  init_utils();
17894
17914
  init_cli_output();
17895
- import {
17896
- spawn as spawn3,
17897
- execSync as execSync5
17898
- } from "node:child_process";
17915
+ import { spawn as spawn3, execSync as execSync5 } from "node:child_process";
17899
17916
  import { platform as platform3 } from "node:os";
17900
17917
  function isDockerRunning() {
17901
17918
  try {
@@ -17945,7 +17962,10 @@ async function startSupabase(app, _projectRoot) {
17945
17962
  if (!childProcess.pid) return;
17946
17963
  if (isWindows) {
17947
17964
  try {
17948
- execSync5(`taskkill /F /T /PID ${childProcess.pid}`, { stdio: "ignore", timeout: 2e3 });
17965
+ execSync5(`taskkill /F /T /PID ${childProcess.pid}`, {
17966
+ stdio: "ignore",
17967
+ timeout: 2e3
17968
+ });
17949
17969
  } catch {
17950
17970
  }
17951
17971
  } else {
@@ -17975,10 +17995,7 @@ async function startSupabase(app, _projectRoot) {
17975
17995
  // packages/tooling/src/apps/emu-vercel.ts
17976
17996
  init_utils();
17977
17997
  init_cli_output();
17978
- import {
17979
- spawn as spawn4,
17980
- execSync as execSync6
17981
- } from "node:child_process";
17998
+ import { spawn as spawn4, execSync as execSync6 } from "node:child_process";
17982
17999
  import { platform as platform4 } from "node:os";
17983
18000
  async function startVercel(app, _projectRoot) {
17984
18001
  log.info(`Starting Vercel dev server for ${app.name}...
@@ -17991,20 +18008,19 @@ async function startVercel(app, _projectRoot) {
17991
18008
  return 1;
17992
18009
  }
17993
18010
  const isWindows = platform4() === "win32";
17994
- const childProcess = spawn4(
17995
- "vercel",
17996
- ["dev"],
17997
- {
17998
- stdio: "inherit",
17999
- cwd: app.path,
18000
- shell: isWindows
18001
- }
18002
- );
18011
+ const childProcess = spawn4("vercel", ["dev"], {
18012
+ stdio: "inherit",
18013
+ cwd: app.path,
18014
+ shell: isWindows
18015
+ });
18003
18016
  const cleanup = () => {
18004
18017
  if (!childProcess.pid) return;
18005
18018
  if (isWindows) {
18006
18019
  try {
18007
- execSync6(`taskkill /F /T /PID ${childProcess.pid}`, { stdio: "ignore", timeout: 2e3 });
18020
+ execSync6(`taskkill /F /T /PID ${childProcess.pid}`, {
18021
+ stdio: "ignore",
18022
+ timeout: 2e3
18023
+ });
18008
18024
  } catch {
18009
18025
  }
18010
18026
  } else {
@@ -18051,7 +18067,9 @@ async function main3(options) {
18051
18067
  switch (app.platform) {
18052
18068
  case "firebase": {
18053
18069
  if (!app.hasFunctions) {
18054
- log.error(`App "${app.name}" has Firebase config but no functions directory.`);
18070
+ log.error(
18071
+ `App "${app.name}" has Firebase config but no functions directory.`
18072
+ );
18055
18073
  log.error('Use "dndev dev" for apps without backend functions.\n');
18056
18074
  return 1;
18057
18075
  }
@@ -18518,7 +18536,11 @@ function getMatrixPath(mode) {
18518
18536
  const executionMode = mode || detectExecutionMode();
18519
18537
  if (executionMode === "development") {
18520
18538
  const templatesRoot = getTemplatesRoot();
18521
- const devPath = normalizePath(templatesRoot, "..", "dependencies-matrix.json");
18539
+ const devPath = normalizePath(
18540
+ templatesRoot,
18541
+ "..",
18542
+ "dependencies-matrix.json"
18543
+ );
18522
18544
  if (pathExists(devPath)) {
18523
18545
  return devPath;
18524
18546
  }
@@ -18689,7 +18711,12 @@ async function runQuestionnaire(questions, initialAnswers, showWIP, askFor) {
18689
18711
  async function deployFrontend(appDir, serviceAccountPath, projectId, config) {
18690
18712
  const s = Y2();
18691
18713
  s.start("Deploying frontend to Firebase Hosting...");
18692
- const args = buildFirebaseDeployArgs("hosting", projectId, config.debug, config.force ?? true);
18714
+ const args = buildFirebaseDeployArgs(
18715
+ "hosting",
18716
+ projectId,
18717
+ config.debug,
18718
+ config.force ?? true
18719
+ );
18693
18720
  const result = executeFirebaseCommand(args, {
18694
18721
  cwd: appDir,
18695
18722
  serviceAccountPath,
@@ -18736,7 +18763,9 @@ async function deployVercelFrontend(appDir, _config) {
18736
18763
  if (result.status !== 0) {
18737
18764
  s.stop("Vercel deployment failed");
18738
18765
  const errOutput = result.stderr?.trim();
18739
- throw new Error(errOutput || `Vercel deploy exited with code ${result.status}`);
18766
+ throw new Error(
18767
+ errOutput || `Vercel deploy exited with code ${result.status}`
18768
+ );
18740
18769
  }
18741
18770
  s.stop("Frontend deployed to Vercel");
18742
18771
  } catch (err) {
@@ -19193,7 +19222,12 @@ async function deployRules(appDir, serviceAccountPath, projectId, config, option
19193
19222
  const targetNames = targets.join(", ");
19194
19223
  const s = Y2();
19195
19224
  s.start(`Deploying ${targetNames}...`);
19196
- const args = buildFirebaseDeployArgs(targets, projectId, config.debug, config.force ?? true);
19225
+ const args = buildFirebaseDeployArgs(
19226
+ targets,
19227
+ projectId,
19228
+ config.debug,
19229
+ config.force ?? true
19230
+ );
19197
19231
  const result = executeFirebaseCommand(args, {
19198
19232
  cwd: appDir,
19199
19233
  serviceAccountPath,
@@ -19567,13 +19601,17 @@ async function main6(options = {}) {
19567
19601
  const availableApps = detectAvailableApps();
19568
19602
  if (availableApps.length === 0) {
19569
19603
  if (providerInfo.hasSupabase && !providerInfo.hasFirebase) {
19570
- log.info("Supabase project detected. Deploying Supabase resources...");
19604
+ log.info(
19605
+ "Supabase project detected. Deploying Supabase resources..."
19606
+ );
19571
19607
  } else {
19572
19608
  log.info("No apps with firebase.json or supabase/ directory found.");
19573
19609
  log.info(
19574
19610
  "To deploy, ensure your app has a firebase.json or supabase/ configuration."
19575
19611
  );
19576
- log.info("Run from a DoNotDev project, or create one with: dndev init");
19612
+ log.info(
19613
+ "Run from a DoNotDev project, or create one with: dndev init"
19614
+ );
19577
19615
  return;
19578
19616
  }
19579
19617
  }
@@ -19853,12 +19891,7 @@ async function main6(options = {}) {
19853
19891
  }
19854
19892
  }
19855
19893
  }
19856
- await deployFunctions(
19857
- appDir,
19858
- serviceAccountPath,
19859
- config.project,
19860
- config
19861
- );
19894
+ await deployFunctions(appDir, serviceAccountPath, config.project, config);
19862
19895
  }
19863
19896
  if (shouldDeployFirebaseRules && serviceAccountPath && config.project && appProviderInfo.firebaseConfig) {
19864
19897
  await deployRules(appDir, serviceAccountPath, config.project, config, {
@@ -20082,18 +20115,102 @@ init_pathResolver();
20082
20115
  // packages/tooling/src/scaffolding/scaffold-matrix.ts
20083
20116
  init_utils();
20084
20117
  var MATRIX = [
20085
- { builder: "vite", backend: "none", baseTemplate: "app-vite", overlay: null, deployConfig: null, functionsTemplate: null },
20086
- { builder: "vite", backend: "firebase", baseTemplate: "app-vite", overlay: "overlay-firebase", deployConfig: "firebase", functionsTemplate: "functions-firebase" },
20087
- { builder: "vite", backend: "supabase", baseTemplate: "app-vite", overlay: "overlay-supabase", deployConfig: "vercel-supabase", functionsTemplate: "functions-supabase" },
20088
- { builder: "vite", backend: "vercel", baseTemplate: "app-vite", overlay: "overlay-vercel", deployConfig: "vercel-vercel", functionsTemplate: "functions-vercel" },
20089
- { builder: "nextjs", backend: "none", baseTemplate: "app-next", overlay: null, deployConfig: null, functionsTemplate: null },
20090
- { builder: "nextjs", backend: "firebase", baseTemplate: "app-next", overlay: "overlay-firebase", deployConfig: "firebase", functionsTemplate: "functions-firebase" },
20091
- { builder: "nextjs", backend: "supabase", baseTemplate: "app-next", overlay: "overlay-supabase", deployConfig: "vercel-supabase", functionsTemplate: "functions-supabase" },
20092
- { builder: "nextjs", backend: "vercel", baseTemplate: "app-next", overlay: "overlay-vercel", deployConfig: "vercel-vercel", functionsTemplate: "functions-vercel" },
20093
- { builder: "expo", backend: "none", baseTemplate: "app-expo", overlay: null, deployConfig: null, functionsTemplate: null },
20094
- { builder: "expo", backend: "firebase", baseTemplate: "app-expo", overlay: "overlay-firebase", deployConfig: null, functionsTemplate: "functions-firebase" },
20095
- { builder: "expo", backend: "supabase", baseTemplate: "app-expo", overlay: "overlay-supabase", deployConfig: null, functionsTemplate: "functions-supabase" },
20096
- { builder: "demo", backend: "none", baseTemplate: "app-demo", overlay: null, deployConfig: null, functionsTemplate: null }
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
+ }
20097
20214
  ];
20098
20215
  function comboKey(builder, backend) {
20099
20216
  return `${builder}-${backend}`;
@@ -20106,7 +20223,9 @@ function getScaffoldRow(builder, backend) {
20106
20223
  const key = comboKey(builder, backend);
20107
20224
  const row = ROWS_BY_KEY.get(key);
20108
20225
  if (!row) {
20109
- throw new Error(`Unsupported scaffold combo: ${key}. Supported: ${[...ROWS_BY_KEY.keys()].join(", ")}`);
20226
+ throw new Error(
20227
+ `Unsupported scaffold combo: ${key}. Supported: ${[...ROWS_BY_KEY.keys()].join(", ")}`
20228
+ );
20110
20229
  }
20111
20230
  return row;
20112
20231
  }
@@ -20262,13 +20381,16 @@ async function createApp(appName, appConfig, workspaceRoot, templatesRoot) {
20262
20381
  const variantFile = `src/config/providers.${appTemplate}.ts.example`;
20263
20382
  if (overlayFiles.includes(variantFile)) continue;
20264
20383
  }
20265
- const providersVariant = file.match(/^src\/config\/providers\.(\w+)\.ts\.example$/);
20384
+ const providersVariant = file.match(
20385
+ /^src\/config\/providers\.(\w+)\.ts\.example$/
20386
+ );
20266
20387
  if (providersVariant) {
20267
20388
  if (providersVariant[1] !== appTemplate) continue;
20268
20389
  const destPath2 = joinPath(appDir, "src/config/providers.ts");
20269
20390
  await ensureDir(getDirname(destPath2));
20270
20391
  await copy(joinPath(overlayDir, file), destPath2, { overwrite: true });
20271
- if (await isTextFile(destPath2)) await replacePlaceholders(destPath2, replacements);
20392
+ if (await isTextFile(destPath2))
20393
+ await replacePlaceholders(destPath2, replacements);
20272
20394
  continue;
20273
20395
  }
20274
20396
  const sourcePath = joinPath(overlayDir, file);
@@ -20293,16 +20415,28 @@ async function createApp(appName, appConfig, workspaceRoot, templatesRoot) {
20293
20415
  }
20294
20416
  if (deployConfig === "vercel-supabase") {
20295
20417
  const vercelPath = joinPath(appDir, "vercel.json");
20296
- const headersFragmentPath = joinPath(overlayDir, "vercel.headers.example");
20418
+ const headersFragmentPath = joinPath(
20419
+ overlayDir,
20420
+ "vercel.headers.example"
20421
+ );
20297
20422
  const fullVercelPath = joinPath(overlayDir, "vercel.json.example");
20298
20423
  if (pathExists(vercelPath) && pathExists(headersFragmentPath)) {
20299
20424
  const vercelJson = readSync(vercelPath, { format: "json" });
20300
- const headersFragment = readSync(headersFragmentPath, { format: "json" });
20301
- vercelJson.headers = [...vercelJson.headers ?? [], ...headersFragment];
20302
- await write(vercelPath, vercelJson, { format: "json", overwrite: true });
20425
+ const headersFragment = readSync(headersFragmentPath, {
20426
+ format: "json"
20427
+ });
20428
+ vercelJson.headers = [
20429
+ ...vercelJson.headers ?? [],
20430
+ ...headersFragment
20431
+ ];
20432
+ await write(vercelPath, vercelJson, {
20433
+ format: "json",
20434
+ overwrite: true
20435
+ });
20303
20436
  } else if (pathExists(fullVercelPath)) {
20304
20437
  await copy(fullVercelPath, vercelPath);
20305
- if (await isTextFile(vercelPath)) await replacePlaceholders(vercelPath, replacements);
20438
+ if (await isTextFile(vercelPath))
20439
+ await replacePlaceholders(vercelPath, replacements);
20306
20440
  }
20307
20441
  }
20308
20442
  }
@@ -20322,9 +20456,13 @@ async function createApp(appName, appConfig, workspaceRoot, templatesRoot) {
20322
20456
  });
20323
20457
  if (row.functionsTemplate) {
20324
20458
  const functionsTemplateName = row.functionsTemplate;
20325
- const functionsTemplateExists = pathExists(joinPath(templatesRoot, functionsTemplateName));
20459
+ const functionsTemplateExists = pathExists(
20460
+ joinPath(templatesRoot, functionsTemplateName)
20461
+ );
20326
20462
  if (!functionsTemplateExists) {
20327
- log.warn(`Functions template "${functionsTemplateName}" not found \u2014 skipping functions scaffolding.`);
20463
+ log.warn(
20464
+ `Functions template "${functionsTemplateName}" not found \u2014 skipping functions scaffolding.`
20465
+ );
20328
20466
  } else {
20329
20467
  const isSupabaseFunctions = functionsTemplateName === "functions-supabase";
20330
20468
  const functionsRootDir = isSupabaseFunctions ? appDir : joinPath(appDir, "functions");
@@ -20332,7 +20470,10 @@ async function createApp(appName, appConfig, workspaceRoot, templatesRoot) {
20332
20470
  const functionsPackageJson = generatePackageJson(
20333
20471
  functionsTemplateName,
20334
20472
  executionMode,
20335
- { appName, platform: row.functionsTemplate.replace("functions-", "") }
20473
+ {
20474
+ appName,
20475
+ platform: row.functionsTemplate.replace("functions-", "")
20476
+ }
20336
20477
  );
20337
20478
  const packageJsonPath2 = joinPath(functionsRootDir, "package.json");
20338
20479
  await ensureDir(functionsRootDir);
@@ -20368,13 +20509,19 @@ async function createApp(appName, appConfig, workspaceRoot, templatesRoot) {
20368
20509
  }
20369
20510
  const deploymentTemplateDir = joinPath(templatesRoot, "root-consumer");
20370
20511
  if (deployConfig === "firebase") {
20371
- const firebaseJsonSource = joinPath(deploymentTemplateDir, "firebase.json.example");
20512
+ const firebaseJsonSource = joinPath(
20513
+ deploymentTemplateDir,
20514
+ "firebase.json.example"
20515
+ );
20372
20516
  if (pathExists(firebaseJsonSource)) {
20373
20517
  await copy(firebaseJsonSource, joinPath(appDir, "firebase.json"));
20374
20518
  const firebaseJsonDest = joinPath(appDir, "firebase.json");
20375
- if (await isTextFile(firebaseJsonDest)) await replacePlaceholders(firebaseJsonDest, replacements);
20519
+ if (await isTextFile(firebaseJsonDest))
20520
+ await replacePlaceholders(firebaseJsonDest, replacements);
20376
20521
  if (appTemplate === "nextjs") {
20377
- const firebaseJson = readSync(firebaseJsonDest, { format: "json" });
20522
+ const firebaseJson = readSync(firebaseJsonDest, {
20523
+ format: "json"
20524
+ });
20378
20525
  if (firebaseJson.hosting?.rewrites) {
20379
20526
  firebaseJson.hosting.rewrites = firebaseJson.hosting.rewrites.filter(
20380
20527
  (r2) => r2.destination !== "/index.html"
@@ -20383,17 +20530,28 @@ async function createApp(appName, appConfig, workspaceRoot, templatesRoot) {
20383
20530
  if (firebaseJson.hosting) {
20384
20531
  firebaseJson.hosting.public = "out";
20385
20532
  }
20386
- await write(firebaseJsonDest, firebaseJson, { format: "json", overwrite: true });
20533
+ await write(firebaseJsonDest, firebaseJson, {
20534
+ format: "json",
20535
+ overwrite: true
20536
+ });
20387
20537
  }
20388
20538
  }
20389
- const firebasercSource = joinPath(deploymentTemplateDir, ".firebaserc.example");
20539
+ const firebasercSource = joinPath(
20540
+ deploymentTemplateDir,
20541
+ ".firebaserc.example"
20542
+ );
20390
20543
  if (pathExists(firebasercSource)) {
20391
20544
  await copy(firebasercSource, joinPath(appDir, ".firebaserc"));
20392
20545
  const firebasercDest = joinPath(appDir, ".firebaserc");
20393
- if (await isTextFile(firebasercDest)) await replacePlaceholders(firebasercDest, replacements);
20546
+ if (await isTextFile(firebasercDest))
20547
+ await replacePlaceholders(firebasercDest, replacements);
20394
20548
  }
20395
20549
  if (row.functionsTemplate === "functions-firebase") {
20396
- for (const example of ["firestore.rules.example", "firestore.indexes.json.example", "storage.rules.example"]) {
20550
+ for (const example of [
20551
+ "firestore.rules.example",
20552
+ "firestore.indexes.json.example",
20553
+ "storage.rules.example"
20554
+ ]) {
20397
20555
  const src = joinPath(deploymentTemplateDir, example);
20398
20556
  if (pathExists(src)) {
20399
20557
  await copy(src, joinPath(appDir, example.replace(".example", "")));
@@ -20409,11 +20567,22 @@ async function createApp(appName, appConfig, workspaceRoot, templatesRoot) {
20409
20567
  {
20410
20568
  source: "functions",
20411
20569
  codebase: "default",
20412
- ignore: ["node_modules", ".git", "firebase-debug.log", "firebase-debug.*.log", "**/.*", "**/*.test.ts", "**/__tests__/**"],
20570
+ ignore: [
20571
+ "node_modules",
20572
+ ".git",
20573
+ "firebase-debug.log",
20574
+ "firebase-debug.*.log",
20575
+ "**/.*",
20576
+ "**/*.test.ts",
20577
+ "**/__tests__/**"
20578
+ ],
20413
20579
  runtime: "nodejs22"
20414
20580
  }
20415
20581
  ],
20416
- firestore: { rules: "firestore.rules", indexes: "firestore.indexes.json" },
20582
+ firestore: {
20583
+ rules: "firestore.rules",
20584
+ indexes: "firestore.indexes.json"
20585
+ },
20417
20586
  storage: { rules: "storage.rules" },
20418
20587
  emulators: {
20419
20588
  auth: { port: 9099 },
@@ -20423,15 +20592,26 @@ async function createApp(appName, appConfig, workspaceRoot, templatesRoot) {
20423
20592
  ui: { enabled: true, port: 4e3 }
20424
20593
  }
20425
20594
  };
20426
- await write(firebaseJsonPath, expoFirebaseJson, { format: "json", overwrite: true });
20595
+ await write(firebaseJsonPath, expoFirebaseJson, {
20596
+ format: "json",
20597
+ overwrite: true
20598
+ });
20427
20599
  }
20428
- const firebasercSource = joinPath(deploymentTemplateDir, ".firebaserc.example");
20600
+ const firebasercSource = joinPath(
20601
+ deploymentTemplateDir,
20602
+ ".firebaserc.example"
20603
+ );
20429
20604
  const firebasercDest = joinPath(appDir, ".firebaserc");
20430
20605
  if (pathExists(firebasercSource) && !pathExists(firebasercDest)) {
20431
20606
  await copy(firebasercSource, firebasercDest);
20432
- if (await isTextFile(firebasercDest)) await replacePlaceholders(firebasercDest, replacements);
20433
- }
20434
- for (const example of ["firestore.rules.example", "firestore.indexes.json.example", "storage.rules.example"]) {
20607
+ if (await isTextFile(firebasercDest))
20608
+ await replacePlaceholders(firebasercDest, replacements);
20609
+ }
20610
+ for (const example of [
20611
+ "firestore.rules.example",
20612
+ "firestore.indexes.json.example",
20613
+ "storage.rules.example"
20614
+ ]) {
20435
20615
  const src = joinPath(deploymentTemplateDir, example);
20436
20616
  const dest = joinPath(appDir, example.replace(".example", ""));
20437
20617
  if (pathExists(src) && !pathExists(dest)) {
@@ -20440,11 +20620,15 @@ async function createApp(appName, appConfig, workspaceRoot, templatesRoot) {
20440
20620
  }
20441
20621
  }
20442
20622
  if (deployConfig === "vercel-vercel") {
20443
- const vercelJsonSource = joinPath(deploymentTemplateDir, "vercel.json.example");
20623
+ const vercelJsonSource = joinPath(
20624
+ deploymentTemplateDir,
20625
+ "vercel.json.example"
20626
+ );
20444
20627
  if (pathExists(vercelJsonSource)) {
20445
20628
  await copy(vercelJsonSource, joinPath(appDir, "vercel.json"));
20446
20629
  const vercelJsonDest = joinPath(appDir, "vercel.json");
20447
- if (await isTextFile(vercelJsonDest)) await replacePlaceholders(vercelJsonDest, replacements);
20630
+ if (await isTextFile(vercelJsonDest))
20631
+ await replacePlaceholders(vercelJsonDest, replacements);
20448
20632
  }
20449
20633
  }
20450
20634
  const backendInfo = row.functionsTemplate ? ` with ${row.functionsTemplate.replace("functions-", "")} functions` : "";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@donotdev/cli",
3
- "version": "0.0.16",
3
+ "version": "0.0.17",
4
4
  "description": "Command-line interface for DoNotDev Framework",
5
5
  "type": "module",
6
6
  "private": false,
@@ -9,8 +9,8 @@ If you haven’t run `dndev init` yet, see [AGENT_START_HERE.md](./AGENT_START_H
9
9
  ## The Flow
10
10
 
11
11
  ```
12
- bun install -> install dependencies
13
- bun dev -> start app, read the homepage setup guide
12
+ bun install install dependencies
13
+ dndev dev -> start app, read the homepage setup guide
14
14
  dndev setup firebase -> configure Firebase project + .env
15
15
  -- or --
16
16
  dndev setup supabase -> configure Supabase project + .env
@@ -24,7 +24,7 @@ dndev deploy -> deploy to production
24
24
 
25
25
  ```bash
26
26
  bun install
27
- bun dev
27
+ dndev dev
28
28
  ```
29
29
 
30
30
  Open the app. The homepage shows every setup step with instructions.
@@ -73,7 +73,7 @@ Asks for your **public** project URL and anon key (both safe to share -- shipped
73
73
 
74
74
  Get them from: https://supabase.com/dashboard -> your project -> Settings -> API
75
75
 
76
- See [SETUP_SUPABASE.md](./SETUP_SUPABASE.md) for full details (tables, RLS, `dn generate sql`). See [Secrets Philosophy](#secrets-philosophy) for how we handle secret keys.
76
+ See [SETUP_SUPABASE.md](./SETUP_SUPABASE.md) for full details (tables, RLS, `dndev generate sql`). See [Secrets Philosophy](#secrets-philosophy) for how we handle secret keys.
77
77
 
78
78
  ---
79
79
 
@@ -186,7 +186,7 @@ my-project/
186
186
 
187
187
  | Command | What It Does |
188
188
  |---------|-------------|
189
- | `bun dev` | Start dev server |
189
+ | `dndev dev` | Start dev server |
190
190
  | `dndev emu start` | Start Firebase emulators |
191
191
  | `dndev setup firebase` | Configure Firebase project + .env |
192
192
  | `dndev setup supabase` | Configure Supabase project + .env |
@@ -215,4 +215,4 @@ my-project/
215
215
 
216
216
  ---
217
217
 
218
- **Start here: `bun install && bun dev`. The homepage tells you everything else.**
218
+ **Start here: `bun install && dndev dev`. The homepage tells you everything else.**
@@ -12,7 +12,7 @@
12
12
  - [ENV_SETUP.md](./ENV_SETUP.md) — After `dndev init`: env, Firebase/Supabase, deploy
13
13
  - [GOTCHAS.md](./GOTCHAS.md) - **Common mistakes & pitfalls** (phase-tagged, read before coding)
14
14
  - [SETUP_FIREBASE.md](./SETUP_FIREBASE.md) - Firebase project setup (`dndev setup firebase`)
15
- - [SETUP_SUPABASE.md](./SETUP_SUPABASE.md) - Supabase project setup (`dndev setup supabase`, `dn generate sql`)
15
+ - [SETUP_SUPABASE.md](./SETUP_SUPABASE.md) - Supabase project setup (`dndev setup supabase`, `dndev generate sql`)
16
16
  - [SETUP_TESTING.md](./SETUP_TESTING.md) - Test generation (Phase 4)
17
17
 
18
18
  ---
@@ -36,7 +36,7 @@
36
36
  - [SETUP_BILLING.md](./SETUP_BILLING.md) - Stripe subscriptions (pre-configured)
37
37
  - [SETUP_BLOG.md](./SETUP_BLOG.md) - Convention-based markdown blog with i18n
38
38
  - [SETUP_PWA.md](./SETUP_PWA.md) - Progressive Web App setup
39
- - [SETUP_FUNCTIONS.md](./SETUP_FUNCTIONS.md) - Firebase Functions (pre-configured)
39
+ - [SETUP_FUNCTIONS.md](./SETUP_FUNCTIONS.md) - Functions overview (redirects to provider guides)
40
40
 
41
41
  ---
42
42