@donotdev/cli 0.0.15 → 0.0.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/dependencies-matrix.json +36 -20
  2. package/dist/bin/commands/build.js +69 -52
  3. package/dist/bin/commands/bump.js +7 -13
  4. package/dist/bin/commands/create-app.js +77 -29
  5. package/dist/bin/commands/create-project.js +109 -135
  6. package/dist/bin/commands/deploy.js +97 -45
  7. package/dist/bin/commands/dev.js +43 -24
  8. package/dist/bin/commands/doctor.d.ts +6 -0
  9. package/dist/bin/commands/doctor.d.ts.map +1 -0
  10. package/dist/bin/commands/{lint.js → doctor.js} +1178 -147
  11. package/dist/bin/commands/doctor.js.map +1 -0
  12. package/dist/bin/commands/emu.js +297 -107
  13. package/dist/bin/commands/make-admin.js +77499 -11
  14. package/dist/bin/commands/preview.js +44 -25
  15. package/dist/bin/commands/setup.d.ts +6 -0
  16. package/dist/bin/commands/setup.d.ts.map +1 -0
  17. package/dist/bin/commands/setup.js +11733 -0
  18. package/dist/bin/commands/setup.js.map +1 -0
  19. package/dist/bin/commands/type-check.js +2018 -283
  20. package/dist/bin/dndev.js +54 -58
  21. package/dist/bin/donotdev.js +28 -44
  22. package/dist/index.js +633 -416
  23. package/package.json +2 -2
  24. package/templates/app-expo/.env.example +2 -22
  25. package/templates/app-expo/README.md.example +1 -1
  26. package/templates/app-expo/assets/adaptive-icon.png +0 -0
  27. package/templates/app-expo/assets/favicon.png +0 -0
  28. package/templates/app-expo/assets/icon.png +0 -0
  29. package/templates/app-expo/assets/splash.png +0 -0
  30. package/templates/app-expo/src/config/app.ts.example +46 -0
  31. package/templates/app-expo/src/config/providers.ts.example +7 -0
  32. package/templates/app-next/src/config/providers.ts.example +7 -0
  33. package/templates/app-vite/src/config/providers.ts.example +7 -0
  34. package/templates/app-vite/src/pages/HomePage.tsx.example +1 -1
  35. package/templates/functions-firebase/README.md.example +1 -1
  36. package/templates/functions-firebase/functions-firebase/.env.example.example +1 -1
  37. package/templates/functions-firebase/functions-firebase/README.md.example +1 -1
  38. package/templates/functions-firebase/functions-firebase/tsconfig.json.example +1 -1
  39. package/templates/functions-firebase/functions.config.js.example +1 -1
  40. package/templates/functions-supabase/supabase/config.toml.example +59 -0
  41. package/templates/functions-supabase/supabase/functions/.env.example +13 -0
  42. package/templates/functions-supabase/supabase/functions/deno.json.example +8 -0
  43. package/templates/overlay-firebase/env.fragment.example +1 -1
  44. package/templates/overlay-firebase/env.fragment.expo.example +1 -1
  45. package/templates/overlay-firebase/env.fragment.nextjs.example +1 -1
  46. package/templates/overlay-supabase/env.fragment.example +8 -3
  47. package/templates/overlay-supabase/env.fragment.expo.example +8 -3
  48. package/templates/overlay-supabase/env.fragment.nextjs.example +8 -3
  49. package/templates/overlay-vercel/env.fragment.example +1 -1
  50. package/templates/overlay-vercel/env.fragment.nextjs.example +1 -1
  51. package/templates/root-consumer/AI.md.example +15 -0
  52. package/templates/root-consumer/guides/dndev/AGENT_START_HERE.md.example +2 -2
  53. package/templates/root-consumer/guides/dndev/ENV_SETUP.md.example +6 -6
  54. package/templates/root-consumer/guides/dndev/INDEX.md.example +2 -2
  55. package/templates/root-consumer/guides/dndev/SETUP_APP_CONFIG.md.example +3 -3
  56. package/templates/root-consumer/guides/dndev/SETUP_CRUD.md.example +98 -0
  57. package/templates/root-consumer/guides/dndev/SETUP_FIREBASE.md.example +4 -4
  58. package/templates/root-consumer/guides/dndev/SETUP_OAUTH_PROVIDERS.md.example +60 -0
  59. package/templates/root-consumer/guides/dndev/SETUP_STRIPE.md.example +62 -0
  60. package/templates/root-consumer/guides/dndev/SETUP_SUPABASE.md.example +3 -3
  61. package/templates/root-consumer/guides/dndev/SETUP_VERCEL.md.example +2 -2
  62. package/templates/root-consumer/guides/wai-way/WAI_WAY_CLI.md.example +7 -8
  63. package/templates/root-consumer/guides/wai-way/blueprints/1_scaffold.md.example +9 -5
  64. package/dist/bin/commands/lint.d.ts +0 -11
  65. package/dist/bin/commands/lint.d.ts.map +0 -1
  66. package/dist/bin/commands/lint.js.map +0 -1
  67. package/dist/bin/commands/staging.d.ts +0 -11
  68. package/dist/bin/commands/staging.d.ts.map +0 -1
  69. package/dist/bin/commands/staging.js +0 -12
  70. package/dist/bin/commands/staging.js.map +0 -1
