@donotdev/cli 0.0.8 → 0.0.11

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 (47) hide show
  1. package/dependencies-matrix.json +177 -76
  2. package/dist/bin/commands/build.js +2 -2
  3. package/dist/bin/commands/bump.js +578 -94
  4. package/dist/bin/commands/cacheout.js +2 -2
  5. package/dist/bin/commands/create-app.js +46 -9
  6. package/dist/bin/commands/create-project.js +63 -10
  7. package/dist/bin/commands/deploy.js +114 -25
  8. package/dist/bin/commands/dev.js +2 -2
  9. package/dist/bin/commands/emu.js +2 -2
  10. package/dist/bin/commands/format.js +2 -2
  11. package/dist/bin/commands/lint.js +2 -2
  12. package/dist/bin/commands/preview.js +2 -2
  13. package/dist/bin/commands/sync-secrets.js +2 -2
  14. package/dist/bin/dndev.js +7 -4
  15. package/dist/bin/donotdev.js +7 -4
  16. package/dist/index.js +177 -33
  17. package/package.json +5 -4
  18. package/templates/app-next/src/config/app.ts.example +1 -1
  19. package/templates/app-vite/index.html.example +24 -2
  20. package/templates/app-vite/src/config/app.ts.example +1 -1
  21. package/templates/app-vite/src/pages/FormPageExample.tsx.example +8 -5
  22. package/templates/app-vite/src/pages/ListPageExample.tsx.example +4 -7
  23. package/templates/root-consumer/.claude/agents/architect.md.example +313 -0
  24. package/templates/root-consumer/.claude/agents/builder.md.example +329 -0
  25. package/templates/root-consumer/.claude/agents/coder.md.example +87 -0
  26. package/templates/root-consumer/.claude/agents/extractor.md.example +235 -0
  27. package/templates/root-consumer/.claude/agents/polisher.md.example +359 -0
  28. package/templates/root-consumer/.claude/agents/prompt-engineer.md.example +85 -0
  29. package/templates/root-consumer/.claude/commands/brainstorm.md.example +133 -0
  30. package/templates/root-consumer/.claude/commands/build.md.example +109 -0
  31. package/templates/root-consumer/.claude/commands/design.md.example +136 -0
  32. package/templates/root-consumer/.claude/commands/polish.md.example +145 -0
  33. package/templates/root-consumer/.cursor/mcp.json.example +8 -0
  34. package/templates/root-consumer/.firebaserc.example +5 -0
  35. package/templates/root-consumer/.mcp.json.example +8 -0
  36. package/templates/root-consumer/CLAUDE.md.example +146 -0
  37. package/templates/root-consumer/entities/ExampleEntity.ts.example +2 -1
  38. package/templates/root-consumer/entities/demo.ts.example +1 -1
  39. package/templates/root-consumer/firestore.indexes.json.example +4 -0
  40. package/templates/root-consumer/firestore.rules.example +11 -0
  41. package/templates/root-consumer/guides/dndev/AGENT_START_HERE.md.example +15 -12
  42. package/templates/root-consumer/guides/dndev/COMPONENTS_CRUD.md.example +9 -6
  43. package/templates/root-consumer/guides/dndev/COMPONENT_API.md.example +195 -0
  44. package/templates/root-consumer/guides/dndev/INDEX.md.example +3 -1
  45. package/templates/root-consumer/guides/dndev/SETUP_CRUD.md.example +485 -57
  46. package/templates/root-consumer/guides/wai-way/entity_patterns.md.example +1 -1
  47. package/templates/root-consumer/storage.rules.example +8 -0
@@ -163,7 +163,7 @@ var require_picocolors = __commonJS({
163
163
  }
164
164
  });
165
165
 
166
- // node_modules/.bun/@clack+core@0.5.0/node_modules/@clack/core/dist/index.mjs
166
+ // node_modules/.bun/@clack+prompts@0.11.0/node_modules/@clack/prompts/node_modules/@clack/core/dist/index.mjs
167
167
  import { stdin as j, stdout as M } from "node:process";
168
168
  import { Writable as X } from "node:stream";
