@donotdev/cli 0.0.7 → 0.0.9

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 (37) hide show
  1. package/README.md +3 -18
  2. package/dependencies-matrix.json +54 -45
  3. package/dist/bin/commands/build.js +19 -5
  4. package/dist/bin/commands/bump.js +30 -5
  5. package/dist/bin/commands/cacheout.js +36 -19
  6. package/dist/bin/commands/create-app.js +73 -7
  7. package/dist/bin/commands/create-project.js +90 -8
  8. package/dist/bin/commands/deploy.js +130 -27
  9. package/dist/bin/commands/dev.js +23 -7
  10. package/dist/bin/commands/emu.js +28 -12
  11. package/dist/bin/commands/format.js +39 -22
  12. package/dist/bin/commands/lint.js +36 -19
  13. package/dist/bin/commands/preview.js +24 -8
  14. package/dist/bin/commands/sync-secrets.js +19 -5
  15. package/dist/bin/dndev.js +7 -20
  16. package/dist/bin/donotdev.js +7 -20
  17. package/dist/index.d.ts +1 -1
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js +209 -100
  20. package/dist/index.js.map +1 -1
  21. package/package.json +4 -3
  22. package/templates/app-next/src/config/app.ts.example +1 -1
  23. package/templates/app-vite/index.html.example +24 -2
  24. package/templates/app-vite/src/config/app.ts.example +1 -1
  25. package/templates/app-vite/src/pages/FormPageExample.tsx.example +8 -5
  26. package/templates/app-vite/src/pages/ListPageExample.tsx.example +4 -7
  27. package/templates/root-consumer/.firebaserc.example +5 -0
  28. package/templates/root-consumer/entities/ExampleEntity.ts.example +2 -1
  29. package/templates/root-consumer/entities/demo.ts.example +15 -1
  30. package/templates/root-consumer/eslint.config.js.example +2 -80
  31. package/templates/root-consumer/firestore.indexes.json.example +4 -0
  32. package/templates/root-consumer/firestore.rules.example +11 -0
  33. package/templates/root-consumer/guides/dndev/COMPONENTS_CRUD.md.example +9 -6
  34. package/templates/root-consumer/guides/dndev/SETUP_CRUD.md.example +376 -38
  35. package/templates/root-consumer/guides/dndev/SETUP_I18N.md.example +46 -0
  36. package/templates/root-consumer/guides/wai-way/entity_patterns.md.example +1 -1
  37. package/templates/root-consumer/storage.rules.example +8 -0
@@ -164,6 +164,8 @@ var require_picocolors = __commonJS({
164
164
  });
165
165
 
166
166
  // node_modules/.bun/@clack+core@0.5.0/node_modules/@clack/core/dist/index.mjs