@@ -2,7 +2,7 @@
2
2
  "$schema": "./dependencies-matrix.schema.json",
3
3
  "version": "0.0.6",
4
4
  "description": "Centralized dependency versions for DoNotDev framework. Single source of truth for all external dependencies. ⚠️ SYNC REQUIRED: When adding/removing @donotdev/* feature packages (auth, billing, crud, oauth), also update packages/core/config/constants.js BUNDLING.optionalFeatures array.",
5
- "lastUpdated": "2026-02-18",
5
+ "lastUpdated": "2026-02-23",
6
6
  "migrationGuides": {
7
7
  "0.0→0.1": {
8
8
  "path": "docs/migration/v0.0-to-v0.1.md",
@@ -17,79 +17,79 @@
17
17
  "@donotdev/adv-comps": {
18
18
  "description": "Advanced components package",
19
19
  "packages": {
20
- "@donotdev/adv-comps": "^0.0.11"
20
+ "@donotdev/adv-comps": "^0.0.13"
21
21
  }
22
22
  },
23
23
  "@donotdev/auth": {
24
24
  "description": "Authentication package",
25
25
  "packages": {
26
- "@donotdev/auth": "^0.0.7"
26
+ "@donotdev/auth": "^0.0.9"
27
27
  }
28
28
  },
29
29
  "@donotdev/billing": {
30
30
  "description": "Billing package",
31
31
  "packages": {
32
- "@donotdev/billing": "^0.0.6"
32
+ "@donotdev/billing": "^0.0.8"
33
33
  }
34
34
  },
35
35
  "@donotdev/components": {
36
36
  "description": "UI components package",
37
37
  "packages": {
38
- "@donotdev/components": "^0.0.17"
38
+ "@donotdev/components": "^0.0.19"
39
39
  }
40
40
  },
41
41
  "@donotdev/core": {
42
42
  "description": "Core framework package",
43
43
  "packages": {
44
- "@donotdev/core": "^0.0.24"
44
+ "@donotdev/core": "^0.0.25"
45
45
  }
46
46
  },
47
47
  "@donotdev/crud": {
48
48
  "description": "CRUD operations package",
49
49
  "packages": {
50
- "@donotdev/crud": "^0.0.15"
50
+ "@donotdev/crud": "^0.0.16"
51
51
  }
52
52
  },
53
53
  "@donotdev/firebase": {
54
54
  "description": "Firebase provider package",
55
55
  "packages": {
56
- "@donotdev/firebase": "^0.0.10"
56
+ "@donotdev/firebase": "^0.0.12"
57
57
  }
58
58
  },
59
59
  "@donotdev/functions": {
60
60
  "description": "Firebase Functions package",
61
61
  "packages": {
62
- "@donotdev/functions": "^0.0.11"
62
+ "@donotdev/functions": "^0.0.12"
63
63
  }
64
64
  },
65
65
  "@donotdev/oauth": {
66
66
  "description": "OAuth package",
67
67
  "packages": {
68
- "@donotdev/oauth": "^0.0.6"
68
+ "@donotdev/oauth": "^0.0.8"
69
69
  }
70
70
  },
71
71
  "@donotdev/templates": {
72
72
  "description": "Page templates package",
73
73
  "packages": {
74
- "@donotdev/templates": "^0.0.9"
74
+ "@donotdev/templates": "^0.0.11"
75
75
  }
76
76
  },
77
77
  "@donotdev/ui": {
78
78
  "description": "UI and routing package",
79
79
  "packages": {
80
- "@donotdev/ui": "^0.0.14"
80
+ "@donotdev/ui": "^0.0.15"
81
81
  }
82
82
  },
83
83
  "@donotdev/expo": {
84
84
  "description": "Expo/React Native components package",
85
85
  "packages": {
86
- "@donotdev/expo": "^0.0.1"
86
+ "@donotdev/expo": "^0.0.2"
87
87
  }
88
88
  },
89
89
  "@donotdev/supabase": {
90
90
  "description": "Supabase provider package",
91
91
  "packages": {
92
- "@donotdev/supabase": "^0.0.1"
92
+ "@donotdev/supabase": "^0.0.2"
93
93
  }
94
94
  },
95
95
  "supabase-js": {
@@ -125,6 +125,12 @@
125
125
  "react-dom": "^19.2.4"
126
126
  }
127
127
  },
128
+ "react-native-only": {
129
+ "description": "React without react-dom for React Native/Expo apps",
130
+ "packages": {
131
+ "react": "^19.2.4"
132
+ }
133
+ },
128
134
  "i18n": {
129
135
  "description": "i18n libraries - auto-installed as transitive deps",
130
136
  "packages": {
@@ -420,13 +426,13 @@
420
426
  "@donotdev/cli": {
421
427
  "description": "Cli package",
422
428
  "packages": {
423
- "@donotdev/cli": "^0.0.15"
429
+ "@donotdev/cli": "^0.0.16"
424
430
  }
425
431
  },
426
432
  "@donotdev/mcp-server": {
427
433
  "description": "MCP server for component type lookups",
428
434
  "packages": {
429
- "@donotdev/mcp-server": "^0.0.4"
435
+ "@donotdev/mcp-server": "^0.0.6"
430
436
  }
431
437
  },
432
438
  "mcp-sdk": {
@@ -448,6 +454,12 @@
448
454
  "@dnd-kit/sortable": "^10.0.0",
449
455
  "@dnd-kit/utilities": "^3.2.2"
450
456
  }
457
+ },
458
+ "@donotdev/security": {
459
+ "description": "Security package",
460
+ "packages": {
461
+ "@donotdev/security": "^0.0.2"
462
+ }
451
463
  }
452
464
  },
453
465
  "overrides": {
@@ -665,12 +677,16 @@
665
677
  "@donotdev/adv-comps": {
666
678
  "peerDependencies": [
667
679
  "react",
668
- "shiki"
680
+ "shiki",
681
+ "lucide-react"
669
682
  ],
670
683
  "dependencies": [],
671
684
  "peerDependenciesMeta": {
672
685
  "shiki": {
673
686
  "optional": true
687
+ },
688
+ "lucide-react": {
689
+ "optional": true
674
690
  }
675
691
  }
676
692
  },
@@ -915,7 +931,7 @@
915
931
  "@donotdev/core",
916
932
  "@donotdev/crud",
917
933
  "@donotdev/oauth",
918
- "react",
934
+ "react-native-only",
919
935
  "zustand",
920
936
  "validation",
921
937
  "react-query"
@@ -940,7 +956,7 @@
940
956
  "@donotdev/core",
941
957
  "@donotdev/crud",
942
958
  "@donotdev/oauth",
943
- "react",
959
+ "react-native-only",
944
960
  "zustand",
945
961
  "validation",
946
962
  "react-query"
@@ -1025,4 +1041,4 @@
1025
1041
  "rule": "If imported in code that gets bundled → dependencies. If externalized in esbuild → devDependencies. If optional/consumer-provided → peerDependencies"
1026
1042
  }
1027
1043
  }