169
169
  function DD({ onlyFirst: e2 = false } = {}) {
@@ -204,7 +204,7 @@ function rD() {
204
204
  }
205
205
  var import_sisteransi, uD, W, tD, eD, FD, sD, w, N, I, R, r, iD, CD, ED, nD, _, xD, B, AD, A;
206
206
  var init_dist = __esm({
207
- "node_modules/.bun/@clack+core@0.5.0/node_modules/@clack/core/dist/index.mjs"() {
207
+ "node_modules/.bun/@clack+prompts@0.11.0/node_modules/@clack/prompts/node_modules/@clack/core/dist/index.mjs"() {
208
208
  init_utils();
209
209
  import_sisteransi = __toESM(require_src(), 1);
210
210
  uD = DD();
@@ -167,7 +167,7 @@ var require_picocolors = __commonJS({
167
167
  }
168
168
  });
169
169
 
170
- // node_modules/.bun/@clack+core@0.5.0/node_modules/@clack/core/dist/index.mjs
170
+ // node_modules/.bun/@clack+prompts@0.11.0/node_modules/@clack/prompts/node_modules/@clack/core/dist/index.mjs
171
171
  import { stdin as j, stdout as M } from "node:process";
172
172
  import * as g from "node:readline";
173
173
  import O from "node:readline";
@@ -283,7 +283,7 @@ function fD({ input: e2 = j, output: u2 = M, overwrite: t = true, hideCursor: F2
283
283
  }
284
284
  var import_sisteransi, import_picocolors, uD, W, tD, eD, FD, sD, w, N, I, R, r, iD, CD, ED, d, oD, y, V, nD, G, _, z, K, aD, k, hD, lD, xD, B, AD, S, gD, vD, h, x, dD, A, OD, PD, J, LD, RD;
285
285
  var init_dist = __esm({
286
- "node_modules/.bun/@clack+core@0.5.0/node_modules/@clack/core/dist/index.mjs"() {
286
+ "node_modules/.bun/@clack+prompts@0.11.0/node_modules/@clack/prompts/node_modules/@clack/core/dist/index.mjs"() {
287
287
  init_utils();
288
288
  import_sisteransi = __toESM(require_src(), 1);
289
289
  import_picocolors = __toESM(require_picocolors(), 1);
@@ -8267,7 +8267,7 @@ async function askForInput(message, defaultValue = "") {
8267
8267
  const result = await he({
8268
8268
  message,
8269
8269
  placeholder: defaultValue || void 0,
8270
- defaultValue: defaultValue || void 0
8270
+ initialValue: defaultValue || void 0
8271
8271
  });
8272
8272
  if (pD(result)) {
8273
8273
  xe("Operation cancelled.");
@@ -8693,7 +8693,7 @@ function generatePackageJson(templateName, mode, options = {}) {
8693
8693
  "dependencies-matrix.json not found. This command requires the matrix file."
8694
8694
  );
8695
8695
  }
8696
- const { matrix, cliVersion } = matrixResult;
8696
+ const { matrix } = matrixResult;
8697
8697
  const template = matrix.templateMapping?.[templateName];
8698
8698
  if (!template) {
8699
8699
  throw new Error(`Template "${templateName}" not found in matrix`);
@@ -8757,6 +8757,7 @@ function generatePackageJson(templateName, mode, options = {}) {
8757
8757
  }
8758
8758
  }
8759
8759
  if (templateName.includes("functions")) {
8760
+ result.main = "lib/index.js";
8760
8761
  result.engines = { node: "20" };
8761
8762
  if (options.appName) {
8762
8763
  const platform = templateName.includes("vercel") ? "Vercel" : "Firebase";
@@ -8884,6 +8885,8 @@ async function createApp(appName, appConfig, workspaceRoot, templatesRoot) {
8884
8885
  s.start(`Creating app: ${appName}`);
8885
8886
  await ensureDir(appDir);
8886
8887
  const templateDir = appTemplate === "demo" ? "app-demo" : appTemplate === "nextjs" ? "app-next" : "app-vite";
8888
+ const firebaseProjectId = (appConfig?.firebaseProjectId ?? "").trim() || appName.toLowerCase().replace(/\s+/g, "-");
8889
+ const firebaseRegion = appConfig?.firebaseRegion ?? "europe-west1";
8887
8890
  const replacements = {
8888
8891
  projectName: appName,
8889
8892
  appName,
@@ -8892,11 +8895,14 @@ async function createApp(appName, appConfig, workspaceRoot, templatesRoot) {
8892
8895
  needsCRUD: Boolean(appConfig.needsCRUD),
8893
8896
  setupGithubActions: false,
8894
8897
  appNames: [appName],
8895
- firebaseProjectId: appName.toLowerCase(),
8898
+ firebaseProjectId,
8899
+ firebaseRegion,
8896
8900
  firebaseSecretName: appName.toUpperCase().replace(/-/g, "_"),
8897
8901
  monorepoRelativePath: "../../packages/tooling",
8898
8902
  appTemplate,
8899
- isNextjs: appTemplate === "nextjs"
8903
+ isNextjs: appTemplate === "nextjs",
8904
+ YOUR_FIREBASE_PROJECT_ID: firebaseProjectId,
8905
+ YOUR_REGION: firebaseRegion
8900
8906
  };
8901
8907
  const templateSourceDir = joinPath(templatesRoot, templateDir);
8902
8908
  const templateFiles = await glob("**/*", {
@@ -8989,6 +8995,32 @@ async function createApp(appName, appConfig, workspaceRoot, templatesRoot) {
8989
8995
  await replacePlaceholders(firebaseJsonDest, replacements);
8990
8996
  }
8991
8997
  }
8998
+ const firebasercSource = joinPath(
8999
+ deploymentTemplateDir,
9000
+ ".firebaserc.example"
9001
+ );
9002
+ if (pathExists(firebasercSource)) {
9003
+ const firebasercDest = joinPath(appDir, ".firebaserc");
9004
+ await copy(firebasercSource, firebasercDest);
9005
+ if (await isTextFile(firebasercDest)) {
9006
+ await replacePlaceholders(firebasercDest, replacements);
9007
+ }
9008
+ }
9009
+ if (appConfig.needsBackend && appConfig.backendPlatform === "firebase") {
9010
+ const rulesFiles = [
9011
+ "firestore.rules.example",
9012
+ "firestore.indexes.json.example",
9013
+ "storage.rules.example"
9014
+ ];
9015
+ for (const example of rulesFiles) {
9016
+ const src = joinPath(deploymentTemplateDir, example);
9017
+ if (pathExists(src)) {
9018
+ const destName = example.replace(".example", "");
9019
+ const dest = joinPath(appDir, destName);
9020
+ await copy(src, dest);
9021
+ }
9022
+ }
9023
+ }
8992
9024
  if (appTemplate === "nextjs" || appConfig.needsBackend && appConfig.backendPlatform === "vercel") {
8993
9025
  const vercelJsonSource = joinPath(
8994
9026
  deploymentTemplateDir,
@@ -9014,12 +9046,15 @@ async function createApp(appName, appConfig, workspaceRoot, templatesRoot) {
9014
9046
  }
9015
9047
  if (isInteractive) {
9016
9048
  Se("\u{1F389} App created successfully!");
9049
+ const firebaseStep = appConfig.needsBackend && appConfig.backendPlatform === "firebase" ? `2. Set Firebase project: cd apps/${appName} && firebase use --add (or edit .firebase rc)
9050
+ 3. bun install
9051
+ 4. bun run dev` : `2. bun install
9052
+ 3. bun run dev`;
9017
9053
  Me(
9018
9054
  `Next steps:
9019
9055
 
9020
9056
  1. cd apps/${appName}
9021
- 2. bun install
9022
- 3. bun run dev
9057
+ ${firebaseStep}
9023
9058
 
9024
9059
  Happy coding!`,
9025
9060
  "\u{1F4CB} Next Steps"
@@ -9051,7 +9086,9 @@ async function main(options) {
9051
9086
  selectedEntities: [],
9052
9087
  userAuth: "social",
9053
9088
  billing: true,
9054
- features: []
9089
+ features: [],
9090
+ firebaseProjectId: options.firebaseProjectId,
9091
+ firebaseRegion: options.firebaseRegion
9055
9092
  };
9056
9093
  await createApp(appName, appConfig);
9057
9094
  } else {
@@ -167,7 +167,7 @@ var require_picocolors = __commonJS({
167
167
  }
168
168
  });
169
169
 
170
- // node_modules/.bun/@clack+core@0.5.0/node_modules/@clack/core/dist/index.mjs
170
+ // node_modules/.bun/@clack+prompts@0.11.0/node_modules/@clack/prompts/node_modules/@clack/core/dist/index.mjs
171
171
  import { stdin as j, stdout as M } from "node:process";
172
172
  import * as g from "node:readline";
173
173
  import O from "node:readline";
@@ -283,7 +283,7 @@ function fD({ input: e2 = j, output: u2 = M, overwrite: t = true, hideCursor: F2
283
283
  }
284
284
  var import_sisteransi, import_picocolors, uD, W, tD, eD, FD, sD, w, N, I, R, r, iD, CD, ED, d, oD, y, V, nD, G, _, z, K, aD, k, hD, lD, xD, B, AD, S, gD, vD, h, x, dD, A, OD, PD, J, LD, RD;
285
285
  var init_dist = __esm({
286
- "node_modules/.bun/@clack+core@0.5.0/node_modules/@clack/core/dist/index.mjs"() {
286
+ "node_modules/.bun/@clack+prompts@0.11.0/node_modules/@clack/prompts/node_modules/@clack/core/dist/index.mjs"() {
287
287
  init_utils();
288
288
  import_sisteransi = __toESM(require_src(), 1);
289
289
  import_picocolors = __toESM(require_picocolors(), 1);
@@ -8267,7 +8267,7 @@ async function askForInput(message, defaultValue = "") {
8267
8267
  const result = await he({
8268
8268
  message,
8269
8269
  placeholder: defaultValue || void 0,
8270
- defaultValue: defaultValue || void 0
8270
+ initialValue: defaultValue || void 0
8271
8271
  });
8272
8272
  if (pD(result)) {
8273
8273
  xe("Operation cancelled.");
@@ -8834,7 +8834,7 @@ function generatePackageJson(templateName, mode, options = {}) {
8834
8834
  "dependencies-matrix.json not found. This command requires the matrix file."
8835
8835
  );
8836
8836
  }
8837
- const { matrix, cliVersion } = matrixResult;
8837
+ const { matrix } = matrixResult;
8838
8838
  const template = matrix.templateMapping?.[templateName];
8839
8839
  if (!template) {
8840
8840
  throw new Error(`Template "${templateName}" not found in matrix`);
@@ -8898,6 +8898,7 @@ function generatePackageJson(templateName, mode, options = {}) {
8898
8898
  }
8899
8899
  }
8900
8900
  if (templateName.includes("functions")) {
8901
+ result.main = "lib/index.js";
8901
8902
  result.engines = { node: "20" };
8902
8903
  if (options.appName) {
8903
8904
  const platform = templateName.includes("vercel") ? "Vercel" : "Firebase";
@@ -9025,6 +9026,8 @@ async function createApp(appName, appConfig, workspaceRoot, templatesRoot) {
9025
9026
  s.start(`Creating app: ${appName}`);
9026
9027
  await ensureDir(appDir);
9027
9028
  const templateDir = appTemplate === "demo" ? "app-demo" : appTemplate === "nextjs" ? "app-next" : "app-vite";
9029
+ const firebaseProjectId = (appConfig?.firebaseProjectId ?? "").trim() || appName.toLowerCase().replace(/\s+/g, "-");
9030
+ const firebaseRegion = appConfig?.firebaseRegion ?? "europe-west1";
9028
9031
  const replacements = {
9029
9032
  projectName: appName,
9030
9033
  appName,
@@ -9033,11 +9036,14 @@ async function createApp(appName, appConfig, workspaceRoot, templatesRoot) {
9033
9036
  needsCRUD: Boolean(appConfig.needsCRUD),
9034
9037
  setupGithubActions: false,
9035
9038
  appNames: [appName],
9036
- firebaseProjectId: appName.toLowerCase(),
9039
+ firebaseProjectId,
9040
+ firebaseRegion,
9037
9041
  firebaseSecretName: appName.toUpperCase().replace(/-/g, "_"),
9038
9042
  monorepoRelativePath: "../../packages/tooling",
9039
9043
  appTemplate,
9040
- isNextjs: appTemplate === "nextjs"
9044
+ isNextjs: appTemplate === "nextjs",
9045
+ YOUR_FIREBASE_PROJECT_ID: firebaseProjectId,
9046
+ YOUR_REGION: firebaseRegion
9041
9047
  };
9042
9048
  const templateSourceDir = joinPath(templatesRoot, templateDir);
9043
9049
  const templateFiles = await glob("**/*", {
@@ -9130,6 +9136,32 @@ async function createApp(appName, appConfig, workspaceRoot, templatesRoot) {
9130
9136
  await replacePlaceholders(firebaseJsonDest, replacements);
9131
9137
  }
9132
9138
  }
9139
+ const firebasercSource = joinPath(
9140
+ deploymentTemplateDir,
9141
+ ".firebaserc.example"
9142
+ );
9143
+ if (pathExists(firebasercSource)) {
9144
+ const firebasercDest = joinPath(appDir, ".firebaserc");
9145
+ await copy(firebasercSource, firebasercDest);
9146
+ if (await isTextFile(firebasercDest)) {
9147
+ await replacePlaceholders(firebasercDest, replacements);
9148
+ }
9149
+ }
9150
+ if (appConfig.needsBackend && appConfig.backendPlatform === "firebase") {
9151
+ const rulesFiles = [
9152
+ "firestore.rules.example",
9153
+ "firestore.indexes.json.example",
9154
+ "storage.rules.example"
9155
+ ];
9156
+ for (const example of rulesFiles) {
9157
+ const src = joinPath(deploymentTemplateDir, example);
9158
+ if (pathExists(src)) {
9159
+ const destName = example.replace(".example", "");
9160
+ const dest = joinPath(appDir, destName);
9161
+ await copy(src, dest);
9162
+ }
9163
+ }
9164
+ }
9133
9165
  if (appTemplate === "nextjs" || appConfig.needsBackend && appConfig.backendPlatform === "vercel") {
9134
9166
  const vercelJsonSource = joinPath(
9135
9167
  deploymentTemplateDir,
@@ -9155,12 +9187,15 @@ async function createApp(appName, appConfig, workspaceRoot, templatesRoot) {
9155
9187
  }
9156
9188
  if (isInteractive) {
9157
9189
  Se("\u{1F389} App created successfully!");
9190
+ const firebaseStep = appConfig.needsBackend && appConfig.backendPlatform === "firebase" ? `2. Set Firebase project: cd apps/${appName} && firebase use --add (or edit .firebase rc)
9191
+ 3. bun install
9192
+ 4. bun run dev` : `2. bun install
9193
+ 3. bun run dev`;
9158
9194
  Me(
9159
9195
  `Next steps:
9160
9196
 
9161
9197
  1. cd apps/${appName}
9162
- 2. bun install
9163
- 3. bun run dev
9198
+ ${firebaseStep}
9164
9199
 
9165
9200
  Happy coding!`,
9166
9201
  "\u{1F4CB} Next Steps"
@@ -9496,6 +9531,8 @@ async function main(options) {
9496
9531
  overwrite: true
9497
9532
  });
9498
9533
  const rootTemplateDir = joinPath(templatesRoot, "root-consumer");
9534
+ const firebaseProjectId = projectName.toLowerCase().replace(/\s+/g, "-");
9535
+ const firebaseRegion = "europe-west1";
9499
9536
  const rootReplacements = {
9500
9537
  projectName,
9501
9538
  appNames: isMergeMode ? allAppNames : appNames,
@@ -9504,12 +9541,22 @@ async function main(options) {
9504
9541
  monorepoRelativePath: relativeMonorepoPath,
9505
9542
  appTemplate: "vite",
9506
9543
  isNextjs: false,
9507
- firebaseProjectId: projectName.toLowerCase(),
9544
+ firebaseProjectId,
9545
+ firebaseRegion,
9508
9546
  firebaseSecretName: projectName.toUpperCase().replace(/-/g, "_"),
9547
+ YOUR_FIREBASE_PROJECT_ID: firebaseProjectId,
9548
+ YOUR_REGION: firebaseRegion,
9509
9549
  needsAuth,
9510
9550
  needsOAuth,
9511
9551
  needsBilling
9512
9552
  };
9553
+ const firebaseRootFiles = /* @__PURE__ */ new Set([
9554
+ "firebase.json.example",
9555
+ ".firebaserc.example",
9556
+ "firestore.rules.example",
9557
+ "firestore.indexes.json.example",
9558
+ "storage.rules.example"
9559
+ ]);
9513
9560
  const files = await glob("**/*", {
9514
9561
  cwd: rootTemplateDir,
9515
9562
  dot: true,
@@ -9517,6 +9564,7 @@ async function main(options) {
9517
9564
  });
9518
9565
  for (const file of files) {
9519
9566
  if (file === "package.json.example") continue;
9567
+ if (firebaseRootFiles.has(file)) continue;
9520
9568
  const sourcePath = joinPath(rootTemplateDir, file);
9521
9569
  let destFileName = file;
9522
9570
  if (destFileName.endsWith(".example")) {
@@ -9591,6 +9639,8 @@ async function main(options) {
9591
9639
  }
9592
9640
  }
9593
9641
  if (installDemoApp) {
9642
+ const demoFirebaseProjectId = projectName.toLowerCase().replace(/\s+/g, "-");
9643
+ const demoFirebaseRegion = "europe-west1";
9594
9644
  await copyTemplateFiles(demoTemplateDir, demoAppDir, {
9595
9645
  projectName,
9596
9646
  appName: "demo",
@@ -9598,8 +9648,11 @@ async function main(options) {
9598
9648
  needsCRUD: false,
9599
9649
  setupGithubActions: false,
9600
9650
  appNames,
9601
- firebaseProjectId: projectName.toLowerCase(),
9651
+ firebaseProjectId: demoFirebaseProjectId,
9652
+ firebaseRegion: demoFirebaseRegion,
9602
9653
  firebaseSecretName: projectName.toUpperCase().replace(/-/g, "_"),
9654
+ YOUR_FIREBASE_PROJECT_ID: demoFirebaseProjectId,
9655
+ YOUR_REGION: demoFirebaseRegion,
9603
9656
  monorepoRelativePath: executionMode === "development" ? calculateRelativePath(projectDirNormalized, monorepoRoot) : "",
9604
9657
  appTemplate: "demo"
9605
9658
  });
@@ -163,7 +163,7 @@ var require_picocolors = __commonJS({
163
163
  }
164
164
  });
165
165
 
166
- // node_modules/.bun/@clack+core@0.5.0/node_modules/@clack/core/dist/index.mjs
166
+ // node_modules/.bun/@clack+prompts@0.11.0/node_modules/@clack/prompts/node_modules/@clack/core/dist/index.mjs
167
167
  import { stdin as j, stdout as M } from "node:process";
168
168
  import * as g from "node:readline";
169
169
  import O from "node:readline";
@@ -279,7 +279,7 @@ function fD({ input: e2 = j, output: u2 = M, overwrite: t = true, hideCursor: F2
279
279
  }
280
280
  var import_sisteransi, import_picocolors, uD, W, tD, eD, FD, sD, w, N, I, R, r, iD, CD, ED, d, oD, y, V, nD, G, _, z, K, aD, k, hD, lD, xD, B, AD, S, gD, vD, h, x, dD, A, OD, PD, J, LD, RD;
281
281
  var init_dist = __esm({
282
- "node_modules/.bun/@clack+core@0.5.0/node_modules/@clack/core/dist/index.mjs"() {
282
+ "node_modules/.bun/@clack+prompts@0.11.0/node_modules/@clack/prompts/node_modules/@clack/core/dist/index.mjs"() {
283
283
  init_utils();
284
284
  import_sisteransi = __toESM(require_src(), 1);
285
285
  import_picocolors = __toESM(require_picocolors(), 1);
@@ -7880,7 +7880,7 @@ async function askForInput(message, defaultValue = "") {
7880
7880
  const result = await he({
7881
7881
  message,
7882
7882
  placeholder: defaultValue || void 0,
7883
- defaultValue: defaultValue || void 0
7883
+ initialValue: defaultValue || void 0
7884
7884
  });
7885
7885
  if (pD(result)) {
7886
7886
  xe("Operation cancelled.");
@@ -7960,8 +7960,10 @@ function executeFirebaseCommand(args, options) {
7960
7960
  errorOutput
7961
7961
  };
7962
7962
  }
7963
- function buildFirebaseDeployArgs(deployType, projectId, debug, force) {
7964
- const args = ["deploy", "--only", deployType, "--non-interactive"];
7963
+ function buildFirebaseDeployArgs(deployTargets, projectId, debug, force) {
7964
+ const targets = Array.isArray(deployTargets) ? deployTargets : [deployTargets];
7965
+ const targetString = targets.join(",");
7966
+ const args = ["deploy", "--only", targetString, "--non-interactive"];
7965
7967
  if (projectId) {
7966
7968
  args.push("--project", projectId);
7967
7969
  }
@@ -8523,6 +8525,47 @@ To fix this, run:
8523
8525
  }
8524
8526
  }
8525
8527
 
8528
+ // packages/tooling/src/apps/deploy-rules.ts
8529
+ init_utils();
8530
+ async function deployRules(appDir, serviceAccountPath, projectId, config, options) {
8531
+ const targets = [];
8532
+ if (options.firestore) {
8533
+ targets.push("firestore:rules");
8534
+ }
8535
+ if (options.firestoreIndexes) {
8536
+ targets.push("firestore:indexes");
8537
+ }
8538
+ if (options.storage) {
8539
+ targets.push("storage");
8540
+ }
8541
+ if (targets.length === 0) {
8542
+ return;
8543
+ }
8544
+ const targetNames = targets.join(", ");
8545
+ const s = Y2();
8546
+ s.start(`Deploying ${targetNames}...`);
8547
+ const args = buildFirebaseDeployArgs(targets, projectId, config.debug);
8548
+ const result = executeFirebaseCommand(args, {
8549
+ cwd: appDir,
8550
+ serviceAccountPath,
8551
+ projectId,
8552
+ debug: config.debug
8553
+ });
8554
+ if (result.error) {
8555
+ s.stop("Rules deployment failed");
8556
+ throw result.error;
8557
+ }
8558
+ if (!result.success) {
8559
+ s.stop("Rules deployment failed");
8560
+ handleDeploymentFailure(
8561
+ result,
8562
+ `firebase ${args.join(" ")}`,
8563
+ serviceAccountPath
8564
+ );
8565
+ }
8566
+ s.stop(`${targetNames} deployed successfully`);
8567
+ }
8568
+
8526
8569
  // packages/tooling/src/apps/deploy-utils.ts
8527
8570
  init_utils();
8528
8571
  import { spawnSync as spawnSync3 } from "node:child_process";
@@ -8643,6 +8686,9 @@ function validateFirebaseJson(appDir) {
8643
8686
  valid: false,
8644
8687
  hasHosting: false,
8645
8688
  hasFunctions: false,
8689
+ hasFirestoreRules: false,
8690
+ hasFirestoreIndexes: false,
8691
+ hasStorageRules: false,
8646
8692
  errors: [`firebase.json not found at: ${firebaseJsonPath}`]
8647
8693
  };
8648
8694
  }
@@ -8655,11 +8701,17 @@ function validateFirebaseJson(appDir) {
8655
8701
  }
8656
8702
  const hasHosting = !!config.hosting;
8657
8703
  const hasFunctions = !!config.functions && Array.isArray(config.functions);
8704
+ const hasFirestoreRules = !!config.firestore?.rules && pathExists(joinPath(appDir, config.firestore.rules));
8705
+ const hasFirestoreIndexes = !!config.firestore?.indexes && pathExists(joinPath(appDir, config.firestore.indexes));
8706
+ const hasStorageRules = !!config.storage?.rules && pathExists(joinPath(appDir, config.storage.rules));
8658
8707
  return {
8659
8708
  valid: true,
8660
8709
  projectId: config.projectId,
8661
8710
  hasHosting,
8662
8711
  hasFunctions,
8712
+ hasFirestoreRules,
8713
+ hasFirestoreIndexes,
8714
+ hasStorageRules,
8663
8715
  errors: []
8664
8716
  };
8665
8717
  } catch (error2) {
@@ -8667,6 +8719,9 @@ function validateFirebaseJson(appDir) {
8667
8719
  valid: false,
8668
8720
  hasHosting: false,
8669
8721
  hasFunctions: false,
8722
+ hasFirestoreRules: false,
8723
+ hasFirestoreIndexes: false,
8724
+ hasStorageRules: false,
8670
8725
  errors: [
8671
8726
  `Invalid JSON format: ${error2 instanceof DoNotDevError ? error2.message : error2 instanceof Error ? error2.message : String(error2)}`
8672
8727
  ]
@@ -8831,16 +8886,36 @@ async function main(options = {}) {
8831
8886
  hint: "Deploy cloud functions"
8832
8887
  });
8833
8888
  }
8889
+ const hasRules = firebaseConfig2.hasFirestoreRules || firebaseConfig2.hasFirestoreIndexes || firebaseConfig2.hasStorageRules;
8890
+ if (hasRules) {
8891
+ choices.push({
8892
+ title: "Rules only",
8893
+ value: "rules",
8894
+ hint: "Deploy Firestore/Storage rules"
8895
+ });
8896
+ }
8834
8897
  if (firebaseConfig2.hasHosting && firebaseConfig2.hasFunctions) {
8835
8898
  choices.push({
8836
- title: "Both frontend and functions",
8899
+ title: "Frontend + Functions",
8837
8900
  value: "both",
8838
- hint: "Deploy everything"
8901
+ hint: "Deploy hosting and functions"
8902
+ });
8903
+ }
8904
+ const deployableKindsCount = [
8905
+ firebaseConfig2.hasHosting,
8906
+ firebaseConfig2.hasFunctions,
8907
+ hasRules
8908
+ ].filter(Boolean).length;
8909
+ if (deployableKindsCount > 1) {
8910
+ choices.push({
8911
+ title: "All",
8912
+ value: "all",
8913
+ hint: "Deploy everything (hosting, functions, rules)"
8839
8914
  });
8840
8915
  }
8841
8916
  if (choices.length === 0) {
8842
8917
  log.error(
8843
- "No deployment targets found. firebase.json must have hosting or functions configuration."
8918
+ "No deployment targets found. firebase.json must have hosting, functions, or rules configuration."
8844
8919
  );
8845
8920
  process.exit(1);
8846
8921
  }
@@ -8885,13 +8960,28 @@ async function main(options = {}) {
8885
8960
  showFirebaseJsonError(firebaseConfig.errors, appDir, deploymentType);
8886
8961
  process.exit(1);
8887
8962
  }
8888
- if (deploymentType === "frontend" || deploymentType === "both") {
8889
- if (!firebaseConfig.hasHosting) {
8890
- log.error(
8891
- "firebase.json does not contain hosting configuration, but frontend deployment was requested."
8892
- );
8893
- process.exit(1);
8894
- }
8963
+ const shouldDeployFrontend = (deploymentType === "frontend" || deploymentType === "both" || deploymentType === "all") && firebaseConfig.hasHosting;
8964
+ const shouldDeployFunctions = (deploymentType === "functions" || deploymentType === "both" || deploymentType === "all") && firebaseConfig.hasFunctions;
8965
+ const shouldDeployRules = (deploymentType === "rules" || deploymentType === "all") && (firebaseConfig.hasFirestoreRules || firebaseConfig.hasFirestoreIndexes || firebaseConfig.hasStorageRules);
8966
+ if (deploymentType === "frontend" && !firebaseConfig.hasHosting) {
8967
+ log.error(
8968
+ "firebase.json does not contain hosting configuration, but frontend deployment was requested."
8969
+ );
8970
+ process.exit(1);
8971
+ }
8972
+ if (deploymentType === "functions" && !firebaseConfig.hasFunctions) {
8973
+ log.error(
8974
+ "firebase.json does not contain functions configuration, but functions deployment was requested."
8975
+ );
8976
+ process.exit(1);
8977
+ }
8978
+ if (deploymentType === "rules" && !shouldDeployRules) {
8979
+ log.error(
8980
+ "firebase.json does not contain rules configuration, but rules deployment was requested."
8981
+ );
8982
+ process.exit(1);
8983
+ }
8984
+ if (shouldDeployFrontend) {
8895
8985
  const buildStatus = validateBuild(appDir);
8896
8986
  let shouldBuild = false;
8897
8987
  if (!buildStatus.exists || buildStatus.isEmpty) {
@@ -8934,14 +9024,6 @@ async function main(options = {}) {
8934
9024
  }
8935
9025
  }
8936
9026
  }
8937
- if (deploymentType === "functions" || deploymentType === "both") {
8938
- if (!firebaseConfig.hasFunctions) {
8939
- log.error(
8940
- "firebase.json does not contain functions configuration, but functions deployment was requested."
8941
- );
8942
- process.exit(1);
8943
- }
8944
- }
8945
9027
  clearFirebaseCache(appDir);
8946
9028
  Me(
8947
9029
  `App: ${appName}
@@ -8950,10 +9032,10 @@ Deployment: ${deploymentType}
8950
9032
  Service Account: ${serviceAccountResult.info.clientEmail}`,
8951
9033
  "Deployment Configuration"
8952
9034
  );
8953
- if (deploymentType === "frontend" || deploymentType === "both") {
9035
+ if (shouldDeployFrontend) {
8954
9036
  await deployFrontend(appDir, serviceAccountPath, config.project, config);
8955
9037
  }
8956
- if (deploymentType === "functions" || deploymentType === "both") {
9038
+ if (shouldDeployFunctions) {
8957
9039
  await deployFunctions(
8958
9040
  appDir,
8959
9041
  serviceAccountPath,
@@ -8961,6 +9043,13 @@ Service Account: ${serviceAccountResult.info.clientEmail}`,
8961
9043
  config
8962
9044
  );
8963
9045
  }
9046
+ if (shouldDeployRules) {
9047
+ await deployRules(appDir, serviceAccountPath, config.project, config, {
9048
+ firestore: firebaseConfig.hasFirestoreRules,
9049
+ firestoreIndexes: firebaseConfig.hasFirestoreIndexes,
9050
+ storage: firebaseConfig.hasStorageRules
9051
+ });
9052
+ }
8964
9053
  Se("Deployment completed successfully!");
8965
9054
  } catch (error2) {
8966
9055
  if (error2 instanceof DoNotDevError) {
@@ -163,7 +163,7 @@ var require_picocolors = __commonJS({
163
163
  }
164
164
  });
165
165
 
166
- // node_modules/.bun/@clack+core@0.5.0/node_modules/@clack/core/dist/index.mjs
166
+ // node_modules/.bun/@clack+prompts@0.11.0/node_modules/@clack/prompts/node_modules/@clack/core/dist/index.mjs
167
167
  import { stdin as j, stdout as M } from "node:process";
168
168
  import O from "node:readline";
169
169
  import { Writable as X } from "node:stream";
@@ -254,7 +254,7 @@ function m(e2, u2) {
254
254
  }
255
255
  var import_sisteransi, uD, W, tD, eD, FD, sD, w, N, I, R, r, iD, CD, ED, d, oD, y, V, nD, G, _, z, K, aD, k, hD, lD, xD, B, AD, S, gD, vD, h, x, A, OD, PD, J, LD;
256
256
  var init_dist = __esm({
257
- "node_modules/.bun/@clack+core@0.5.0/node_modules/@clack/core/dist/index.mjs"() {
257
+ "node_modules/.bun/@clack+prompts@0.11.0/node_modules/@clack/prompts/node_modules/@clack/core/dist/index.mjs"() {
258
258
  init_utils();
259
259
  import_sisteransi = __toESM(require_src(), 1);
260
260
  uD = DD();
@@ -163,7 +163,7 @@ var require_picocolors = __commonJS({
163
163
  }
164
164
  });
165
165
 
166
- // node_modules/.bun/@clack+core@0.5.0/node_modules/@clack/core/dist/index.mjs
166
+ // node_modules/.bun/@clack+prompts@0.11.0/node_modules/@clack/prompts/node_modules/@clack/core/dist/index.mjs
167
167
  import { stdin as j, stdout as M } from "node:process";
168
168
  import O from "node:readline";
169
169
  import { Writable as X } from "node:stream";
@@ -257,7 +257,7 @@ function m(e2, u2) {
257
257
  }
258
258
  var import_sisteransi, uD, W, tD, eD, FD, sD, w, N, I, R, r, iD, CD, ED, d, oD, y, V, nD, G, _, z, K, aD, k, hD, lD, xD, B, AD, S, gD, vD, h, x, A, kD, $D, H, SD, OD, PD, J, LD;
259
259
  var init_dist = __esm({
260
- "node_modules/.bun/@clack+core@0.5.0/node_modules/@clack/core/dist/index.mjs"() {
260
+ "node_modules/.bun/@clack+prompts@0.11.0/node_modules/@clack/prompts/node_modules/@clack/core/dist/index.mjs"() {
261
261
  init_utils();
262
262
  import_sisteransi = __toESM(require_src(), 1);
263
263
  uD = DD();
@@ -163,7 +163,7 @@ var require_picocolors = __commonJS({
163
163
  }
164
164
  });
165
165
 
166
- // node_modules/.bun/@clack+core@0.5.0/node_modules/@clack/core/dist/index.mjs
166
+ // node_modules/.bun/@clack+prompts@0.11.0/node_modules/@clack/prompts/node_modules/@clack/core/dist/index.mjs
167
167
  import { stdin as j, stdout as M } from "node:process";
168
168
  import { Writable as X } from "node:stream";
169
169
  function DD({ onlyFirst: e2 = false } = {}) {
@@ -204,7 +204,7 @@ function rD() {
204
204
  }
205
205
  var import_sisteransi, uD, W, tD, eD, FD, sD, w, N, I, R, r, iD, CD, ED, nD, _, xD, B, AD, A;
206
206
  var init_dist = __esm({
207
- "node_modules/.bun/@clack+core@0.5.0/node_modules/@clack/core/dist/index.mjs"() {
207
+ "node_modules/.bun/@clack+prompts@0.11.0/node_modules/@clack/prompts/node_modules/@clack/core/dist/index.mjs"() {
208
208
  init_utils();
209
209
  import_sisteransi = __toESM(require_src(), 1);
210
210
  uD = DD();
@@ -163,7 +163,7 @@ var require_picocolors = __commonJS({
163
163
  }
164
164
  });
165
165
 
166
- // node_modules/.bun/@clack+core@0.5.0/node_modules/@clack/core/dist/index.mjs
166
+ // node_modules/.bun/@clack+prompts@0.11.0/node_modules/@clack/prompts/node_modules/@clack/core/dist/index.mjs
167
167
  import { stdin as j, stdout as M } from "node:process";
168
168
  import { Writable as X } from "node:stream";
169
169
  function DD({ onlyFirst: e2 = false } = {}) {
@@ -204,7 +204,7 @@ function rD() {
204
204
  }
205
205
  var import_sisteransi, uD, W, tD, eD, FD, sD, w, N, I, R, r, iD, CD, ED, nD, _, xD, B, AD, A;
206
206
  var init_dist = __esm({
207
- "node_modules/.bun/@clack+core@0.5.0/node_modules/@clack/core/dist/index.mjs"() {
207
+ "node_modules/.bun/@clack+prompts@0.11.0/node_modules/@clack/prompts/node_modules/@clack/core/dist/index.mjs"() {
208
208
  init_utils();
209
209
  import_sisteransi = __toESM(require_src(), 1);
210
210
  uD = DD();
@@ -163,7 +163,7 @@ var require_picocolors = __commonJS({
163
163
  }
164
164
  });
165
165
 
166
- // node_modules/.bun/@clack+core@0.5.0/node_modules/@clack/core/dist/index.mjs
166
+ // node_modules/.bun/@clack+prompts@0.11.0/node_modules/@clack/prompts/node_modules/@clack/core/dist/index.mjs
167
167
  import { stdin as j, stdout as M } from "node:process";
168
168
  import O from "node:readline";
169
169
  import { Writable as X } from "node:stream";
@@ -254,7 +254,7 @@ function m(e2, u2) {
254
254
  }
255
255
  var import_sisteransi, uD, W, tD, eD, FD, sD, w, N, I, R, r, iD, CD, ED, d, oD, y, V, nD, G, _, z, K, aD, k, hD, lD, xD, B, AD, S, gD, vD, h, x, A, OD, PD, J, LD;
256
256
  var init_dist = __esm({
257
- "node_modules/.bun/@clack+core@0.5.0/node_modules/@clack/core/dist/index.mjs"() {
257
+ "node_modules/.bun/@clack+prompts@0.11.0/node_modules/@clack/prompts/node_modules/@clack/core/dist/index.mjs"() {
258
258
  init_utils();
259
259
  import_sisteransi = __toESM(require_src(), 1);
260
260
  uD = DD();