@donotdev/cli 0.0.13 → 0.0.15

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 (162) hide show
  1. package/dependencies-matrix.json +357 -89
  2. package/dist/bin/commands/agent-setup.d.ts +6 -0
  3. package/dist/bin/commands/agent-setup.d.ts.map +1 -0
  4. package/dist/bin/commands/agent-setup.js +629 -0
  5. package/dist/bin/commands/agent-setup.js.map +1 -0
  6. package/dist/bin/commands/build.js +131 -50
  7. package/dist/bin/commands/bump.js +137 -49
  8. package/dist/bin/commands/cacheout.js +50 -21
  9. package/dist/bin/commands/create-app.js +270 -261
  10. package/dist/bin/commands/create-project.js +418 -197
  11. package/dist/bin/commands/deploy.js +1752 -712
  12. package/dist/bin/commands/dev.js +151 -35
  13. package/dist/bin/commands/emu.js +228 -70
  14. package/dist/bin/commands/format.js +50 -21
  15. package/dist/bin/commands/lint.js +50 -21
  16. package/dist/bin/commands/preview.js +155 -35
  17. package/dist/bin/commands/supabase-setup.d.ts +6 -0
  18. package/dist/bin/commands/supabase-setup.d.ts.map +1 -0
  19. package/dist/bin/commands/supabase-setup.js +7 -0
  20. package/dist/bin/commands/supabase-setup.js.map +1 -0
  21. package/dist/bin/commands/sync-secrets.js +224 -46
  22. package/dist/bin/commands/type-check.d.ts +14 -0
  23. package/dist/bin/commands/type-check.d.ts.map +1 -0
  24. package/dist/bin/commands/type-check.js +314 -0
  25. package/dist/bin/commands/type-check.js.map +1 -0
  26. package/dist/bin/commands/wai.js +7399 -11
  27. package/dist/bin/dndev.js +27 -2
  28. package/dist/bin/donotdev.js +27 -2
  29. package/dist/index.js +3960 -2996
  30. package/package.json +2 -2
  31. package/templates/app-demo/src/App.tsx.example +1 -0
  32. package/templates/app-demo/src/pages/FullPage.tsx.example +2 -2
  33. package/templates/app-demo/src/pages/components/DemoLayout.tsx.example +2 -2
  34. package/templates/app-demo/src/themes.css.example +5 -12
  35. package/templates/app-expo/.env.example +64 -0
  36. package/templates/app-expo/.expo/README.md.example +5 -0
  37. package/templates/app-expo/.gitignore.example +36 -0
  38. package/templates/app-expo/README.md.example +58 -0
  39. package/templates/app-expo/app/.gitkeep +2 -0
  40. package/templates/app-expo/app/_layout.tsx.example +41 -0
  41. package/templates/app-expo/app/form.tsx.example +52 -0
  42. package/templates/app-expo/app/index.tsx.example +89 -0
  43. package/templates/app-expo/app/list.tsx.example +32 -0
  44. package/templates/app-expo/app/profile.tsx.example +76 -0
  45. package/templates/app-expo/app/signin.tsx.example +53 -0
  46. package/templates/app-expo/app.json.example +39 -0
  47. package/templates/app-expo/babel.config.js.example +10 -0
  48. package/templates/app-expo/eas.json.example +20 -0
  49. package/templates/app-expo/expo-env.d.ts.example +4 -0
  50. package/templates/app-expo/metro.config.js.example +20 -0
  51. package/templates/app-expo/service-account-key.json.example +12 -0
  52. package/templates/app-expo/tsconfig.json.example +19 -0
  53. package/templates/app-next/.env.example +4 -33
  54. package/templates/app-next/src/app/ClientLayout.tsx.example +2 -0
  55. package/templates/app-next/src/app/layout.tsx.example +7 -6
  56. package/templates/app-next/src/globals.css.example +2 -11
  57. package/templates/app-next/src/pages/HomePage.tsx.example +1 -1
  58. package/templates/app-next/src/themes.css.example +10 -13
  59. package/templates/app-vite/.env.example +3 -32
  60. package/templates/app-vite/index.html.example +2 -24
  61. package/templates/app-vite/src/App.tsx.example +2 -0
  62. package/templates/app-vite/src/globals.css.example +2 -12
  63. package/templates/app-vite/src/pages/FormPageExample.tsx.example +1 -2
  64. package/templates/app-vite/src/pages/HomePage.tsx.example +1 -1
  65. package/templates/app-vite/src/themes.css.example +109 -79
  66. package/templates/app-vite/vercel.json.example +11 -0
  67. package/templates/functions-firebase/build.mjs.example +2 -72
  68. package/templates/functions-firebase/functions-firebase/.env.example.example +23 -25
  69. package/templates/functions-firebase/functions-firebase/build.mjs.example +2 -72
  70. package/templates/functions-firebase/functions-firebase/tsconfig.json.example +1 -1
  71. package/templates/functions-supabase/supabase/functions/cancel-subscription/index.ts.example +7 -0
  72. package/templates/functions-supabase/supabase/functions/change-plan/index.ts.example +11 -0
  73. package/templates/functions-supabase/supabase/functions/create-checkout-session/index.ts.example +11 -0
  74. package/templates/functions-supabase/supabase/functions/create-customer-portal/index.ts.example +7 -0
  75. package/templates/functions-supabase/supabase/functions/crud/index.ts.example +16 -0
  76. package/templates/functions-supabase/supabase/functions/delete-account/index.ts.example +7 -0
  77. package/templates/functions-supabase/supabase/functions/get-custom-claims/index.ts.example +7 -0
  78. package/templates/functions-supabase/supabase/functions/get-user-auth-status/index.ts.example +7 -0
  79. package/templates/functions-supabase/supabase/functions/refresh-subscription-status/index.ts.example +7 -0
  80. package/templates/functions-supabase/supabase/functions/remove-custom-claims/index.ts.example +7 -0
  81. package/templates/functions-supabase/supabase/functions/set-custom-claims/index.ts.example +7 -0
  82. package/templates/functions-supabase/supabase/migrations/20250101000000_idempotency.sql +24 -0
  83. package/templates/functions-supabase/supabase/migrations/20250101000001_rate_limits.sql +22 -0
  84. package/templates/functions-supabase/supabase/migrations/20250101000002_cleanup_jobs.sql +28 -0
  85. package/templates/functions-supabase/supabase/migrations/20250101000003_operation_metrics.sql +28 -0
  86. package/templates/functions-vercel/functions-vercel/tsconfig.json.example +1 -1
  87. package/templates/functions-vercel/functions-vercel/vercel.json.example +1 -1
  88. package/templates/functions-vercel/vercel.json.example +1 -1
  89. package/templates/github/github/workflows/firebase-deploy.yml.example +1 -1
  90. package/templates/github/workflows/firebase-deploy.yml.example +1 -1
  91. package/templates/overlay-firebase/env.fragment.example +34 -0
  92. package/templates/overlay-firebase/env.fragment.expo.example +34 -0
  93. package/templates/overlay-firebase/env.fragment.nextjs.example +34 -0
  94. package/templates/overlay-firebase/src/config/providers.expo.ts.example +49 -0
  95. package/templates/overlay-firebase/src/config/providers.ts.example +23 -0
  96. package/templates/overlay-supabase/env.fragment.example +7 -0
  97. package/templates/overlay-supabase/env.fragment.expo.example +7 -0
  98. package/templates/overlay-supabase/env.fragment.nextjs.example +7 -0
  99. package/templates/overlay-supabase/src/config/providers.expo.ts.example +35 -0
  100. package/templates/overlay-supabase/src/config/providers.ts.example +33 -0
  101. package/templates/overlay-supabase/vercel.headers.example +23 -0
  102. package/templates/overlay-supabase/vercel.json.example +22 -0
  103. package/templates/overlay-vercel/env.fragment.example +34 -0
  104. package/templates/overlay-vercel/env.fragment.nextjs.example +34 -0
  105. package/templates/overlay-vercel/src/config/providers.ts.example +24 -0
  106. package/templates/root-consumer/.claude/agents/architect.md.example +2 -310
  107. package/templates/root-consumer/.claude/agents/builder.md.example +2 -326
  108. package/templates/root-consumer/.claude/agents/coder.md.example +2 -83
  109. package/templates/root-consumer/.claude/agents/extractor.md.example +2 -231
  110. package/templates/root-consumer/.claude/agents/polisher.md.example +2 -132
  111. package/templates/root-consumer/.claude/agents/prompt-engineer.md.example +2 -81
  112. package/templates/root-consumer/.claude/commands/brainstorm.md.example +1 -1
  113. package/templates/root-consumer/.claude/commands/build.md.example +1 -1
  114. package/templates/root-consumer/.claude/commands/design.md.example +1 -1
  115. package/templates/root-consumer/.claude/commands/grill.md.example +30 -0
  116. package/templates/root-consumer/.claude/commands/polish.md.example +1 -1
  117. package/templates/root-consumer/.claude/commands/techdebt.md.example +28 -0
  118. package/templates/root-consumer/.clinerules.example +1 -0
  119. package/templates/root-consumer/.cursor/rules/no-docs.mdc.example +15 -0
  120. package/templates/root-consumer/.cursorrules.example +1 -0
  121. package/templates/root-consumer/.dndev/args.json.example +6 -0
  122. package/templates/root-consumer/.gemini/settings.json.example +2 -2
  123. package/templates/root-consumer/.github/copilot-instructions.md.example +1 -0
  124. package/templates/root-consumer/.windsurfrules.example +1 -0
  125. package/templates/root-consumer/AI.md.example +25 -108
  126. package/templates/root-consumer/CLAUDE.md.example +1 -128
  127. package/templates/root-consumer/CONVENTIONS.md.example +1 -0
  128. package/templates/root-consumer/GEMINI.md.example +1 -0
  129. package/templates/root-consumer/firebase.json.example +1 -1
  130. package/templates/root-consumer/guides/dndev/AGENT_START_HERE.md.example +54 -0
  131. package/templates/root-consumer/guides/dndev/COMPONENTS_ADV.md.example +0 -18
  132. package/templates/root-consumer/guides/dndev/COMPONENTS_UI.md.example +1 -1
  133. package/templates/root-consumer/guides/dndev/ENV_SETUP.md.example +99 -30
  134. package/templates/root-consumer/guides/dndev/GOTCHAS.md.example +186 -0
  135. package/templates/root-consumer/guides/dndev/INDEX.md.example +4 -1
  136. package/templates/root-consumer/guides/dndev/SETUP_CRUD.md.example +143 -12
  137. package/templates/root-consumer/guides/dndev/SETUP_FIREBASE.md.example +9 -3
  138. package/templates/root-consumer/guides/dndev/SETUP_FUNCTIONS.md.example +12 -7
  139. package/templates/root-consumer/guides/dndev/SETUP_SOC2.md.example +234 -0
  140. package/templates/root-consumer/guides/dndev/SETUP_SUPABASE.md.example +124 -0
  141. package/templates/root-consumer/guides/dndev/SETUP_THEMES.md.example +6 -2
  142. package/templates/root-consumer/guides/dndev/SETUP_VERCEL.md.example +176 -0
  143. package/templates/root-consumer/guides/dndev/USE_ROUTING.md.example +5 -9
  144. package/templates/root-consumer/guides/dndev/essences_reference.css.example +174 -0
  145. package/templates/root-consumer/guides/wai-way/agents/builder.md.example +10 -0
  146. package/templates/root-consumer/guides/wai-way/agents/extractor.md.example +25 -5
  147. package/templates/root-consumer/guides/wai-way/agents/polisher.md.example +13 -2
  148. package/templates/root-consumer/guides/wai-way/blueprints/0_brainstorm.md.example +2 -2
  149. package/templates/root-consumer/guides/wai-way/blueprints/1_scaffold.md.example +47 -11
  150. package/templates/root-consumer/guides/wai-way/blueprints/3_compose.md.example +15 -4
  151. package/templates/root-consumer/guides/wai-way/spec_template.md.example +7 -6
  152. package/templates/app-payload/.env.example +0 -28
  153. package/templates/app-payload/README.md.example +0 -233
  154. package/templates/app-payload/collections/Company.ts.example +0 -125
  155. package/templates/app-payload/collections/Hero.ts.example +0 -62
  156. package/templates/app-payload/collections/Media.ts.example +0 -41
  157. package/templates/app-payload/collections/Products.ts.example +0 -115
  158. package/templates/app-payload/collections/Services.ts.example +0 -104
  159. package/templates/app-payload/collections/Testimonials.ts.example +0 -92
  160. package/templates/app-payload/collections/Users.ts.example +0 -35
  161. package/templates/app-payload/src/server.ts.example +0 -79
  162. package/templates/app-payload/tsconfig.json.example +0 -24