1028
- }
1044
+ }
@@ -7852,53 +7852,7 @@ var init_utils = __esm({
7852
7852
  }
7853
7853
  });
7854
7854
 
7855
- // packages/tooling/src/utils/cli-input.ts
7856
- async function askForSelection(message, choices, defaultValue = 0) {
7857
- const options = choices.map((choice) => ({
7858
- value: choice.value,
7859
- label: choice.title,
7860
- hint: choice.hint
7861
- }));
7862
- const result = await ve({
7863
- message,
7864
- options,
7865
- initialValue: choices[defaultValue]?.value
7866
- });
7867
- if (pD(result)) {
7868
- xe("Operation cancelled.");
7869
- process.exit(0);
7870
- }
7871
- return result;
7872
- }
7873
- var init_cli_input = __esm({
7874
- "packages/tooling/src/utils/cli-input.ts"() {
7875
- "use strict";
7876
- init_utils();
7877
- init_dist2();
7878
- }
7879
- });
7880
-
7881
- // packages/cli/src/bin/commands/build.ts
7882
- init_utils();
7883
-
7884
- // packages/tooling/src/index.ts
7885
- init_utils();
7886
-
7887
- // packages/tooling/src/cli/index.ts
7888
- init_utils();
7889
-
7890
- // packages/tooling/src/apps/build.ts
7891
- init_utils();
7892
- import { spawnSync, execSync } from "node:child_process";
7893
-
7894
- // packages/tooling/src/utils/app-selector.ts
7895
- init_utils();
7896
- init_dist2();
7897
-
7898
7855
  // packages/tooling/src/utils/app-detection.ts