167
+ import { stdin as j, stdout as M } from "node:process";
168
+ import { Writable as X } from "node:stream";
167
169
  function DD({ onlyFirst: e2 = false } = {}) {
168
170
  const t = ["[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]+)*|[a-zA-Z\\d]+(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?(?:\\u0007|\\u001B\\u005C|\\u009C))", "(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-nq-uy=><~]))"].join("|");
169
171
  return new RegExp(t, e2 ? void 0 : "g");
@@ -259,11 +261,12 @@ var init_dist = __esm({
259
261
  });
260
262
 
261
263
  // node_modules/.bun/@clack+prompts@0.11.0/node_modules/@clack/prompts/dist/index.mjs
264
+ import { stripVTControlCharacters as S } from "node:util";
262
265
  import y from "node:process";
263
266
  function ce() {
264
267
  return y.platform !== "win32" ? y.env.TERM !== "linux" : !!y.env.CI || !!y.env.WT_SESSION || !!y.env.TERMINUS_SUBLIME || y.env.ConEmuTask === "{cmd::Cmder}" || y.env.TERM_PROGRAM === "Terminus-Sublime" || y.env.TERM_PROGRAM === "vscode" || y.env.TERM === "xterm-256color" || y.env.TERM === "alacritty" || y.env.TERMINAL_EMULATOR === "JetBrains-JediTerm";
265
268
  }
266
- var import_picocolors, import_sisteransi2, V, u, le, L2, W2, C, ue, o, d, k, P, A2, T, F, $e, _2, me, de, pe, q, D, U, K, M, J;
269
+ var import_picocolors, import_sisteransi2, V, u, le, L2, W2, C, ue, o, d, k, P, A2, T, F, $e, _2, me, de, pe, q, D, U, K, M2, J;
267
270
  var init_dist2 = __esm({
268
271
  "node_modules/.bun/@clack+prompts@0.11.0/node_modules/@clack/prompts/dist/index.mjs"() {
269
272
  init_utils();
@@ -294,7 +297,7 @@ var init_dist2 = __esm({
294
297
  D = u("\u25C6", "*");
295
298
  U = u("\u25B2", "!");
296
299
  K = u("\u25A0", "x");
297
- M = { message: (t = "", { symbol: n = import_picocolors.default.gray(o) } = {}) => {
300
+ M2 = { message: (t = "", { symbol: n = import_picocolors.default.gray(o) } = {}) => {
298
301
  const r2 = [`${import_picocolors.default.gray(o)}`];
299
302
  if (t) {
300
303
  const [i, ...s] = t.split(`
@@ -305,23 +308,24 @@ var init_dist2 = __esm({
305
308
  `)}
306
309
  `);
307
310
  }, info: (t) => {
308
- M.message(t, { symbol: import_picocolors.default.blue(q) });
311
+ M2.message(t, { symbol: import_picocolors.default.blue(q) });
309
312
  }, success: (t) => {
310
- M.message(t, { symbol: import_picocolors.default.green(D) });
313
+ M2.message(t, { symbol: import_picocolors.default.green(D) });
311
314
  }, step: (t) => {
312
- M.message(t, { symbol: import_picocolors.default.green(C) });
315
+ M2.message(t, { symbol: import_picocolors.default.green(C) });
313
316
  }, warn: (t) => {
314
- M.message(t, { symbol: import_picocolors.default.yellow(U) });
317
+ M2.message(t, { symbol: import_picocolors.default.yellow(U) });
315
318
  }, warning: (t) => {
316
- M.warn(t);
319
+ M2.warn(t);
317
320
  }, error: (t) => {
318
- M.message(t, { symbol: import_picocolors.default.red(K) });
321
+ M2.message(t, { symbol: import_picocolors.default.red(K) });
319
322
  } };
320
323
  J = `${import_picocolors.default.gray(o)} `;
321
324
  }
322
325
  });
323
326
 
324
327
  // packages/tooling/src/utils/cli-output.ts
328
+ import "node:os";
325
329
  function supportsColor() {
326
330
  if (process.env.NO_COLOR) return false;
327
331
  if (process.platform === "win32") {
@@ -402,7 +406,7 @@ var init_cli_output = __esm({
402
406
  error(...args) {
403
407
  if (currentLogLevel < 0 /* Quiet */) return;
404
408
  const message = formatMessage(...args);
405
- M.error(colorize(message, colors.brightRed));
409
+ M2.error(colorize(message, colors.brightRed));
406
410
  },
407
411
  /**
408
412
  * Logs a warning message (shows at Normal level and above)
@@ -411,7 +415,7 @@ var init_cli_output = __esm({
411
415
  warn(...args) {
412
416
  if (currentLogLevel < 1 /* Normal */) return;
413
417
  const message = formatMessage(...args);
414
- M.warn(colorize(message, colors.brightYellow));
418
+ M2.warn(colorize(message, colors.brightYellow));
415
419
  },
416
420
  /**
417
421
  * Logs an info message (shows at Normal level and above)
@@ -420,7 +424,7 @@ var init_cli_output = __esm({
420
424
  info(...args) {
421
425
  if (currentLogLevel < 1 /* Normal */) return;
422
426
  const message = formatMessage(...args);
423
- M.info(colorize(message, colors.brightCyan));
427
+ M2.info(colorize(message, colors.brightCyan));
424
428
  },
425
429
  /**
426
430
  * Logs a success message (shows at Normal level and above)
@@ -429,7 +433,7 @@ var init_cli_output = __esm({
429
433
  success(...args) {
430
434
  if (currentLogLevel < 1 /* Normal */) return;
431
435
  const message = formatMessage(...args);
432
- M.success(colorize(message, colors.brightGreen));
436
+ M2.success(colorize(message, colors.brightGreen));
433
437
  },
434
438
  /**
435
439
  * Logs a debug message (only shows at Verbose level and above)
@@ -438,7 +442,7 @@ var init_cli_output = __esm({
438
442
  debug(...args) {
439
443
  if (currentLogLevel < 2 /* Verbose */) return;
440
444
  const timeStamp = (/* @__PURE__ */ new Date()).toISOString().slice(11, 19);
441
- M.message(
445
+ M2.message(
442
446
  colorize(
443
447
  `[${timeStamp}] \u{1F50D} DEBUG: ${formatMessage(...args)}`,
444
448
  colors.gray
@@ -452,7 +456,7 @@ var init_cli_output = __esm({
452
456
  trace(...args) {
453
457
  if (currentLogLevel < 3 /* Debug */) return;
454
458
  const timeStamp = (/* @__PURE__ */ new Date()).toISOString().slice(11, 19);
455
- M.message(
459
+ M2.message(
456
460
  colorize(
457
461
  `[${timeStamp}] \u{1F52C} TRACE: ${formatMessage(...args)}`,
458
462
  colors.gray
@@ -6109,7 +6113,16 @@ var init_constants = __esm({
6109
6113
  },
6110
6114
  i18n: {
6111
6115
  eager: ["src/locales/*_*.json"],
6112
- lazy: ["src/**/locales/*_*.json", "!src/locales/*_*.json"],
6116
+ lazy: [
6117
+ "src/**/locales/*_*.json",
6118
+ "!src/locales/*_*.json",
6119
+ // Auto-detect shared entity translations in monorepos (if exists, use it; if not, no problem)
6120
+ "../../entities/locales/*_*.json"
6121
+ ],
6122
+ // Additional paths from workspace packages (e.g., shared entities)
6123
+ // Consumers can still configure via i18n.additionalPaths in dndev/vite config for custom paths
6124
+ // Example: ['../../packages/shared/locales/*_*.json']
6125
+ additional: [],
6113
6126
  framework: {
6114
6127
  eager: [`${I18N_PATHS.SOURCE_EAGER}/*_*.json`],
6115
6128
  lazy: [`${I18N_PATHS.SOURCE_LAZY}/*_*.json`]
@@ -6202,6 +6215,7 @@ var init_constants = __esm({
6202
6215
 
6203
6216
  // packages/core/config/utils/PathResolver.ts
6204
6217
  import * as fs from "node:fs";
6218
+ import "node:fs";
6205
6219
  import { createRequire } from "node:module";
6206
6220
  import {
6207
6221
  resolve,
@@ -7314,6 +7328,7 @@ var init_errors = __esm({
7314
7328
  });
7315
7329
 
7316
7330
  // packages/tooling/src/utils/pathResolver.ts
7331
+ import { createRequire as createRequire2 } from "node:module";
7317
7332
  import {
7318
7333
  join as join2,
7319
7334
  dirname as dirname2,
@@ -7323,6 +7338,7 @@ import {
7323
7338
  resolve as resolve2,
7324
7339
  isAbsolute as pathIsAbsolute
7325
7340
  } from "node:path";
7341
+ import { fileURLToPath as fileURLToPath2 } from "node:url";
7326
7342
  function readdirSync2(dirPath, options) {
7327
7343
  return pathResolverInstance.readdirSync(dirPath, options);
7328
7344
  }
@@ -7377,16 +7393,17 @@ var init_pathResolver = __esm({
7377
7393
 
7378
7394
  // packages/tooling/src/bundler/utils.ts
7379
7395
  import { Buffer as Buffer2 } from "node:buffer";
7380
- import { createRequire as createRequire2 } from "node:module";
7396
+ import { readFileSync as readFileSync2, writeFileSync as writeFileSync2, mkdirSync as mkdirSync2 } from "node:fs";
7397
+ import { createRequire as createRequire3 } from "node:module";
7381
7398
  import { dirname as dirname3, resolve as resolve3 } from "node:path";
7382
7399
  import process from "node:process";
7383
- import { fileURLToPath as fileURLToPath2 } from "node:url";
7400
+ import { fileURLToPath as fileURLToPath3 } from "node:url";
7384
7401
  var require2, __filename, __dirname;
7385
7402
  var init_utils = __esm({
7386
7403
  "packages/tooling/src/bundler/utils.ts"() {
7387
7404
  "use strict";
7388
- require2 = createRequire2(import.meta.url);
7389
- __filename = fileURLToPath2(import.meta.url);
7405
+ require2 = createRequire3(import.meta.url);
7406
+ __filename = fileURLToPath3(import.meta.url);
7390
7407
  __dirname = dirname3(__filename);
7391
7408
  if (typeof globalThis !== "undefined") {
7392
7409
  globalThis.require = require2;
@@ -822,6 +822,7 @@ __export(cli_output_exports, {
822
822
  success: () => success,
823
823
  warn: () => warn
824
824
  });
825
+ import "node:os";
825
826
  function supportsColor() {
826
827
  if (process.env.NO_COLOR) return false;
827
828
  if (process.platform === "win32") {
@@ -6655,7 +6656,16 @@ var init_constants = __esm({
6655
6656
  },
6656
6657
  i18n: {
6657
6658
  eager: ["src/locales/*_*.json"],
6658
- lazy: ["src/**/locales/*_*.json", "!src/locales/*_*.json"],
6659
+ lazy: [
6660
+ "src/**/locales/*_*.json",
6661
+ "!src/locales/*_*.json",
6662
+ // Auto-detect shared entity translations in monorepos (if exists, use it; if not, no problem)
6663
+ "../../entities/locales/*_*.json"
6664
+ ],
6665
+ // Additional paths from workspace packages (e.g., shared entities)
6666
+ // Consumers can still configure via i18n.additionalPaths in dndev/vite config for custom paths
6667
+ // Example: ['../../packages/shared/locales/*_*.json']
6668
+ additional: [],
6659
6669
  framework: {
6660
6670
  eager: [`${I18N_PATHS.SOURCE_EAGER}/*_*.json`],
6661
6671
  lazy: [`${I18N_PATHS.SOURCE_LAZY}/*_*.json`]
@@ -6748,6 +6758,7 @@ var init_constants = __esm({
6748
6758
 
6749
6759
  // packages/core/config/utils/PathResolver.ts
6750
6760
  import * as fs from "node:fs";
6761
+ import "node:fs";
6751
6762
  import { createRequire } from "node:module";
6752
6763
  import {
6753
6764
  resolve,
@@ -8215,6 +8226,7 @@ var init_pathResolver = __esm({
8215
8226
 
8216
8227
  // packages/tooling/src/bundler/utils.ts
8217
8228
  import { Buffer as Buffer2 } from "node:buffer";
8229
+ import { readFileSync as readFileSync2, writeFileSync as writeFileSync2, mkdirSync as mkdirSync2 } from "node:fs";
8218
8230
  import { createRequire as createRequire3 } from "node:module";
8219
8231
  import { dirname as dirname3, resolve as resolve3 } from "node:path";
8220
8232
  import process from "node:process";
@@ -8681,7 +8693,7 @@ function generatePackageJson(templateName, mode, options = {}) {
8681
8693
  "dependencies-matrix.json not found. This command requires the matrix file."
8682
8694
  );
8683
8695
  }
8684
- const { matrix, cliVersion } = matrixResult;
8696
+ const { matrix } = matrixResult;
8685
8697
  const template = matrix.templateMapping?.[templateName];
8686
8698
  if (!template) {
8687
8699
  throw new Error(`Template "${templateName}" not found in matrix`);
@@ -8745,6 +8757,7 @@ function generatePackageJson(templateName, mode, options = {}) {
8745
8757
  }
8746
8758
  }
8747
8759
  if (templateName.includes("functions")) {
8760
+ result.main = "lib/index.js";
8748
8761
  result.engines = { node: "20" };
8749
8762
  if (options.appName) {
8750
8763
  const platform = templateName.includes("vercel") ? "Vercel" : "Firebase";
@@ -8763,6 +8776,23 @@ function generatePackageJson(templateName, mode, options = {}) {
8763
8776
  }
8764
8777
  }
8765
8778
  }
8779
+ if (mode === "published") {
8780
+ const overrides = {};
8781
+ for (const [groupName, group] of Object.entries(matrix.groups || {})) {
8782
+ if (groupName.startsWith("@donotdev/")) {
8783
+ const version = group.packages?.[groupName];
8784
+ if (version) {
8785
+ overrides[groupName] = version.replace(/^\^/, "");
8786
+ }
8787
+ }
8788
+ }
8789
+ if (matrix.overrides) {
8790
+ Object.assign(overrides, matrix.overrides);
8791
+ }
8792
+ if (Object.keys(overrides).length > 0) {
8793
+ result.overrides = overrides;
8794
+ }
8795
+ }
8766
8796
  return result;
8767
8797
  }
8768
8798
 
@@ -8855,6 +8885,8 @@ async function createApp(appName, appConfig, workspaceRoot, templatesRoot) {
8855
8885
  s.start(`Creating app: ${appName}`);
8856
8886
  await ensureDir(appDir);
8857
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";
8858
8890
  const replacements = {
8859
8891
  projectName: appName,
8860
8892
  appName,
@@ -8863,11 +8895,14 @@ async function createApp(appName, appConfig, workspaceRoot, templatesRoot) {
8863
8895
  needsCRUD: Boolean(appConfig.needsCRUD),
8864
8896
  setupGithubActions: false,
8865
8897
  appNames: [appName],
8866
- firebaseProjectId: appName.toLowerCase(),
8898
+ firebaseProjectId,
8899
+ firebaseRegion,
8867
8900
  firebaseSecretName: appName.toUpperCase().replace(/-/g, "_"),
8868
8901
  monorepoRelativePath: "../../packages/tooling",
8869
8902
  appTemplate,
8870
- isNextjs: appTemplate === "nextjs"
8903
+ isNextjs: appTemplate === "nextjs",
8904
+ YOUR_FIREBASE_PROJECT_ID: firebaseProjectId,
8905
+ YOUR_REGION: firebaseRegion
8871
8906
  };
8872
8907
  const templateSourceDir = joinPath(templatesRoot, templateDir);
8873
8908
  const templateFiles = await glob("**/*", {
@@ -8960,6 +8995,32 @@ async function createApp(appName, appConfig, workspaceRoot, templatesRoot) {
8960
8995
  await replacePlaceholders(firebaseJsonDest, replacements);
8961
8996
  }
8962
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
+ }
8963
9024
  if (appTemplate === "nextjs" || appConfig.needsBackend && appConfig.backendPlatform === "vercel") {
8964
9025
  const vercelJsonSource = joinPath(
8965
9026
  deploymentTemplateDir,
@@ -8985,12 +9046,15 @@ async function createApp(appName, appConfig, workspaceRoot, templatesRoot) {
8985
9046
  }
8986
9047
  if (isInteractive) {
8987
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`;
8988
9053
  Me(
8989
9054
  `Next steps:
8990
9055
 
8991
9056
  1. cd apps/${appName}
8992
- 2. bun install
8993
- 3. bun run dev
9057
+ ${firebaseStep}
8994
9058
 
8995
9059
  Happy coding!`,
8996
9060
  "\u{1F4CB} Next Steps"
@@ -9022,7 +9086,9 @@ async function main(options) {
9022
9086
  selectedEntities: [],
9023
9087
  userAuth: "social",
9024
9088
  billing: true,
9025
- features: []
9089
+ features: [],
9090
+ firebaseProjectId: options.firebaseProjectId,
9091
+ firebaseRegion: options.firebaseRegion
9026
9092
  };
9027
9093
  await createApp(appName, appConfig);
9028
9094
  } else {
@@ -822,6 +822,7 @@ __export(cli_output_exports, {
822
822
  success: () => success,
823
823
  warn: () => warn
824
824
  });
825
+ import "node:os";
825
826
  function supportsColor() {
826
827
  if (process.env.NO_COLOR) return false;
827
828
  if (process.platform === "win32") {
@@ -6655,7 +6656,16 @@ var init_constants = __esm({
6655
6656
  },
6656
6657
  i18n: {
6657
6658
  eager: ["src/locales/*_*.json"],
6658
- lazy: ["src/**/locales/*_*.json", "!src/locales/*_*.json"],
6659
+ lazy: [
6660
+ "src/**/locales/*_*.json",
6661
+ "!src/locales/*_*.json",
6662
+ // Auto-detect shared entity translations in monorepos (if exists, use it; if not, no problem)
6663
+ "../../entities/locales/*_*.json"
6664
+ ],
6665
+ // Additional paths from workspace packages (e.g., shared entities)
6666
+ // Consumers can still configure via i18n.additionalPaths in dndev/vite config for custom paths
6667
+ // Example: ['../../packages/shared/locales/*_*.json']
6668
+ additional: [],
6659
6669
  framework: {
6660
6670
  eager: [`${I18N_PATHS.SOURCE_EAGER}/*_*.json`],
6661
6671
  lazy: [`${I18N_PATHS.SOURCE_LAZY}/*_*.json`]
@@ -6748,6 +6758,7 @@ var init_constants = __esm({
6748
6758
 
6749
6759
  // packages/core/config/utils/PathResolver.ts
6750
6760
  import * as fs from "node:fs";
6761
+ import "node:fs";
6751
6762
  import { createRequire } from "node:module";
6752
6763
  import {
6753
6764
  resolve,
@@ -8215,6 +8226,7 @@ var init_pathResolver = __esm({
8215
8226
 
8216
8227
  // packages/tooling/src/bundler/utils.ts
8217
8228
  import { Buffer as Buffer2 } from "node:buffer";
8229
+ import { readFileSync as readFileSync2, writeFileSync as writeFileSync2, mkdirSync as mkdirSync2 } from "node:fs";
8218
8230
  import { createRequire as createRequire3 } from "node:module";
8219
8231
  import { dirname as dirname3, resolve as resolve3 } from "node:path";
8220
8232
  import process from "node:process";
@@ -8822,7 +8834,7 @@ function generatePackageJson(templateName, mode, options = {}) {
8822
8834
  "dependencies-matrix.json not found. This command requires the matrix file."
8823
8835
  );
8824
8836
  }
8825
- const { matrix, cliVersion } = matrixResult;
8837
+ const { matrix } = matrixResult;
8826
8838
  const template = matrix.templateMapping?.[templateName];
8827
8839
  if (!template) {
8828
8840
  throw new Error(`Template "${templateName}" not found in matrix`);
@@ -8886,6 +8898,7 @@ function generatePackageJson(templateName, mode, options = {}) {
8886
8898
  }
8887
8899
  }
8888
8900
  if (templateName.includes("functions")) {
8901
+ result.main = "lib/index.js";
8889
8902
  result.engines = { node: "20" };
8890
8903
  if (options.appName) {
8891
8904
  const platform = templateName.includes("vercel") ? "Vercel" : "Firebase";
@@ -8904,6 +8917,23 @@ function generatePackageJson(templateName, mode, options = {}) {
8904
8917
  }
8905
8918
  }
8906
8919
  }
8920
+ if (mode === "published") {
8921
+ const overrides = {};
8922
+ for (const [groupName, group] of Object.entries(matrix.groups || {})) {
8923
+ if (groupName.startsWith("@donotdev/")) {
8924
+ const version = group.packages?.[groupName];
8925
+ if (version) {
8926
+ overrides[groupName] = version.replace(/^\^/, "");
8927
+ }
8928
+ }
8929
+ }
8930
+ if (matrix.overrides) {
8931
+ Object.assign(overrides, matrix.overrides);
8932
+ }
8933
+ if (Object.keys(overrides).length > 0) {
8934
+ result.overrides = overrides;
8935
+ }
8936
+ }
8907
8937
  return result;
8908
8938
  }
8909
8939
 
@@ -8996,6 +9026,8 @@ async function createApp(appName, appConfig, workspaceRoot, templatesRoot) {
8996
9026
  s.start(`Creating app: ${appName}`);
8997
9027
  await ensureDir(appDir);
8998
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";
8999
9031
  const replacements = {
9000
9032
  projectName: appName,
9001
9033
  appName,
@@ -9004,11 +9036,14 @@ async function createApp(appName, appConfig, workspaceRoot, templatesRoot) {
9004
9036
  needsCRUD: Boolean(appConfig.needsCRUD),
9005
9037
  setupGithubActions: false,
9006
9038
  appNames: [appName],
9007
- firebaseProjectId: appName.toLowerCase(),
9039
+ firebaseProjectId,
9040
+ firebaseRegion,
9008
9041
  firebaseSecretName: appName.toUpperCase().replace(/-/g, "_"),
9009
9042
  monorepoRelativePath: "../../packages/tooling",
9010
9043
  appTemplate,
9011
- isNextjs: appTemplate === "nextjs"
9044
+ isNextjs: appTemplate === "nextjs",
9045
+ YOUR_FIREBASE_PROJECT_ID: firebaseProjectId,
9046
+ YOUR_REGION: firebaseRegion
9012
9047
  };
9013
9048
  const templateSourceDir = joinPath(templatesRoot, templateDir);
9014
9049
  const templateFiles = await glob("**/*", {
@@ -9101,6 +9136,32 @@ async function createApp(appName, appConfig, workspaceRoot, templatesRoot) {
9101
9136
  await replacePlaceholders(firebaseJsonDest, replacements);
9102
9137
  }
9103
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
+ }
9104
9165
  if (appTemplate === "nextjs" || appConfig.needsBackend && appConfig.backendPlatform === "vercel") {
9105
9166
  const vercelJsonSource = joinPath(
9106
9167
  deploymentTemplateDir,
@@ -9126,12 +9187,15 @@ async function createApp(appName, appConfig, workspaceRoot, templatesRoot) {
9126
9187
  }
9127
9188
  if (isInteractive) {
9128
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`;
9129
9194
  Me(
9130
9195
  `Next steps:
9131
9196
 
9132
9197
  1. cd apps/${appName}
9133
- 2. bun install
9134
- 3. bun run dev
9198
+ ${firebaseStep}
9135
9199
 
9136
9200
  Happy coding!`,
9137
9201
  "\u{1F4CB} Next Steps"
@@ -9467,6 +9531,8 @@ async function main(options) {
9467
9531
  overwrite: true
9468
9532
  });
9469
9533
  const rootTemplateDir = joinPath(templatesRoot, "root-consumer");
9534
+ const firebaseProjectId = projectName.toLowerCase().replace(/\s+/g, "-");
9535
+ const firebaseRegion = "europe-west1";
9470
9536
  const rootReplacements = {
9471
9537
  projectName,
9472
9538
  appNames: isMergeMode ? allAppNames : appNames,
@@ -9475,12 +9541,22 @@ async function main(options) {
9475
9541
  monorepoRelativePath: relativeMonorepoPath,
9476
9542
  appTemplate: "vite",
9477
9543
  isNextjs: false,
9478
- firebaseProjectId: projectName.toLowerCase(),
9544
+ firebaseProjectId,
9545
+ firebaseRegion,
9479
9546
  firebaseSecretName: projectName.toUpperCase().replace(/-/g, "_"),
9547
+ YOUR_FIREBASE_PROJECT_ID: firebaseProjectId,
9548
+ YOUR_REGION: firebaseRegion,
9480
9549
  needsAuth,
9481
9550
  needsOAuth,
9482
9551
  needsBilling
9483
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
+ ]);
9484
9560
  const files = await glob("**/*", {
9485
9561
  cwd: rootTemplateDir,
9486
9562
  dot: true,
@@ -9488,6 +9564,7 @@ async function main(options) {
9488
9564
  });
9489
9565
  for (const file of files) {
9490
9566
  if (file === "package.json.example") continue;
9567
+ if (firebaseRootFiles.has(file)) continue;
9491
9568
  const sourcePath = joinPath(rootTemplateDir, file);
9492
9569
  let destFileName = file;
9493
9570
  if (destFileName.endsWith(".example")) {
@@ -9562,6 +9639,8 @@ async function main(options) {
9562
9639
  }
9563
9640
  }
9564
9641
  if (installDemoApp) {
9642
+ const demoFirebaseProjectId = projectName.toLowerCase().replace(/\s+/g, "-");
9643
+ const demoFirebaseRegion = "europe-west1";
9565
9644
  await copyTemplateFiles(demoTemplateDir, demoAppDir, {
9566
9645
  projectName,
9567
9646
  appName: "demo",
@@ -9569,8 +9648,11 @@ async function main(options) {
9569
9648
  needsCRUD: false,
9570
9649
  setupGithubActions: false,
9571
9650
  appNames,
9572
- firebaseProjectId: projectName.toLowerCase(),
9651
+ firebaseProjectId: demoFirebaseProjectId,
9652
+ firebaseRegion: demoFirebaseRegion,
9573
9653
  firebaseSecretName: projectName.toUpperCase().replace(/-/g, "_"),
9654
+ YOUR_FIREBASE_PROJECT_ID: demoFirebaseProjectId,
9655
+ YOUR_REGION: demoFirebaseRegion,
9574
9656
  monorepoRelativePath: executionMode === "development" ? calculateRelativePath(projectDirNormalized, monorepoRoot) : "",
9575
9657
  appTemplate: "demo"
9576
9658
  });