@@ -1975,7 +1975,7 @@ var require_parse = __commonJS({
1975
1975
  CHAR_NO_BREAK_SPACE,
1976
1976
  CHAR_ZERO_WIDTH_NOBREAK_SPACE
1977
1977
  } = require_constants();
1978
- var parse = (input, options = {}) => {
1978
+ var parse2 = (input, options = {}) => {
1979
1979
  if (typeof input !== "string") {
1980
1980
  throw new TypeError("Expected a string");
1981
1981
  }
@@ -2175,7 +2175,7 @@ var require_parse = __commonJS({
2175
2175
  push({ type: "eos" });
2176
2176
  return ast;
2177
2177
  };
2178
- module.exports = parse;
2178
+ module.exports = parse2;
2179
2179
  }
2180
2180
  });
2181
2181
 
@@ -2187,7 +2187,7 @@ var require_braces = __commonJS({
2187
2187
  var stringify2 = require_stringify();
2188
2188
  var compile = require_compile();
2189
2189
  var expand = require_expand();
2190
- var parse = require_parse();
2190
+ var parse2 = require_parse();
2191
2191
  var braces = (input, options = {}) => {
2192
2192
  let output = [];
2193
2193
  if (Array.isArray(input)) {
@@ -2207,7 +2207,7 @@ var require_braces = __commonJS({
2207
2207
  }
2208
2208
  return output;
2209
2209
  };
2210
- braces.parse = (input, options = {}) => parse(input, options);
2210
+ braces.parse = (input, options = {}) => parse2(input, options);
2211
2211
  braces.stringify = (input, options = {}) => {
2212
2212
  if (typeof input === "string") {
2213
2213
  return stringify2(braces.parse(input, options), options);
@@ -2864,7 +2864,7 @@ var require_parse2 = __commonJS({
2864
2864
  var syntaxError = (type, char) => {
2865
2865
  return `Missing ${type}: "${char}" - use "\\\\${char}" to match literal characters`;
2866
2866
  };
2867
- var parse = (input, options) => {
2867
+ var parse2 = (input, options) => {
2868
2868
  if (typeof input !== "string") {
2869
2869
  throw new TypeError("Expected a string");
2870
2870
  }
@@ -3013,7 +3013,7 @@ var require_parse2 = __commonJS({
3013
3013
  output = token.close = `)$))${extglobStar}`;
3014
3014
  }
3015
3015
  if (token.inner.includes("*") && (rest = remaining()) && /^\.[^\\/.]+$/.test(rest)) {
3016
- const expression = parse(rest, { ...options, fastpaths: false }).output;
3016
+ const expression = parse2(rest, { ...options, fastpaths: false }).output;
3017
3017
  output = token.close = `)${expression})${extglobStar})`;
3018
3018
  }
3019
3019
  if (token.prev.type === "bos") {
@@ -3538,7 +3538,7 @@ var require_parse2 = __commonJS({
3538
3538
  }
3539
3539
  return state;
3540
3540
  };
3541
- parse.fastpaths = (input, options) => {
3541
+ parse2.fastpaths = (input, options) => {
3542
3542
  const opts = { ...options };
3543
3543
  const max = typeof opts.maxLength === "number" ? Math.min(MAX_LENGTH, opts.maxLength) : MAX_LENGTH;
3544
3544
  const len = input.length;
@@ -3604,7 +3604,7 @@ var require_parse2 = __commonJS({
3604
3604
  }
3605
3605
  return source;
3606
3606
  };
3607
- module.exports = parse;
3607
+ module.exports = parse2;
3608
3608
  }
3609
3609
  });
3610
3610
 
@@ -3615,7 +3615,7 @@ var require_picomatch = __commonJS({
3615
3615
  init_utils();
3616
3616
  var path = __require("path");
3617
3617
  var scan = require_scan();
3618
- var parse = require_parse2();
3618
+ var parse2 = require_parse2();
3619
3619
  var utils = require_utils2();
3620
3620
  var constants2 = require_constants2();
3621
3621
  var isObject = (val) => val && typeof val === "object" && !Array.isArray(val);
@@ -3703,7 +3703,7 @@ var require_picomatch = __commonJS({
3703
3703
  picomatch.isMatch = (str, patterns, options) => picomatch(patterns, options)(str);
3704
3704
  picomatch.parse = (pattern, options) => {
3705
3705
  if (Array.isArray(pattern)) return pattern.map((p2) => picomatch.parse(p2, options));
3706
- return parse(pattern, { ...options, fastpaths: false });
3706
+ return parse2(pattern, { ...options, fastpaths: false });
3707
3707
  };
3708
3708
  picomatch.scan = (input, options) => scan(input, options);
3709
3709
  picomatch.compileRe = (state, options, returnOutput = false, returnState = false) => {
@@ -3729,10 +3729,10 @@ var require_picomatch = __commonJS({
3729
3729
  }
3730
3730
  let parsed = { negated: false, fastpaths: true };
3731
3731
  if (options.fastpaths !== false && (input[0] === "." || input[0] === "*")) {
3732
- parsed.output = parse.fastpaths(input, options);
3732
+ parsed.output = parse2.fastpaths(input, options);
3733
3733
  }
3734
3734
  if (!parsed.output) {
3735
- parsed = parse(input, options);
3735
+ parsed = parse2(input, options);
3736
3736
  }
3737
3737
  return picomatch.compileRe(parsed, options, returnOutput, returnState);
3738
3738
  };
@@ -7594,11 +7594,39 @@ var init_PathResolver = __esm({
7594
7594
  });
7595
7595
 
7596
7596
  // packages/tooling/src/utils/errors.ts
7597
- var DoNotDevError;
7597
+ var DO_NOT_DEV_ERROR_CODES, DoNotDevError;
7598
7598
  var init_errors = __esm({
7599
7599
  "packages/tooling/src/utils/errors.ts"() {
7600
7600
  "use strict";
7601
7601
  init_utils();
7602
+ DO_NOT_DEV_ERROR_CODES = {
7603
+ CONFIGURATION_ERROR: "configuration-error",
7604
+ CONFIG_NOT_FOUND: "config-not-found",
7605
+ CONFIG_INVALID: "config-invalid",
7606
+ PATH_RESOLUTION_ERROR: "path-resolution-error",
7607
+ FILE_OPERATION_ERROR: "file-operation-error",
7608
+ FILE_NOT_FOUND: "file-not-found",
7609
+ PERMISSION_DENIED: "permission-denied",
7610
+ GENERATION_ERROR: "generation-error",
7611
+ TEMPLATE_ERROR: "template-error",
7612
+ TEMPLATE_NOT_FOUND: "template-not-found",
7613
+ CLI_EXECUTION_ERROR: "cli-execution-error",
7614
+ COMMAND_NOT_FOUND: "command-not-found",
7615
+ COMMAND_FAILED: "command-failed",
7616
+ VALIDATION_ERROR: "validation-error",
7617
+ SCHEMA_ERROR: "schema-error",
7618
+ DEPENDENCY_ERROR: "dependency-error",
7619
+ DEPENDENCY_NOT_FOUND: "dependency-not-found",
7620
+ DEPENDENCY_VERSION_ERROR: "dependency-version-error",
7621
+ INVALID_ARGUMENT: "invalid-argument",
7622
+ MISSING_ARGUMENT: "missing-argument",
7623
+ MISSING_PROJECT_ID: "missing-project-id",
7624
+ FIREBASE_CLI_ERROR: "firebase-cli-error",
7625
+ DEPLOYMENT_FAILED: "deployment-failed",
7626
+ OPERATION_CANCELLED: "operation-cancelled",
7627
+ TIMEOUT_ERROR: "timeout-error",
7628
+ UNKNOWN_ERROR: "unknown-error"
7629
+ };
7602
7630
  DoNotDevError = class _DoNotDevError extends Error {
7603
7631
  /** The error code categorizing this error */
7604
7632
  code;
@@ -7618,7 +7646,7 @@ var init_errors = __esm({
7618
7646
  * @param {Record<string, any>} [options.context] - Additional context data
7619
7647
  * @param {boolean} [options.displayable=true] - Whether this error should be displayed to the user
7620
7648
  */
7621
- constructor(message, code = "unknown-error", options) {
7649
+ constructor(message, code = DO_NOT_DEV_ERROR_CODES.UNKNOWN_ERROR, options) {
7622
7650
  super(message);
7623
7651
  this.name = "DoNotDevError";
7624
7652
  this.code = code;
@@ -7649,7 +7677,7 @@ var init_errors = __esm({
7649
7677
  * @param {boolean} [options.displayable=true] - Whether this error should be displayed to the user
7650
7678
  * @returns {DoNotDevError} New DoNotDev error wrapping the original
7651
7679
  */
7652
- static from(error2, context, code = "unknown-error", options) {
7680
+ static from(error2, context, code = DO_NOT_DEV_ERROR_CODES.UNKNOWN_ERROR, options) {
7653
7681
  if (!(error2 instanceof Error)) {
7654
7682
  return new _DoNotDevError(
7655
7683
  `Unknown error: ${String(error2)}`,
@@ -7686,21 +7714,21 @@ var init_errors = __esm({
7686
7714
  }
7687
7715
  const message = error2.message.toLowerCase();
7688
7716
  if (error2.name === "ValidationError" || message.includes("validation")) {
7689
- return "validation-error";
7717
+ return DO_NOT_DEV_ERROR_CODES.VALIDATION_ERROR;
7690
7718
  }
7691
7719
  if (message.includes("not found") || message.includes("no such file")) {
7692
- return "file-not-found";
7720
+ return DO_NOT_DEV_ERROR_CODES.FILE_NOT_FOUND;
7693
7721
  }
7694
7722
  if (message.includes("permission") || message.includes("access denied")) {
7695
- return "permission-denied";
7723
+ return DO_NOT_DEV_ERROR_CODES.PERMISSION_DENIED;
7696
7724
  }
7697
7725
  if (message.includes("timeout") || message.includes("timed out")) {
7698
- return "timeout-error";
7726
+ return DO_NOT_DEV_ERROR_CODES.TIMEOUT_ERROR;
7699
7727
  }
7700
7728
  if (message.includes("dependency") || message.includes("module not found")) {
7701
- return "dependency-error";
7729
+ return DO_NOT_DEV_ERROR_CODES.DEPENDENCY_ERROR;
7702
7730
  }
7703
- return "unknown-error";
7731
+ return DO_NOT_DEV_ERROR_CODES.UNKNOWN_ERROR;
7704
7732
  }
7705
7733
  };
7706
7734
  }
@@ -7715,6 +7743,7 @@ import {
7715
7743
  extname as extname2,
7716
7744
  relative as relative2,
7717
7745
  resolve as resolve2,
7746
+ parse,
7718
7747
  isAbsolute as pathIsAbsolute
7719
7748
  } from "node:path";
7720
7749
  import { fileURLToPath as fileURLToPath2 } from "node:url";
@@ -7742,6 +7771,52 @@ var init_pathResolver = __esm({
7742
7771
  }
7743
7772
  });
7744
7773
 
7774
+ // packages/tooling/src/utils/typed-file-operations.ts
7775
+ function readFirebaseJson(filePath) {
7776
+ if (!pathExists(filePath)) {
7777
+ throw new DoNotDevError(
7778
+ `firebase.json not found: ${filePath}`,
7779
+ DO_NOT_DEV_ERROR_CODES.FILE_NOT_FOUND,
7780
+ { context: { filePath } }
7781
+ );
7782
+ }
7783
+ const content = readSync(filePath, { format: "json" });
7784
+ if (!content || typeof content !== "object") {
7785
+ throw new DoNotDevError(
7786
+ `Invalid firebase.json: ${filePath}`,
7787
+ DO_NOT_DEV_ERROR_CODES.CONFIG_INVALID,
7788
+ { context: { filePath } }
7789
+ );
7790
+ }
7791
+ return content;
7792
+ }
7793
+ function readPackageJson(filePath) {
7794
+ if (!pathExists(filePath)) {
7795
+ throw new DoNotDevError(
7796
+ `package.json not found: ${filePath}`,
7797
+ DO_NOT_DEV_ERROR_CODES.FILE_NOT_FOUND,
7798
+ { context: { filePath } }
7799
+ );
7800
+ }
7801
+ const content = readSync(filePath, { format: "json" });
7802
+ if (!content || typeof content !== "object" || !("name" in content)) {
7803
+ throw new DoNotDevError(
7804
+ `Invalid package.json: ${filePath}`,
7805
+ DO_NOT_DEV_ERROR_CODES.CONFIG_INVALID,
7806
+ { context: { filePath } }
7807
+ );
7808
+ }
7809
+ return content;
7810
+ }
7811
+ var init_typed_file_operations = __esm({
7812
+ "packages/tooling/src/utils/typed-file-operations.ts"() {
7813
+ "use strict";
7814
+ init_utils();
7815
+ init_pathResolver();
7816
+ init_errors();
7817
+ }
7818
+ });
7819
+
7745
7820
  // packages/tooling/src/bundler/utils.ts
7746
7821
  import { Buffer as Buffer2 } from "node:buffer";
7747
7822
  import { readFileSync as readFileSync2, writeFileSync as writeFileSync2, mkdirSync as mkdirSync2 } from "node:fs";
@@ -7769,6 +7844,33 @@ var init_utils = __esm({
7769
7844
  }
7770
7845
  });
7771
7846
 
7847
+ // packages/tooling/src/utils/cli-input.ts
7848
+ async function askForMultiSelection(message, choices, defaultIndices = []) {
7849
+ const options = choices.map((choice) => ({
7850
+ value: choice.value,
7851
+ label: choice.title,
7852
+ hint: choice.hint
7853
+ }));
7854
+ const initialValues = defaultIndices.map((i) => choices[i]?.value).filter(Boolean);
7855
+ const result = await fe({
7856
+ message,
7857
+ options,
7858
+ initialValues: initialValues.length > 0 ? initialValues : void 0
7859
+ });
7860
+ if (pD(result)) {
7861
+ xe("Operation cancelled.");
7862
+ process.exit(0);
7863
+ }
7864
+ return result;
7865
+ }
7866
+ var init_cli_input = __esm({
7867
+ "packages/tooling/src/utils/cli-input.ts"() {
7868
+ "use strict";
7869
+ init_utils();
7870
+ init_dist2();
7871
+ }
7872
+ });
7873
+
7772
7874
  // packages/cli/src/bin/commands/emu.ts
7773
7875
  init_utils();
7774
7876
 
@@ -7785,6 +7887,7 @@ init_dist2();
7785
7887
  // packages/tooling/src/utils/app-detection.ts
7786
7888
  init_utils();
7787
7889
  init_pathResolver();
7890
+ init_typed_file_operations();
7788
7891
  function detectApps(projectRoot) {
7789
7892
  const apps = [];
7790
7893
  const appsDir = joinPath(projectRoot, "apps");
@@ -7805,9 +7908,7 @@ function detectApps(projectRoot) {
7805
7908
  const packageJsonPath = joinPath(projectRoot, "package.json");
7806
7909
  if (pathExists(packageJsonPath)) {
7807
7910
  try {
7808
- const packageJson = readSync(packageJsonPath, {
7809
- format: "json"
7810
- });
7911
+ const packageJson = readPackageJson(packageJsonPath);
7811
7912
  if (packageJson && (packageJson.dependencies?.vite || packageJson.devDependencies?.vite || packageJson.dependencies?.next || packageJson.devDependencies?.next)) {
7812
7913
  const pathParts = projectRoot.split(/[/\\]/);
7813
7914
  const appName = pathParts[pathParts.length - 1] || "app";
@@ -7827,10 +7928,10 @@ function analyzeApp(appPath, appName) {
7827
7928
  if (!pathExists(packageJsonPath)) {
7828
7929
  return null;
7829
7930
  }
7830
- let packageJson;
7931
+ let packageJson = null;
7831
7932
  try {
7832
- packageJson = readSync(packageJsonPath, { format: "json" });
7833
- if (!packageJson) {
7933
+ packageJson = readPackageJson(packageJsonPath);
7934
+ if (!packageJson.name) {
7834
7935
  return null;
7835
7936
  }
7836
7937
  } catch {
@@ -7845,14 +7946,14 @@ function analyzeApp(appPath, appName) {
7845
7946
  const functionsPath = joinPath(appPath, "functions");
7846
7947
  const functionsStat = statSync2(functionsPath);
7847
7948
  const hasFunctions = pathExists(functionsPath) && (functionsStat?.isDirectory() ?? false);
7848
- let platform;
7949
+ let platform2;
7849
7950
  if (hasFunctions) {
7850
7951
  const firebaseJsonPath = joinPath(functionsPath, "firebase.json");
7851
7952
  const vercelJsonPath = joinPath(appPath, "vercel.json");
7852
7953
  if (pathExists(firebaseJsonPath)) {
7853
- platform = "firebase";
7954
+ platform2 = "firebase";
7854
7955
  } else if (pathExists(vercelJsonPath)) {
7855
- platform = "vercel";
7956
+ platform2 = "vercel";
7856
7957
  }
7857
7958
  }
7858
7959
  return {
@@ -7863,7 +7964,7 @@ function analyzeApp(appPath, appName) {
7863
7964
  framework,
7864
7965
  hasFunctions,
7865
7966
  functionsPath: hasFunctions ? functionsPath : void 0,
7866
- platform
7967
+ platform: platform2
7867
7968
  };
7868
7969
  }
7869
7970
 
@@ -7903,28 +8004,6 @@ async function selectApp(projectRoot, appName) {
7903
8004
  return apps.find((a) => a.name === selected) || null;
7904
8005
  }
7905
8006
 
7906
- // packages/tooling/src/utils/cli-input.ts
7907
- init_utils();
7908
- init_dist2();
7909
- async function askForMultiSelection(message, choices, defaultIndices = []) {
7910
- const options = choices.map((choice) => ({
7911
- value: choice.value,
7912
- label: choice.title,
7913
- hint: choice.hint
7914
- }));
7915
- const initialValues = defaultIndices.map((i) => choices[i]?.value).filter(Boolean);
7916
- const result = await fe({
7917
- message,
7918
- options,
7919
- initialValues: initialValues.length > 0 ? initialValues : void 0
7920
- });
7921
- if (pD(result)) {
7922
- xe("Operation cancelled.");
7923
- process.exit(0);
7924
- }
7925
- return result;
7926
- }
7927
-
7928
8007
  // packages/tooling/src/utils/spawn-utils.ts
7929
8008
  init_utils();
7930
8009
  import { spawnSync, execSync } from "node:child_process";
@@ -7969,16 +8048,24 @@ function createEmulatorEnv(appPath, framework = "vite", options) {
7969
8048
 
7970
8049
  // packages/tooling/src/apps/emu.ts
7971
8050
  init_utils();
7972
- import { spawnSync as spawnSync2, execSync as execSync2 } from "node:child_process";
8051
+ import {
8052
+ spawn,
8053
+ spawnSync as spawnSync2,
8054
+ execSync as execSync2
8055
+ } from "node:child_process";
8056
+ import { platform } from "node:os";
8057
+ init_cli_input();
7973
8058
  init_cli_output();
7974
8059
  init_errors();
7975
8060
  init_pathResolver();
7976
8061
  init_pathResolver();
8062
+ init_typed_file_operations();
7977
8063
  function discoverFirebaseProjectId(appPath) {
7978
8064
  const firebasercPath = joinPath(appPath, ".firebaserc");
7979
8065
  if (pathExists(firebasercPath)) {
7980
8066
  try {
7981
- const firebaserc = readSync(firebasercPath, { format: "json" });
8067
+ const firebasercRaw = readSync(firebasercPath, { format: "json" });
8068
+ const firebaserc = firebasercRaw && typeof firebasercRaw === "object" ? firebasercRaw : null;
7982
8069
  if (firebaserc?.projects?.default) {
7983
8070
  return firebaserc.projects.default;
7984
8071
  }
@@ -8013,12 +8100,18 @@ function killPorts(ports) {
8013
8100
  }
8014
8101
  } else {
8015
8102
  try {
8016
- const pid = execSync2(`lsof -ti:${port}`, {
8103
+ const output = execSync2(`lsof -ti:${port}`, {
8017
8104
  encoding: "utf-8"
8018
8105
  }).trim();
8019
- if (pid) {
8020
- execSync2(`kill -9 ${pid}`, { stdio: "ignore" });
8021
- log.debug(`Killed process ${pid} on port ${port}`);
8106
+ if (output) {
8107
+ const pids = output.split("\n").filter(Boolean);
8108
+ for (const pid of pids) {
8109
+ try {
8110
+ execSync2(`kill -9 ${pid}`, { stdio: "ignore" });
8111
+ log.debug(`Killed process ${pid} on port ${port}`);
8112
+ } catch {
8113
+ }
8114
+ }
8022
8115
  }
8023
8116
  } catch {
8024
8117
  }
@@ -8205,8 +8298,10 @@ FIREBASE_AUTH_EMULATOR_HOST=${authEmulatorHost}
8205
8298
  let emulatorConfig = null;
8206
8299
  if (pathExists(appFirebaseJson)) {
8207
8300
  try {
8208
- const firebaseConfig = readSync(appFirebaseJson, { format: "json" });
8209
- emulatorConfig = firebaseConfig?.emulators;
8301
+ const firebaseConfig = readFirebaseJson(appFirebaseJson);
8302
+ if (firebaseConfig.emulators) {
8303
+ emulatorConfig = firebaseConfig.emulators;
8304
+ }
8210
8305
  } catch {
8211
8306
  }
8212
8307
  }
@@ -8243,7 +8338,7 @@ FIREBASE_AUTH_EMULATOR_HOST=${authEmulatorHost}
8243
8338
  const concurrentlyArgs = [
8244
8339
  "--kill-others-on-fail",
8245
8340
  "--prefix-colors",
8246
- "cyan,green,yellow",
8341
+ useStripe ? "cyan,green,yellow" : "cyan,green",
8247
8342
  "--prefix",
8248
8343
  "[{name}]",
8249
8344
  "--names",
@@ -8261,15 +8356,78 @@ FIREBASE_AUTH_EMULATOR_HOST=${authEmulatorHost}
8261
8356
  log.info(" stripe trigger checkout.session.completed");
8262
8357
  log.info("");
8263
8358
  }
8264
- const result = spawnSync2("bunx", ["concurrently", ...concurrentlyArgs], {
8265
- stdio: "inherit",
8266
- env: createEmulatorEnv(app.path, app.framework, {
8267
- useEmulatorAuth: useAuth,
8268
- useEmulatorFirestore: useFirestore
8269
- }),
8270
- cwd: app.path
8359
+ const isWindows = platform() === "win32";
8360
+ const childProcess = spawn(
8361
+ "bunx",
8362
+ ["concurrently", ...concurrentlyArgs],
8363
+ {
8364
+ stdio: "inherit",
8365
+ env: createEmulatorEnv(app.path, app.framework, {
8366
+ useEmulatorAuth: useAuth,
8367
+ useEmulatorFirestore: useFirestore
8368
+ }),
8369
+ cwd: app.path,
8370
+ shell: isWindows
8371
+ }
8372
+ );
8373
+ const SIGNAL_EXIT_CODES = {
8374
+ SIGINT: 130,
8375
+ // 128 + 2
8376
+ SIGTERM: 143
8377
+ // 128 + 15
8378
+ };
8379
+ const cleanup = (signal) => {
8380
+ if (!childProcess.pid) return;
8381
+ log.debug(`Received ${signal}, cleaning up processes...`);
8382
+ if (isWindows) {
8383
+ try {
8384
+ execSync2(`taskkill /F /T /PID ${childProcess.pid}`, {
8385
+ stdio: "ignore",
8386
+ timeout: 2e3
8387
+ });
8388
+ } catch {
8389
+ }
8390
+ } else {
8391
+ try {
8392
+ process.kill(childProcess.pid, signal);
8393
+ } catch {
8394
+ }
8395
+ try {
8396
+ execSync2(`pkill -P ${childProcess.pid}`, {
8397
+ stdio: "ignore",
8398
+ timeout: 1e3
8399
+ });
8400
+ } catch {
8401
+ }
8402
+ }
8403
+ };
8404
+ const signals = ["SIGINT", "SIGTERM"];
8405
+ const handlers = [];
8406
+ for (const signal of signals) {
8407
+ const handler = () => {
8408
+ cleanup(signal);
8409
+ handlers.forEach((h2) => h2());
8410
+ process.exit(SIGNAL_EXIT_CODES[signal] ?? 130);
8411
+ };
8412
+ process.on(signal, handler);
8413
+ handlers.push(() => process.removeListener(signal, handler));
8414
+ }
8415
+ return new Promise((resolve4) => {
8416
+ childProcess.on("exit", (code, signal) => {
8417
+ handlers.forEach((h2) => h2());
8418
+ if (signal) {
8419
+ log.debug(`Process killed by signal: ${signal}`);
8420
+ resolve4(SIGNAL_EXIT_CODES[signal] ?? 130);
8421
+ } else {
8422
+ resolve4(code ?? 0);
8423
+ }
8424
+ });
8425
+ childProcess.on("error", (error2) => {
8426
+ handlers.forEach((h2) => h2());
8427
+ log.error(`Failed to start emulators: ${error2.message}`);
8428
+ resolve4(1);
8429
+ });
8271
8430
  });
8272
- return result.status || 0;
8273
8431
  }
8274
8432
  export {
8275
8433
  main