7899
- init_utils();
7900
- init_pathResolver();
7901
- init_typed_file_operations();
7902
7856
  function detectApps(projectRoot) {
7903
7857
  const apps = [];
7904
7858
  const appsDir = joinPath(projectRoot, "apps");
@@ -7958,12 +7912,21 @@ function analyzeApp(appPath, appName) {
7958
7912
  const functionsStat = statSync2(functionsPath);
7959
7913
  const hasFunctions = pathExists(functionsPath) && (functionsStat?.isDirectory() ?? false);
7960
7914
  let platform;
7961
- if (hasFunctions) {
7962
- const firebaseJsonPath = joinPath(functionsPath, "firebase.json");
7915
+ const firebaseJsonInFunctions = hasFunctions && pathExists(joinPath(functionsPath, "firebase.json"));
7916
+ const firebaseJsonInApp = pathExists(joinPath(appPath, "firebase.json"));
7917
+ if (firebaseJsonInFunctions || firebaseJsonInApp) {
7918
+ platform = "firebase";
7919
+ }
7920
+ if (!platform) {
7921
+ const supabaseConfigPath = joinPath(appPath, "supabase", "config.toml");
7922
+ const hasSupabaseDep = !!(packageJson.dependencies?.["@donotdev/supabase"] || packageJson.dependencies?.["@supabase/supabase-js"]);
7923
+ if (pathExists(supabaseConfigPath) || hasSupabaseDep) {
7924
+ platform = "supabase";
7925
+ }
7926
+ }
7927
+ if (!platform) {
7963
7928
  const vercelJsonPath = joinPath(appPath, "vercel.json");
7964
- if (pathExists(firebaseJsonPath)) {
7965
- platform = "firebase";
7966
- } else if (pathExists(vercelJsonPath)) {
7929
+ if (pathExists(vercelJsonPath)) {
7967
7930
  platform = "vercel";
7968
7931
  }
7969
7932
  }
@@ -7978,9 +7941,16 @@ function analyzeApp(appPath, appName) {
7978
7941
  platform
7979
7942
  };
7980
7943
  }
7944
+ var init_app_detection = __esm({
7945
+ "packages/tooling/src/utils/app-detection.ts"() {
7946
+ "use strict";
7947
+ init_utils();
7948
+ init_pathResolver();
7949
+ init_typed_file_operations();
7950
+ }
7951
+ });
7981
7952
 
7982
7953
  // packages/tooling/src/utils/app-selector.ts
7983
- init_cli_output();
7984
7954
  async function selectApp(projectRoot, appName) {
7985
7955
  const apps = detectApps(projectRoot);
7986
7956
  if (apps.length === 0) {
@@ -8014,13 +7984,60 @@ async function selectApp(projectRoot, appName) {
8014
7984
  }
8015
7985
  return apps.find((a) => a.name === selected) || null;
8016
7986
  }
7987
+ var init_app_selector = __esm({
7988
+ "packages/tooling/src/utils/app-selector.ts"() {
7989
+ "use strict";
7990
+ init_utils();
7991
+ init_dist2();
7992
+ init_app_detection();
7993
+ init_cli_output();
7994
+ }
7995
+ });
7996
+
7997
+ // packages/tooling/src/utils/cli-input.ts
7998
+ async function askForSelection(message, choices, defaultValue = 0) {
7999
+ const options = choices.map((choice) => ({
8000
+ value: choice.value,
8001
+ label: choice.title,
8002
+ hint: choice.hint
8003
+ }));
8004
+ const result = await ve({
8005
+ message,
8006
+ options,
8007
+ initialValue: choices[defaultValue]?.value
8008
+ });
8009
+ if (pD(result)) {
8010
+ xe("Operation cancelled.");
8011
+ process.exit(0);
8012
+ }
8013
+ return result;
8014
+ }
8015
+ var init_cli_input = __esm({
8016
+ "packages/tooling/src/utils/cli-input.ts"() {
8017
+ "use strict";
8018
+ init_utils();
8019
+ init_dist2();
8020
+ }
8021
+ });
8022
+
8023
+ // packages/cli/src/bin/commands/build.ts
8024
+ init_utils();
8025
+
8026
+ // packages/tooling/src/index.ts
8027
+ init_utils();
8028
+
8029
+ // packages/tooling/src/cli/index.ts
8030
+ init_utils();
8017
8031
 
8018
8032
  // packages/tooling/src/apps/build.ts
8033
+ init_utils();
8034
+ init_app_selector();
8019
8035
  init_cli_input();
8020
8036
  init_cli_output();
8021
8037
  init_errors();
8022
8038
  init_pathResolver();
8023
8039
  init_typed_file_operations();
8040
+ import { spawnSync, execSync } from "node:child_process";
8024
8041
  function validateFirebaseJson(appDir) {
8025
8042
  const firebaseJsonPath = joinPath(appDir, "firebase.json");
8026
8043
  if (!pathExists(firebaseJsonPath)) {
@@ -7857,14 +7857,13 @@ function globSync(pattern, options = {}) {
7857
7857
  });
7858
7858
  return results.map((p2) => pathResolverInstance.normalizePath(p2));
7859
7859
  }
7860
- var pathResolverInstance, getRepoRoot, getAppRoot, resolveFrameworkPackage, normalizePath, pathExists, read, readSync, write, writeSync, ensureDir, getRelativePathBetween, getDirname, joinPath;
7860
+ var pathResolverInstance, getAppRoot, resolveFrameworkPackage, normalizePath, pathExists, read, readSync, write, writeSync, ensureDir, getRelativePathBetween, getDirname, joinPath;
7861
7861
  var init_pathResolver = __esm({
7862
7862
  "packages/tooling/src/utils/pathResolver.ts"() {
7863
7863
  "use strict";
7864
7864
  init_utils();
7865
7865
  init_PathResolver();
7866
7866
  pathResolverInstance = PathResolver.getInstance({ debug: false });
7867
- getRepoRoot = () => pathResolverInstance.getRepoRoot();
7868
7867
  getAppRoot = () => pathResolverInstance.getAppRoot();
7869
7868
  resolveFrameworkPackage = (name, from) => pathResolverInstance.resolveFrameworkPackage(name, from || null);
7870
7869
  normalizePath = (...pathSegments) => {
@@ -7977,15 +7976,10 @@ function getMatrixPath(mode) {
7977
7976
  }
7978
7977
  const executionMode = mode || detectExecutionMode();
7979
7978
  if (executionMode === "development") {
7980
- const repoRoot = getRepoRoot();
7981
- if (repoRoot) {
7982
- const devPath = normalizePath(
7983
- repoRoot,
7984
- "packages/cli/dependencies-matrix.json"
7985
- );
7986
- if (pathExists(devPath)) {
7987
- return devPath;
7988
- }
7979
+ const templatesRoot = getTemplatesRoot();
7980
+ const devPath = normalizePath(templatesRoot, "..", "dependencies-matrix.json");
7981
+ if (pathExists(devPath)) {
7982
+ return devPath;
7989
7983
  }
7990
7984
  }
7991
7985
  return null;
@@ -8000,8 +7994,8 @@ function getCliVersion(mode) {
8000
7994
  }
8001
7995
  const executionMode = mode || detectExecutionMode();
8002
7996
  if (executionMode === "development") {
8003
- const repoRoot = getRepoRoot();
8004
- const cliPackageJson = joinPath(repoRoot, "packages/cli/package.json");
7997
+ const templatesRoot = getTemplatesRoot();
7998
+ const cliPackageJson = normalizePath(templatesRoot, "..", "package.json");
8005
7999
  if (pathExists(cliPackageJson)) {
8006
8000
  const pkg = readSync(cliPackageJson, { format: "json" });
8007
8001
  return String(pkg?.version || "0.0.0");
@@ -8393,15 +8393,10 @@ function getMatrixPath(mode) {
8393
8393
  }
8394
8394
  const executionMode = mode || detectExecutionMode();
8395
8395
  if (executionMode === "development") {
8396
- const repoRoot = getRepoRoot();
8397
- if (repoRoot) {
8398
- const devPath = normalizePath(
8399
- repoRoot,
8400
- "packages/cli/dependencies-matrix.json"
8401
- );
8402
- if (pathExists(devPath)) {
8403
- return devPath;
8404
- }
8396
+ const templatesRoot = getTemplatesRoot();
8397
+ const devPath = normalizePath(templatesRoot, "..", "dependencies-matrix.json");
8398
+ if (pathExists(devPath)) {
8399
+ return devPath;
8405
8400
  }
8406
8401
  }
8407
8402
  return null;
@@ -8416,8 +8411,8 @@ function getCliVersion(mode) {
8416
8411
  }
8417
8412
  const executionMode = mode || detectExecutionMode();
8418
8413
  if (executionMode === "development") {
8419
- const repoRoot = getRepoRoot();
8420
- const cliPackageJson = joinPath(repoRoot, "packages/cli/package.json");
8414
+ const templatesRoot = getTemplatesRoot();
8415
+ const cliPackageJson = normalizePath(templatesRoot, "..", "package.json");
8421
8416
  if (pathExists(cliPackageJson)) {
8422
8417
  const pkg = readSync(cliPackageJson, { format: "json" });
8423
8418
  return String(pkg?.version || "0.0.0");
@@ -8706,7 +8701,7 @@ function generatePackageJson(templateName, mode, options = {}) {
8706
8701
  }
8707
8702
  if (templateName.includes("functions")) {
8708
8703
  result.main = "lib/index.js";
8709
- result.engines = { node: "20" };
8704
+ result.engines = { node: "22" };
8710
8705
  if (options.appName) {
8711
8706
  const platform = templateName.includes("vercel") ? "Vercel" : "Firebase";
8712
8707
  result.description = `${options.appName} ${platform} Functions`;
@@ -8753,15 +8748,15 @@ init_utils();
8753
8748
  var MATRIX = [
8754
8749
  { builder: "vite", backend: "none", baseTemplate: "app-vite", overlay: null, deployConfig: null, functionsTemplate: null },
8755
8750
  { builder: "vite", backend: "firebase", baseTemplate: "app-vite", overlay: "overlay-firebase", deployConfig: "firebase", functionsTemplate: "functions-firebase" },
8756
- { builder: "vite", backend: "supabase", baseTemplate: "app-vite", overlay: "overlay-supabase", deployConfig: "vercel-supabase", functionsTemplate: null },
8751
+ { builder: "vite", backend: "supabase", baseTemplate: "app-vite", overlay: "overlay-supabase", deployConfig: "vercel-supabase", functionsTemplate: "functions-supabase" },
8757
8752
  { builder: "vite", backend: "vercel", baseTemplate: "app-vite", overlay: "overlay-vercel", deployConfig: "vercel-vercel", functionsTemplate: "functions-vercel" },
8758
8753
  { builder: "nextjs", backend: "none", baseTemplate: "app-next", overlay: null, deployConfig: null, functionsTemplate: null },
8759
8754
  { builder: "nextjs", backend: "firebase", baseTemplate: "app-next", overlay: "overlay-firebase", deployConfig: "firebase", functionsTemplate: "functions-firebase" },
8760
- { builder: "nextjs", backend: "supabase", baseTemplate: "app-next", overlay: "overlay-supabase", deployConfig: "vercel-supabase", functionsTemplate: null },
8755
+ { builder: "nextjs", backend: "supabase", baseTemplate: "app-next", overlay: "overlay-supabase", deployConfig: "vercel-supabase", functionsTemplate: "functions-supabase" },
8761
8756
  { builder: "nextjs", backend: "vercel", baseTemplate: "app-next", overlay: "overlay-vercel", deployConfig: "vercel-vercel", functionsTemplate: "functions-vercel" },
8762
8757
  { builder: "expo", backend: "none", baseTemplate: "app-expo", overlay: null, deployConfig: null, functionsTemplate: null },
8763
8758
  { builder: "expo", backend: "firebase", baseTemplate: "app-expo", overlay: "overlay-firebase", deployConfig: null, functionsTemplate: "functions-firebase" },
8764
- { builder: "expo", backend: "supabase", baseTemplate: "app-expo", overlay: "overlay-supabase", deployConfig: null, functionsTemplate: null },
8759
+ { builder: "expo", backend: "supabase", baseTemplate: "app-expo", overlay: "overlay-supabase", deployConfig: null, functionsTemplate: "functions-supabase" },
8765
8760
  { builder: "demo", backend: "none", baseTemplate: "app-demo", overlay: null, deployConfig: null, functionsTemplate: null }
8766
8761
  ];
8767
8762
  function comboKey(builder, backend) {
@@ -8936,7 +8931,7 @@ async function createApp(appName, appConfig, workspaceRoot, templatesRoot) {
8936
8931
  if (providersVariant[1] !== appTemplate) continue;
8937
8932
  const destPath2 = joinPath(appDir, "src/config/providers.ts");
8938
8933
  await ensureDir(getDirname(destPath2));
8939
- await copy(joinPath(overlayDir, file), destPath2);
8934
+ await copy(joinPath(overlayDir, file), destPath2, { overwrite: true });
8940
8935
  if (await isTextFile(destPath2)) await replacePlaceholders(destPath2, replacements);
8941
8936
  continue;
8942
8937
  }
@@ -8947,7 +8942,7 @@ async function createApp(appName, appConfig, workspaceRoot, templatesRoot) {
8947
8942
  }
8948
8943
  const destPath = joinPath(appDir, destFileName);
8949
8944
  await ensureDir(getDirname(destPath));
8950
- await copy(sourcePath, destPath);
8945
+ await copy(sourcePath, destPath, { overwrite: true });
8951
8946
  if (await isTextFile(destPath)) {
8952
8947
  await replacePlaceholders(destPath, replacements);
8953
8948
  }
@@ -8990,23 +8985,26 @@ async function createApp(appName, appConfig, workspaceRoot, templatesRoot) {
8990
8985
  overwrite: true
8991
8986
  });
8992
8987
  if (row.functionsTemplate) {
8993
- const functionsRootDir = joinPath(appDir, "functions");
8994
8988
  const functionsTemplateName = row.functionsTemplate;
8995
8989
  const functionsTemplateExists = pathExists(joinPath(templatesRoot, functionsTemplateName));
8996
8990
  if (!functionsTemplateExists) {
8997
8991
  log.warn(`Functions template "${functionsTemplateName}" not found \u2014 skipping functions scaffolding.`);
8998
8992
  } else {
8999
- const functionsPackageJson = generatePackageJson(
9000
- functionsTemplateName,
9001
- executionMode,
9002
- { appName, platform: row.functionsTemplate.replace("functions-", "") }
9003
- );
9004
- const packageJsonPath2 = joinPath(functionsRootDir, "package.json");
9005
- await ensureDir(functionsRootDir);
9006
- await write(packageJsonPath2, functionsPackageJson, {
9007
- format: "json",
9008
- overwrite: true
9009
- });
8993
+ const isSupabaseFunctions = functionsTemplateName === "functions-supabase";
8994
+ const functionsRootDir = isSupabaseFunctions ? appDir : joinPath(appDir, "functions");
8995
+ if (!isSupabaseFunctions) {
8996
+ const functionsPackageJson = generatePackageJson(
8997
+ functionsTemplateName,
8998
+ executionMode,
8999
+ { appName, platform: row.functionsTemplate.replace("functions-", "") }
9000
+ );
9001
+ const packageJsonPath2 = joinPath(functionsRootDir, "package.json");
9002
+ await ensureDir(functionsRootDir);
9003
+ await write(packageJsonPath2, functionsPackageJson, {
9004
+ format: "json",
9005
+ overwrite: true
9006
+ });
9007
+ }
9010
9008
  const templateDir2 = joinPath(templatesRoot, functionsTemplateName);
9011
9009
  const templateFiles2 = await glob("**/*", {
9012
9010
  cwd: templateDir2,
@@ -9039,6 +9037,18 @@ async function createApp(appName, appConfig, workspaceRoot, templatesRoot) {
9039
9037
  await copy(firebaseJsonSource, joinPath(appDir, "firebase.json"));
9040
9038
  const firebaseJsonDest = joinPath(appDir, "firebase.json");
9041
9039
  if (await isTextFile(firebaseJsonDest)) await replacePlaceholders(firebaseJsonDest, replacements);
9040
+ if (appTemplate === "nextjs") {
9041
+ const firebaseJson = readSync(firebaseJsonDest, { format: "json" });
9042
+ if (firebaseJson.hosting?.rewrites) {
9043
+ firebaseJson.hosting.rewrites = firebaseJson.hosting.rewrites.filter(
9044
+ (r2) => r2.destination !== "/index.html"
9045
+ );
9046
+ }
9047
+ if (firebaseJson.hosting) {
9048
+ firebaseJson.hosting.public = "out";
9049
+ }
9050
+ await write(firebaseJsonDest, firebaseJson, { format: "json", overwrite: true });
9051
+ }
9042
9052
  }
9043
9053
  const firebasercSource = joinPath(deploymentTemplateDir, ".firebaserc.example");
9044
9054
  if (pathExists(firebasercSource)) {
@@ -9055,6 +9065,44 @@ async function createApp(appName, appConfig, workspaceRoot, templatesRoot) {
9055
9065
  }
9056
9066
  }
9057
9067
  }
9068
+ if (!deployConfig && backend === "firebase" && row.functionsTemplate) {
9069
+ const firebaseJsonPath = joinPath(appDir, "firebase.json");
9070
+ if (!pathExists(firebaseJsonPath)) {
9071
+ const expoFirebaseJson = {
9072
+ functions: [
9073
+ {
9074
+ source: "functions",
9075
+ codebase: "default",
9076
+ ignore: ["node_modules", ".git", "firebase-debug.log", "firebase-debug.*.log", "**/.*", "**/*.test.ts", "**/__tests__/**"],
9077
+ runtime: "nodejs22"
9078
+ }
9079
+ ],
9080
+ firestore: { rules: "firestore.rules", indexes: "firestore.indexes.json" },
9081
+ storage: { rules: "storage.rules" },
9082
+ emulators: {
9083
+ auth: { port: 9099 },
9084
+ functions: { port: 5001 },
9085
+ firestore: { port: 8080 },
9086
+ storage: { port: 9199 },
9087
+ ui: { enabled: true, port: 4e3 }
9088
+ }
9089
+ };
9090
+ await write(firebaseJsonPath, expoFirebaseJson, { format: "json", overwrite: true });
9091
+ }
9092
+ const firebasercSource = joinPath(deploymentTemplateDir, ".firebaserc.example");
9093
+ const firebasercDest = joinPath(appDir, ".firebaserc");
9094
+ if (pathExists(firebasercSource) && !pathExists(firebasercDest)) {
9095
+ await copy(firebasercSource, firebasercDest);
9096
+ if (await isTextFile(firebasercDest)) await replacePlaceholders(firebasercDest, replacements);
9097
+ }
9098
+ for (const example of ["firestore.rules.example", "firestore.indexes.json.example", "storage.rules.example"]) {
9099
+ const src = joinPath(deploymentTemplateDir, example);
9100
+ const dest = joinPath(appDir, example.replace(".example", ""));
9101
+ if (pathExists(src) && !pathExists(dest)) {
9102
+ await copy(src, dest);
9103
+ }
9104
+ }
9105
+ }
9058
9106
  if (deployConfig === "vercel-vercel") {
9059
9107
  const vercelJsonSource = joinPath(deploymentTemplateDir, "vercel.json.example");
9060
9108
  if (pathExists(vercelJsonSource)) {