@donotdev/cli 0.0.14 → 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 (184) hide show
  1. package/dependencies-matrix.json +372 -88
  2. package/dist/bin/commands/agent-setup.js +7 -1
  3. package/dist/bin/commands/build.js +141 -44
  4. package/dist/bin/commands/bump.js +81 -41
  5. package/dist/bin/commands/cacheout.js +37 -9
  6. package/dist/bin/commands/create-app.js +276 -121
  7. package/dist/bin/commands/create-project.js +506 -217
  8. package/dist/bin/commands/deploy.js +1785 -694
  9. package/dist/bin/commands/dev.js +177 -43
  10. package/dist/bin/commands/doctor.d.ts +6 -0
  11. package/dist/bin/commands/doctor.d.ts.map +1 -0
  12. package/dist/bin/commands/{lint.js → doctor.js} +1215 -156
  13. package/dist/bin/commands/doctor.js.map +1 -0
  14. package/dist/bin/commands/emu.js +451 -104
  15. package/dist/bin/commands/format.js +37 -9
  16. package/dist/bin/commands/make-admin.js +77499 -11
  17. package/dist/bin/commands/preview.js +181 -43
  18. package/dist/bin/commands/setup.d.ts +6 -0
  19. package/dist/bin/commands/setup.d.ts.map +1 -0
  20. package/dist/bin/commands/setup.js +11733 -0
  21. package/dist/bin/commands/setup.js.map +1 -0
  22. package/dist/bin/commands/supabase-setup.d.ts +6 -0
  23. package/dist/bin/commands/supabase-setup.d.ts.map +1 -0
  24. package/dist/bin/commands/supabase-setup.js +7 -0
  25. package/dist/bin/commands/supabase-setup.js.map +1 -0
  26. package/dist/bin/commands/sync-secrets.js +211 -34
  27. package/dist/bin/commands/type-check.d.ts +14 -0
  28. package/dist/bin/commands/type-check.d.ts.map +1 -0
  29. package/dist/bin/commands/type-check.js +2049 -0
  30. package/dist/bin/commands/type-check.js.map +1 -0
  31. package/dist/bin/commands/wai.js +3 -1
  32. package/dist/bin/dndev.js +73 -52
  33. package/dist/bin/donotdev.js +54 -45
  34. package/dist/index.js +4212 -3050
  35. package/package.json +3 -3
  36. package/templates/app-demo/src/App.tsx.example +1 -0
  37. package/templates/app-demo/src/pages/FullPage.tsx.example +2 -2
  38. package/templates/app-demo/src/pages/components/DemoLayout.tsx.example +2 -2
  39. package/templates/app-demo/src/themes.css.example +5 -12
  40. package/templates/app-expo/.env.example +44 -0
  41. package/templates/app-expo/.expo/README.md.example +5 -0
  42. package/templates/app-expo/.gitignore.example +36 -0
  43. package/templates/app-expo/README.md.example +58 -0
  44. package/templates/app-expo/app/.gitkeep +2 -0
  45. package/templates/app-expo/app/_layout.tsx.example +41 -0
  46. package/templates/app-expo/app/form.tsx.example +52 -0
  47. package/templates/app-expo/app/index.tsx.example +89 -0
  48. package/templates/app-expo/app/list.tsx.example +32 -0
  49. package/templates/app-expo/app/profile.tsx.example +76 -0
  50. package/templates/app-expo/app/signin.tsx.example +53 -0
  51. package/templates/app-expo/app.json.example +39 -0
  52. package/templates/app-expo/assets/adaptive-icon.png +0 -0
  53. package/templates/app-expo/assets/favicon.png +0 -0
  54. package/templates/app-expo/assets/icon.png +0 -0
  55. package/templates/app-expo/assets/splash.png +0 -0
  56. package/templates/app-expo/babel.config.js.example +10 -0
  57. package/templates/app-expo/eas.json.example +20 -0
  58. package/templates/app-expo/expo-env.d.ts.example +4 -0
  59. package/templates/app-expo/metro.config.js.example +20 -0
  60. package/templates/app-expo/service-account-key.json.example +12 -0
  61. package/templates/app-expo/src/config/app.ts.example +46 -0
  62. package/templates/app-expo/src/config/providers.ts.example +7 -0
  63. package/templates/app-expo/tsconfig.json.example +19 -0
  64. package/templates/app-next/.env.example +4 -33
  65. package/templates/app-next/src/app/ClientLayout.tsx.example +2 -0
  66. package/templates/app-next/src/app/layout.tsx.example +7 -6
  67. package/templates/app-next/src/config/providers.ts.example +7 -0
  68. package/templates/app-next/src/globals.css.example +2 -11
  69. package/templates/app-next/src/pages/HomePage.tsx.example +1 -1
  70. package/templates/app-next/src/themes.css.example +10 -13
  71. package/templates/app-vite/.env.example +3 -32
  72. package/templates/app-vite/index.html.example +2 -24
  73. package/templates/app-vite/src/App.tsx.example +2 -0
  74. package/templates/app-vite/src/config/providers.ts.example +7 -0
  75. package/templates/app-vite/src/globals.css.example +2 -12
  76. package/templates/app-vite/src/pages/FormPageExample.tsx.example +1 -2
  77. package/templates/app-vite/src/pages/HomePage.tsx.example +2 -2
  78. package/templates/app-vite/src/themes.css.example +109 -79
  79. package/templates/app-vite/vercel.json.example +11 -0
  80. package/templates/functions-firebase/README.md.example +1 -1
  81. package/templates/functions-firebase/build.mjs.example +2 -72
  82. package/templates/functions-firebase/functions-firebase/.env.example.example +24 -26
  83. package/templates/functions-firebase/functions-firebase/README.md.example +1 -1
  84. package/templates/functions-firebase/functions-firebase/build.mjs.example +2 -72
  85. package/templates/functions-firebase/functions-firebase/tsconfig.json.example +1 -1
  86. package/templates/functions-firebase/functions.config.js.example +1 -1
  87. package/templates/functions-supabase/supabase/config.toml.example +59 -0
  88. package/templates/functions-supabase/supabase/functions/.env.example +13 -0
  89. package/templates/functions-supabase/supabase/functions/cancel-subscription/index.ts.example +7 -0
  90. package/templates/functions-supabase/supabase/functions/change-plan/index.ts.example +11 -0
  91. package/templates/functions-supabase/supabase/functions/create-checkout-session/index.ts.example +11 -0
  92. package/templates/functions-supabase/supabase/functions/create-customer-portal/index.ts.example +7 -0
  93. package/templates/functions-supabase/supabase/functions/crud/index.ts.example +16 -0
  94. package/templates/functions-supabase/supabase/functions/delete-account/index.ts.example +7 -0
  95. package/templates/functions-supabase/supabase/functions/deno.json.example +8 -0
  96. package/templates/functions-supabase/supabase/functions/get-custom-claims/index.ts.example +7 -0
  97. package/templates/functions-supabase/supabase/functions/get-user-auth-status/index.ts.example +7 -0
  98. package/templates/functions-supabase/supabase/functions/refresh-subscription-status/index.ts.example +7 -0
  99. package/templates/functions-supabase/supabase/functions/remove-custom-claims/index.ts.example +7 -0
  100. package/templates/functions-supabase/supabase/functions/set-custom-claims/index.ts.example +7 -0
  101. package/templates/functions-supabase/supabase/migrations/20250101000000_idempotency.sql +24 -0
  102. package/templates/functions-supabase/supabase/migrations/20250101000001_rate_limits.sql +22 -0
  103. package/templates/functions-supabase/supabase/migrations/20250101000002_cleanup_jobs.sql +28 -0
  104. package/templates/functions-supabase/supabase/migrations/20250101000003_operation_metrics.sql +28 -0
  105. package/templates/functions-vercel/functions-vercel/tsconfig.json.example +1 -1
  106. package/templates/functions-vercel/functions-vercel/vercel.json.example +1 -1
  107. package/templates/functions-vercel/vercel.json.example +1 -1
  108. package/templates/github/github/workflows/firebase-deploy.yml.example +1 -1
  109. package/templates/github/workflows/firebase-deploy.yml.example +1 -1
  110. package/templates/overlay-firebase/env.fragment.example +34 -0
  111. package/templates/overlay-firebase/env.fragment.expo.example +34 -0
  112. package/templates/overlay-firebase/env.fragment.nextjs.example +34 -0
  113. package/templates/overlay-firebase/src/config/providers.expo.ts.example +49 -0
  114. package/templates/overlay-firebase/src/config/providers.ts.example +23 -0
  115. package/templates/overlay-supabase/env.fragment.example +12 -0
  116. package/templates/overlay-supabase/env.fragment.expo.example +12 -0
  117. package/templates/overlay-supabase/env.fragment.nextjs.example +12 -0
  118. package/templates/overlay-supabase/src/config/providers.expo.ts.example +35 -0
  119. package/templates/overlay-supabase/src/config/providers.ts.example +33 -0
  120. package/templates/overlay-supabase/vercel.headers.example +23 -0
  121. package/templates/overlay-supabase/vercel.json.example +22 -0
  122. package/templates/overlay-vercel/env.fragment.example +34 -0
  123. package/templates/overlay-vercel/env.fragment.nextjs.example +34 -0
  124. package/templates/overlay-vercel/src/config/providers.ts.example +24 -0
  125. package/templates/root-consumer/.claude/agents/architect.md.example +2 -310
  126. package/templates/root-consumer/.claude/agents/builder.md.example +2 -326
  127. package/templates/root-consumer/.claude/agents/coder.md.example +2 -83
  128. package/templates/root-consumer/.claude/agents/extractor.md.example +2 -231
  129. package/templates/root-consumer/.claude/agents/polisher.md.example +2 -132
  130. package/templates/root-consumer/.claude/agents/prompt-engineer.md.example +2 -81
  131. package/templates/root-consumer/.claude/commands/grill.md.example +30 -0
  132. package/templates/root-consumer/.claude/commands/techdebt.md.example +28 -0
  133. package/templates/root-consumer/.clinerules.example +1 -0
  134. package/templates/root-consumer/.cursor/rules/no-docs.mdc.example +15 -0
  135. package/templates/root-consumer/.cursorrules.example +1 -0
  136. package/templates/root-consumer/.github/copilot-instructions.md.example +1 -0
  137. package/templates/root-consumer/.windsurfrules.example +1 -0
  138. package/templates/root-consumer/AI.md.example +44 -123
  139. package/templates/root-consumer/CLAUDE.md.example +1 -134
  140. package/templates/root-consumer/CONVENTIONS.md.example +1 -0
  141. package/templates/root-consumer/GEMINI.md.example +1 -0
  142. package/templates/root-consumer/firebase.json.example +1 -1
  143. package/templates/root-consumer/guides/dndev/AGENT_START_HERE.md.example +22 -2
  144. package/templates/root-consumer/guides/dndev/COMPONENTS_ADV.md.example +0 -18
  145. package/templates/root-consumer/guides/dndev/COMPONENTS_UI.md.example +1 -1
  146. package/templates/root-consumer/guides/dndev/ENV_SETUP.md.example +101 -32
  147. package/templates/root-consumer/guides/dndev/INDEX.md.example +4 -2
  148. package/templates/root-consumer/guides/dndev/SETUP_APP_CONFIG.md.example +3 -3
  149. package/templates/root-consumer/guides/dndev/SETUP_CRUD.md.example +241 -12
  150. package/templates/root-consumer/guides/dndev/SETUP_FIREBASE.md.example +13 -7
  151. package/templates/root-consumer/guides/dndev/SETUP_OAUTH_PROVIDERS.md.example +60 -0
  152. package/templates/root-consumer/guides/dndev/SETUP_SOC2.md.example +234 -0
  153. package/templates/root-consumer/guides/dndev/SETUP_STRIPE.md.example +62 -0
  154. package/templates/root-consumer/guides/dndev/SETUP_SUPABASE.md.example +124 -0
  155. package/templates/root-consumer/guides/dndev/SETUP_THEMES.md.example +6 -2
  156. package/templates/root-consumer/guides/dndev/SETUP_VERCEL.md.example +176 -0
  157. package/templates/root-consumer/guides/dndev/USE_ROUTING.md.example +5 -9
  158. package/templates/root-consumer/guides/dndev/essences_reference.css.example +174 -0
  159. package/templates/root-consumer/guides/wai-way/WAI_WAY_CLI.md.example +7 -8
  160. package/templates/root-consumer/guides/wai-way/agents/builder.md.example +10 -0
  161. package/templates/root-consumer/guides/wai-way/agents/extractor.md.example +25 -5
  162. package/templates/root-consumer/guides/wai-way/agents/polisher.md.example +13 -2
  163. package/templates/root-consumer/guides/wai-way/blueprints/0_brainstorm.md.example +2 -2
  164. package/templates/root-consumer/guides/wai-way/blueprints/1_scaffold.md.example +55 -15
  165. package/templates/root-consumer/guides/wai-way/blueprints/3_compose.md.example +15 -4
  166. package/templates/root-consumer/guides/wai-way/spec_template.md.example +7 -6
  167. package/dist/bin/commands/lint.d.ts +0 -11
  168. package/dist/bin/commands/lint.d.ts.map +0 -1
  169. package/dist/bin/commands/lint.js.map +0 -1
  170. package/dist/bin/commands/staging.d.ts +0 -11
  171. package/dist/bin/commands/staging.d.ts.map +0 -1
  172. package/dist/bin/commands/staging.js +0 -12
  173. package/dist/bin/commands/staging.js.map +0 -1
  174. package/templates/app-payload/.env.example +0 -28
  175. package/templates/app-payload/README.md.example +0 -233
  176. package/templates/app-payload/collections/Company.ts.example +0 -125
  177. package/templates/app-payload/collections/Hero.ts.example +0 -62
  178. package/templates/app-payload/collections/Media.ts.example +0 -41
  179. package/templates/app-payload/collections/Products.ts.example +0 -115
  180. package/templates/app-payload/collections/Services.ts.example +0 -104
  181. package/templates/app-payload/collections/Testimonials.ts.example +0 -92
  182. package/templates/app-payload/collections/Users.ts.example +0 -35
  183. package/templates/app-payload/src/server.ts.example +0 -79
  184. package/templates/app-payload/tsconfig.json.example +0 -24
@@ -4,11 +4,11 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
4
  var __getOwnPropNames = Object.getOwnPropertyNames;
5
5
  var __getProtoOf = Object.getPrototypeOf;
6
6
  var __hasOwnProp = Object.prototype.hasOwnProperty;
7
- var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
8
- get: (a, b2) => (typeof require !== "undefined" ? require : a)[b2]
9
- }) : x)(function(x) {
7
+ var __require = /* @__PURE__ */ ((x2) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x2, {
8
+ get: (a, b3) => (typeof require !== "undefined" ? require : a)[b3]
9
+ }) : x2)(function(x2) {
10
10
  if (typeof require !== "undefined") return require.apply(this, arguments);
11
- throw Error('Dynamic require of "' + x + '" is not supported');
11
+ throw Error('Dynamic require of "' + x2 + '" is not supported');
12
12
  });
13
13
  var __esm = (fn, res) => function __init() {
14
14
  return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
@@ -16,6 +16,10 @@ var __esm = (fn, res) => function __init() {
16
16
  var __commonJS = (cb, mod) => function __require2() {
17
17
  return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
18
18
  };
19
+ var __export = (target, all) => {
20
+ for (var name in all)
21
+ __defProp(target, name, { get: all[name], enumerable: true });
22
+ };
19
23
  var __copyProps = (to, from, except, desc) => {
20
24
  if (from && typeof from === "object" || typeof from === "function") {
21
25
  for (let key of __getOwnPropNames(from))
@@ -42,16 +46,16 @@ var require_src = __commonJS({
42
46
  var CSI = `${ESC}[`;
43
47
  var beep = "\x07";
44
48
  var cursor = {
45
- to(x, y2) {
46
- if (!y2) return `${CSI}${x + 1}G`;
47
- return `${CSI}${y2 + 1};${x + 1}H`;
49
+ to(x2, y3) {
50
+ if (!y3) return `${CSI}${x2 + 1}G`;
51
+ return `${CSI}${y3 + 1};${x2 + 1}H`;
48
52
  },
49
- move(x, y2) {
53
+ move(x2, y3) {
50
54
  let ret = "";
51
- if (x < 0) ret += `${CSI}${-x}D`;
52
- else if (x > 0) ret += `${CSI}${x}C`;
53
- if (y2 < 0) ret += `${CSI}${-y2}A`;
54
- else if (y2 > 0) ret += `${CSI}${y2}B`;
55
+ if (x2 < 0) ret += `${CSI}${-x2}D`;
56
+ else if (x2 > 0) ret += `${CSI}${x2}C`;
57
+ if (y3 < 0) ret += `${CSI}${-y3}A`;
58
+ else if (y3 > 0) ret += `${CSI}${y3}B`;
55
59
  return ret;
56
60
  },
57
61
  up: (count = 1) => `${CSI}${count}A`,
@@ -94,10 +98,10 @@ var require_src = __commonJS({
94
98
  var require_picocolors = __commonJS({
95
99
  "node_modules/.bun/picocolors@1.1.1/node_modules/picocolors/picocolors.js"(exports, module) {
96
100
  init_utils();
97
- var p = process || {};
98
- var argv = p.argv || [];
99
- var env = p.env || {};
100
- var isColorSupported = !(!!env.NO_COLOR || argv.includes("--no-color")) && (!!env.FORCE_COLOR || argv.includes("--color") || p.platform === "win32" || (p.stdout || {}).isTTY && env.TERM !== "dumb" || !!env.CI);
101
+ var p2 = process || {};
102
+ var argv = p2.argv || [];
103
+ var env = p2.env || {};
104
+ var isColorSupported = !(!!env.NO_COLOR || argv.includes("--no-color")) && (!!env.FORCE_COLOR || argv.includes("--color") || p2.platform === "win32" || (p2.stdout || {}).isTTY && env.TERM !== "dumb" || !!env.CI);
101
105
  var formatter = (open, close, replace = open) => (input) => {
102
106
  let string = "" + input, index = string.indexOf(close, open.length);
103
107
  return ~index ? open + replaceClose(string, close, replace, index) + close : open + string + close;
@@ -165,14 +169,41 @@ var require_picocolors = __commonJS({
165
169
 
166
170
  // node_modules/.bun/@clack+prompts@0.11.0/node_modules/@clack/prompts/node_modules/@clack/core/dist/index.mjs
167
171
  import { stdin as j, stdout as M } from "node:process";
172
+ import O from "node:readline";
168
173
  import { Writable as X } from "node:stream";
169
174
  function DD({ onlyFirst: e2 = false } = {}) {
170
175
  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("|");
171
176
  return new RegExp(t, e2 ? void 0 : "g");
172
177
  }
178
+ function P(e2) {
179
+ if (typeof e2 != "string") throw new TypeError(`Expected a \`string\`, got \`${typeof e2}\``);
180
+ return e2.replace(uD, "");
181
+ }
173
182
  function L(e2) {
174
183
  return e2 && e2.__esModule && Object.prototype.hasOwnProperty.call(e2, "default") ? e2.default : e2;
175
184
  }
185
+ function p(e2, u2 = {}) {
186
+ if (typeof e2 != "string" || e2.length === 0 || (u2 = { ambiguousIsNarrow: true, ...u2 }, e2 = P(e2), e2.length === 0)) return 0;
187
+ e2 = e2.replace(sD(), " ");
188
+ const t = u2.ambiguousIsNarrow ? 1 : 2;
189
+ let F2 = 0;
190
+ for (const s of e2) {
191
+ const i = s.codePointAt(0);
192
+ if (i <= 31 || i >= 127 && i <= 159 || i >= 768 && i <= 879) continue;
193
+ switch (eD.eastAsianWidth(s)) {
194
+ case "F":
195
+ case "W":
196
+ F2 += 2;
197
+ break;
198
+ case "A":
199
+ F2 += t;
200
+ break;
201
+ default:
202
+ F2 += 1;
203
+ }
204
+ }
205
+ return F2;
206
+ }
176
207
  function rD() {
177
208
  const e2 = /* @__PURE__ */ new Map();
178
209
  for (const [u2, t] of Object.entries(r)) {
@@ -202,7 +233,30 @@ function rD() {
202
233
  return i === 2 && (D2 += 60), D2;
203
234
  }, enumerable: false }, rgbToAnsi: { value: (u2, t, F2) => r.ansi256ToAnsi(r.rgbToAnsi256(u2, t, F2)), enumerable: false }, hexToAnsi: { value: (u2) => r.ansi256ToAnsi(r.hexToAnsi256(u2)), enumerable: false } }), r;
204
235
  }
205
- var import_sisteransi, uD, W, tD, eD, FD, sD, w, N, I, R, r, iD, CD, ED, nD, _, xD, B, AD, A;
236
+ function Y(e2, u2, t) {
237
+ return String(e2).normalize().replace(/\r\n/g, `
238
+ `).split(`
239
+ `).map((F2) => lD(F2, u2, t)).join(`
240
+ `);
241
+ }
242
+ function $(e2, u2) {
243
+ if (typeof e2 == "string") return B.aliases.get(e2) === u2;
244
+ for (const t of e2) if (t !== void 0 && $(t, u2)) return true;
245
+ return false;
246
+ }
247
+ function BD(e2, u2) {
248
+ if (e2 === u2) return;
249
+ const t = e2.split(`
250
+ `), F2 = u2.split(`
251
+ `), s = [];
252
+ for (let i = 0; i < Math.max(t.length, F2.length); i++) t[i] !== F2[i] && s.push(i);
253
+ return s;
254
+ }
255
+ function m(e2, u2) {
256
+ const t = e2;
257
+ t.isTTY && t.setRawMode(u2);
258
+ }
259
+ 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;
206
260
  var init_dist = __esm({
207
261
  "node_modules/.bun/@clack+prompts@0.11.0/node_modules/@clack/prompts/node_modules/@clack/core/dist/index.mjs"() {
208
262
  init_utils();
@@ -251,22 +305,213 @@ var init_dist = __esm({
251
305
  CD = Object.keys(r.bgColor);
252
306
  [...iD, ...CD];
253
307
  ED = rD();
308
+ d = /* @__PURE__ */ new Set(["\x1B", "\x9B"]);
309
+ oD = 39;
310
+ y = "\x07";
311
+ V = "[";
254
312
  nD = "]";
313
+ G = "m";
255
314
  _ = `${nD}8;;`;
315
+ z = (e2) => `${d.values().next().value}${V}${e2}${G}`;
316
+ K = (e2) => `${d.values().next().value}${_}${e2}${y}`;
317
+ aD = (e2) => e2.split(" ").map((u2) => p(u2));
318
+ k = (e2, u2, t) => {
319
+ const F2 = [...u2];
320
+ let s = false, i = false, D2 = p(P(e2[e2.length - 1]));
321
+ for (const [C2, n] of F2.entries()) {
322
+ const E = p(n);
323
+ if (D2 + E <= t ? e2[e2.length - 1] += n : (e2.push(n), D2 = 0), d.has(n) && (s = true, i = F2.slice(C2 + 1).join("").startsWith(_)), s) {
324
+ i ? n === y && (s = false, i = false) : n === G && (s = false);
325
+ continue;
326
+ }
327
+ D2 += E, D2 === t && C2 < F2.length - 1 && (e2.push(""), D2 = 0);
328
+ }
329
+ !D2 && e2[e2.length - 1].length > 0 && e2.length > 1 && (e2[e2.length - 2] += e2.pop());
330
+ };
331
+ hD = (e2) => {
332
+ const u2 = e2.split(" ");
333
+ let t = u2.length;
334
+ for (; t > 0 && !(p(u2[t - 1]) > 0); ) t--;
335
+ return t === u2.length ? e2 : u2.slice(0, t).join(" ") + u2.slice(t).join("");
336
+ };
337
+ lD = (e2, u2, t = {}) => {
338
+ if (t.trim !== false && e2.trim() === "") return "";
339
+ let F2 = "", s, i;
340
+ const D2 = aD(e2);
341
+ let C2 = [""];
342
+ for (const [E, a] of e2.split(" ").entries()) {
343
+ t.trim !== false && (C2[C2.length - 1] = C2[C2.length - 1].trimStart());
344
+ let o2 = p(C2[C2.length - 1]);
345
+ if (E !== 0 && (o2 >= u2 && (t.wordWrap === false || t.trim === false) && (C2.push(""), o2 = 0), (o2 > 0 || t.trim === false) && (C2[C2.length - 1] += " ", o2++)), t.hard && D2[E] > u2) {
346
+ const c = u2 - o2, f = 1 + Math.floor((D2[E] - c - 1) / u2);
347
+ Math.floor((D2[E] - 1) / u2) < f && C2.push(""), k(C2, a, u2);
348
+ continue;
349
+ }
350
+ if (o2 + D2[E] > u2 && o2 > 0 && D2[E] > 0) {
351
+ if (t.wordWrap === false && o2 < u2) {
352
+ k(C2, a, u2);
353
+ continue;
354
+ }
355
+ C2.push("");
356
+ }
357
+ if (o2 + D2[E] > u2 && t.wordWrap === false) {
358
+ k(C2, a, u2);
359
+ continue;
360
+ }
361
+ C2[C2.length - 1] += a;
362
+ }
363
+ t.trim !== false && (C2 = C2.map((E) => hD(E)));
364
+ const n = [...C2.join(`
365
+ `)];
366
+ for (const [E, a] of n.entries()) {
367
+ if (F2 += a, d.has(a)) {
368
+ const { groups: c } = new RegExp(`(?:\\${V}(?<code>\\d+)m|\\${_}(?<uri>.*)${y})`).exec(n.slice(E).join("")) || { groups: {} };
369
+ if (c.code !== void 0) {
370
+ const f = Number.parseFloat(c.code);
371
+ s = f === oD ? void 0 : f;
372
+ } else c.uri !== void 0 && (i = c.uri.length === 0 ? void 0 : c.uri);
373
+ }
374
+ const o2 = ED.codes.get(Number(s));
375
+ n[E + 1] === `
376
+ ` ? (i && (F2 += K("")), s && o2 && (F2 += z(o2))) : a === `
377
+ ` && (s && o2 && (F2 += z(s)), i && (F2 += K(i)));
378
+ }
379
+ return F2;
380
+ };
256
381
  xD = ["up", "down", "left", "right", "space", "enter", "cancel"];
257
382
  B = { actions: new Set(xD), aliases: /* @__PURE__ */ new Map([["k", "up"], ["j", "down"], ["h", "left"], ["l", "right"], ["", "cancel"], ["escape", "cancel"]]) };
258
383
  AD = globalThis.process.platform.startsWith("win");
384
+ S = /* @__PURE__ */ Symbol("clack:cancel");
385
+ gD = Object.defineProperty;
386
+ vD = (e2, u2, t) => u2 in e2 ? gD(e2, u2, { enumerable: true, configurable: true, writable: true, value: t }) : e2[u2] = t;
387
+ h = (e2, u2, t) => (vD(e2, typeof u2 != "symbol" ? u2 + "" : u2, t), t);
388
+ x = class {
389
+ constructor(u2, t = true) {
390
+ h(this, "input"), h(this, "output"), h(this, "_abortSignal"), h(this, "rl"), h(this, "opts"), h(this, "_render"), h(this, "_track", false), h(this, "_prevFrame", ""), h(this, "_subscribers", /* @__PURE__ */ new Map()), h(this, "_cursor", 0), h(this, "state", "initial"), h(this, "error", ""), h(this, "value");
391
+ const { input: F2 = j, output: s = M, render: i, signal: D2, ...C2 } = u2;
392
+ this.opts = C2, this.onKeypress = this.onKeypress.bind(this), this.close = this.close.bind(this), this.render = this.render.bind(this), this._render = i.bind(this), this._track = t, this._abortSignal = D2, this.input = F2, this.output = s;
393
+ }
394
+ unsubscribe() {
395
+ this._subscribers.clear();
396
+ }
397
+ setSubscriber(u2, t) {
398
+ const F2 = this._subscribers.get(u2) ?? [];
399
+ F2.push(t), this._subscribers.set(u2, F2);
400
+ }
401
+ on(u2, t) {
402
+ this.setSubscriber(u2, { cb: t });
403
+ }
404
+ once(u2, t) {
405
+ this.setSubscriber(u2, { cb: t, once: true });
406
+ }
407
+ emit(u2, ...t) {
408
+ const F2 = this._subscribers.get(u2) ?? [], s = [];
409
+ for (const i of F2) i.cb(...t), i.once && s.push(() => F2.splice(F2.indexOf(i), 1));
410
+ for (const i of s) i();
411
+ }
412
+ prompt() {
413
+ return new Promise((u2, t) => {
414
+ if (this._abortSignal) {
415
+ if (this._abortSignal.aborted) return this.state = "cancel", this.close(), u2(S);
416
+ this._abortSignal.addEventListener("abort", () => {
417
+ this.state = "cancel", this.close();
418
+ }, { once: true });
419
+ }
420
+ const F2 = new X();
421
+ F2._write = (s, i, D2) => {
422
+ this._track && (this.value = this.rl?.line.replace(/\t/g, ""), this._cursor = this.rl?.cursor ?? 0, this.emit("value", this.value)), D2();
423
+ }, this.input.pipe(F2), this.rl = O.createInterface({ input: this.input, output: F2, tabSize: 2, prompt: "", escapeCodeTimeout: 50, terminal: true }), O.emitKeypressEvents(this.input, this.rl), this.rl.prompt(), this.opts.initialValue !== void 0 && this._track && this.rl.write(this.opts.initialValue), this.input.on("keypress", this.onKeypress), m(this.input, true), this.output.on("resize", this.render), this.render(), this.once("submit", () => {
424
+ this.output.write(import_sisteransi.cursor.show), this.output.off("resize", this.render), m(this.input, false), u2(this.value);
425
+ }), this.once("cancel", () => {
426
+ this.output.write(import_sisteransi.cursor.show), this.output.off("resize", this.render), m(this.input, false), u2(S);
427
+ });
428
+ });
429
+ }
430
+ onKeypress(u2, t) {
431
+ if (this.state === "error" && (this.state = "active"), t?.name && (!this._track && B.aliases.has(t.name) && this.emit("cursor", B.aliases.get(t.name)), B.actions.has(t.name) && this.emit("cursor", t.name)), u2 && (u2.toLowerCase() === "y" || u2.toLowerCase() === "n") && this.emit("confirm", u2.toLowerCase() === "y"), u2 === " " && this.opts.placeholder && (this.value || (this.rl?.write(this.opts.placeholder), this.emit("value", this.opts.placeholder))), u2 && this.emit("key", u2.toLowerCase()), t?.name === "return") {
432
+ if (this.opts.validate) {
433
+ const F2 = this.opts.validate(this.value);
434
+ F2 && (this.error = F2 instanceof Error ? F2.message : F2, this.state = "error", this.rl?.write(this.value));
435
+ }
436
+ this.state !== "error" && (this.state = "submit");
437
+ }
438
+ $([u2, t?.name, t?.sequence], "cancel") && (this.state = "cancel"), (this.state === "submit" || this.state === "cancel") && this.emit("finalize"), this.render(), (this.state === "submit" || this.state === "cancel") && this.close();
439
+ }
440
+ close() {
441
+ this.input.unpipe(), this.input.removeListener("keypress", this.onKeypress), this.output.write(`
442
+ `), m(this.input, false), this.rl?.close(), this.rl = void 0, this.emit(`${this.state}`, this.value), this.unsubscribe();
443
+ }
444
+ restoreCursor() {
445
+ const u2 = Y(this._prevFrame, process.stdout.columns, { hard: true }).split(`
446
+ `).length - 1;
447
+ this.output.write(import_sisteransi.cursor.move(-999, u2 * -1));
448
+ }
449
+ render() {
450
+ const u2 = Y(this._render(this) ?? "", process.stdout.columns, { hard: true });
451
+ if (u2 !== this._prevFrame) {
452
+ if (this.state === "initial") this.output.write(import_sisteransi.cursor.hide);
453
+ else {
454
+ const t = BD(this._prevFrame, u2);
455
+ if (this.restoreCursor(), t && t?.length === 1) {
456
+ const F2 = t[0];
457
+ this.output.write(import_sisteransi.cursor.move(0, F2)), this.output.write(import_sisteransi.erase.lines(1));
458
+ const s = u2.split(`
459
+ `);
460
+ this.output.write(s[F2]), this._prevFrame = u2, this.output.write(import_sisteransi.cursor.move(0, s.length - F2 - 1));
461
+ return;
462
+ }
463
+ if (t && t?.length > 1) {
464
+ const F2 = t[0];
465
+ this.output.write(import_sisteransi.cursor.move(0, F2)), this.output.write(import_sisteransi.erase.down());
466
+ const s = u2.split(`
467
+ `).slice(F2);
468
+ this.output.write(s.join(`
469
+ `)), this._prevFrame = u2;
470
+ return;
471
+ }
472
+ this.output.write(import_sisteransi.erase.down());
473
+ }
474
+ this.output.write(u2), this.state === "initial" && (this.state = "active"), this._prevFrame = u2;
475
+ }
476
+ }
477
+ };
259
478
  A = /* @__PURE__ */ new WeakMap();
479
+ OD = Object.defineProperty;
480
+ PD = (e2, u2, t) => u2 in e2 ? OD(e2, u2, { enumerable: true, configurable: true, writable: true, value: t }) : e2[u2] = t;
481
+ J = (e2, u2, t) => (PD(e2, typeof u2 != "symbol" ? u2 + "" : u2, t), t);
482
+ LD = class extends x {
483
+ constructor(u2) {
484
+ super(u2, false), J(this, "options"), J(this, "cursor", 0), this.options = u2.options, this.cursor = this.options.findIndex(({ value: t }) => t === u2.initialValue), this.cursor === -1 && (this.cursor = 0), this.changeValue(), this.on("cursor", (t) => {
485
+ switch (t) {
486
+ case "left":
487
+ case "up":
488
+ this.cursor = this.cursor === 0 ? this.options.length - 1 : this.cursor - 1;
489
+ break;
490
+ case "down":
491
+ case "right":
492
+ this.cursor = this.cursor === this.options.length - 1 ? 0 : this.cursor + 1;
493
+ break;
494
+ }
495
+ this.changeValue();
496
+ });
497
+ }
498
+ get _value() {
499
+ return this.options[this.cursor];
500
+ }
501
+ changeValue() {
502
+ this.value = this._value.value;
503
+ }
504
+ };
260
505
  }
261
506
  });
262
507
 
263
508
  // node_modules/.bun/@clack+prompts@0.11.0/node_modules/@clack/prompts/dist/index.mjs
264
- import { stripVTControlCharacters as S } from "node:util";
265
- import y from "node:process";
509
+ import { stripVTControlCharacters as S2 } from "node:util";
510
+ import y2 from "node:process";
266
511
  function ce() {
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";
512
+ return y2.platform !== "win32" ? y2.env.TERM !== "linux" : !!y2.env.CI || !!y2.env.WT_SESSION || !!y2.env.TERMINUS_SUBLIME || y2.env.ConEmuTask === "{cmd::Cmder}" || y2.env.TERM_PROGRAM === "Terminus-Sublime" || y2.env.TERM_PROGRAM === "vscode" || y2.env.TERM === "xterm-256color" || y2.env.TERM === "alacritty" || y2.env.TERMINAL_EMULATOR === "JetBrains-JediTerm";
268
513
  }
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;
514
+ var import_picocolors, import_sisteransi2, V2, u, le, L2, W2, C, ue, o, d2, k2, P2, A2, T, F, $e, _2, me, de, pe, q, D, U, K2, b2, G2, ve, Me, Ie, Se, M2, J2;
270
515
  var init_dist2 = __esm({
271
516
  "node_modules/.bun/@clack+prompts@0.11.0/node_modules/@clack/prompts/dist/index.mjs"() {
272
517
  init_utils();
@@ -274,17 +519,17 @@ var init_dist2 = __esm({
274
519
  init_dist();
275
520
  import_picocolors = __toESM(require_picocolors(), 1);
276
521
  import_sisteransi2 = __toESM(require_src(), 1);
277
- V = ce();
278
- u = (t, n) => V ? t : n;
522
+ V2 = ce();
523
+ u = (t, n) => V2 ? t : n;
279
524
  le = u("\u25C6", "*");
280
525
  L2 = u("\u25A0", "x");
281
526
  W2 = u("\u25B2", "x");
282
527
  C = u("\u25C7", "o");
283
528
  ue = u("\u250C", "T");
284
529
  o = u("\u2502", "|");
285
- d = u("\u2514", "\u2014");
286
- k = u("\u25CF", ">");
287
- P = u("\u25CB", " ");
530
+ d2 = u("\u2514", "\u2014");
531
+ k2 = u("\u25CF", ">");
532
+ P2 = u("\u25CB", " ");
288
533
  A2 = u("\u25FB", "[\u2022]");
289
534
  T = u("\u25FC", "[+]");
290
535
  F = u("\u25FB", "[ ]");
@@ -296,7 +541,87 @@ var init_dist2 = __esm({
296
541
  q = u("\u25CF", "\u2022");
297
542
  D = u("\u25C6", "*");
298
543
  U = u("\u25B2", "!");
299
- K = u("\u25A0", "x");
544
+ K2 = u("\u25A0", "x");
545
+ b2 = (t) => {
546
+ switch (t) {
547
+ case "initial":
548
+ case "active":
549
+ return import_picocolors.default.cyan(le);
550
+ case "cancel":
551
+ return import_picocolors.default.red(L2);
552
+ case "error":
553
+ return import_picocolors.default.yellow(W2);
554
+ case "submit":
555
+ return import_picocolors.default.green(C);
556
+ }
557
+ };
558
+ G2 = (t) => {
559
+ const { cursor: n, options: r2, style: i } = t, s = t.maxItems ?? Number.POSITIVE_INFINITY, c = Math.max(process.stdout.rows - 4, 0), a = Math.min(c, Math.max(s, 5));
560
+ let l2 = 0;
561
+ n >= l2 + a - 3 ? l2 = Math.max(Math.min(n - a + 3, r2.length - a), 0) : n < l2 + 2 && (l2 = Math.max(n - 2, 0));
562
+ const $2 = a < r2.length && l2 > 0, g = a < r2.length && l2 + a < r2.length;
563
+ return r2.slice(l2, l2 + a).map((p2, v, f) => {
564
+ const j2 = v === 0 && $2, E = v === f.length - 1 && g;
565
+ return j2 || E ? import_picocolors.default.dim("...") : i(p2, v + l2 === n);
566
+ });
567
+ };
568
+ ve = (t) => {
569
+ const n = (r2, i) => {
570
+ const s = r2.label ?? String(r2.value);
571
+ switch (i) {
572
+ case "selected":
573
+ return `${import_picocolors.default.dim(s)}`;
574
+ case "active":
575
+ return `${import_picocolors.default.green(k2)} ${s} ${r2.hint ? import_picocolors.default.dim(`(${r2.hint})`) : ""}`;
576
+ case "cancelled":
577
+ return `${import_picocolors.default.strikethrough(import_picocolors.default.dim(s))}`;
578
+ default:
579
+ return `${import_picocolors.default.dim(P2)} ${import_picocolors.default.dim(s)}`;
580
+ }
581
+ };
582
+ return new LD({ options: t.options, initialValue: t.initialValue, render() {
583
+ const r2 = `${import_picocolors.default.gray(o)}
584
+ ${b2(this.state)} ${t.message}
585
+ `;
586
+ switch (this.state) {
587
+ case "submit":
588
+ return `${r2}${import_picocolors.default.gray(o)} ${n(this.options[this.cursor], "selected")}`;
589
+ case "cancel":
590
+ return `${r2}${import_picocolors.default.gray(o)} ${n(this.options[this.cursor], "cancelled")}
591
+ ${import_picocolors.default.gray(o)}`;
592
+ default:
593
+ return `${r2}${import_picocolors.default.cyan(o)} ${G2({ cursor: this.cursor, options: this.options, maxItems: t.maxItems, style: (i, s) => n(i, s ? "active" : "inactive") }).join(`
594
+ ${import_picocolors.default.cyan(o)} `)}
595
+ ${import_picocolors.default.cyan(d2)}
596
+ `;
597
+ }
598
+ } }).prompt();
599
+ };
600
+ Me = (t = "", n = "") => {
601
+ const r2 = `
602
+ ${t}
603
+ `.split(`
604
+ `), i = S2(n).length, s = Math.max(r2.reduce((a, l2) => {
605
+ const $2 = S2(l2);
606
+ return $2.length > a ? $2.length : a;
607
+ }, 0), i) + 2, c = r2.map((a) => `${import_picocolors.default.gray(o)} ${import_picocolors.default.dim(a)}${" ".repeat(s - S2(a).length)}${import_picocolors.default.gray(o)}`).join(`
608
+ `);
609
+ process.stdout.write(`${import_picocolors.default.gray(o)}
610
+ ${import_picocolors.default.green(C)} ${import_picocolors.default.reset(n)} ${import_picocolors.default.gray(_2.repeat(Math.max(s - i - 1, 1)) + me)}
611
+ ${c}
612
+ ${import_picocolors.default.gray(de + _2.repeat(s + 2) + pe)}
613
+ `);
614
+ };
615
+ Ie = (t = "") => {
616
+ process.stdout.write(`${import_picocolors.default.gray(ue)} ${t}
617
+ `);
618
+ };
619
+ Se = (t = "") => {
620
+ process.stdout.write(`${import_picocolors.default.gray(o)}
621
+ ${import_picocolors.default.gray(d2)} ${t}
622
+
623
+ `);
624
+ };
300
625
  M2 = { message: (t = "", { symbol: n = import_picocolors.default.gray(o) } = {}) => {
301
626
  const r2 = [`${import_picocolors.default.gray(o)}`];
302
627
  if (t) {
@@ -318,9 +643,9 @@ var init_dist2 = __esm({
318
643
  }, warning: (t) => {
319
644
  M2.warn(t);
320
645
  }, error: (t) => {
321
- M2.message(t, { symbol: import_picocolors.default.red(K) });
646
+ M2.message(t, { symbol: import_picocolors.default.red(K2) });
322
647
  } };
323
- J = `${import_picocolors.default.gray(o)} `;
648
+ J2 = `${import_picocolors.default.gray(o)} `;
324
649
  }
325
650
  });
326
651
 
@@ -934,8 +1259,8 @@ var require_to_regex_range = __commonJS({
934
1259
  return toRegexRange.cache[cacheKey].result;
935
1260
  }
936
1261
  let a = Math.min(min, max);
937
- let b2 = Math.max(min, max);
938
- if (Math.abs(a - b2) === 1) {
1262
+ let b3 = Math.max(min, max);
1263
+ if (Math.abs(a - b3) === 1) {
939
1264
  let result = min + "|" + max;
940
1265
  if (opts.capture) {
941
1266
  return `(${result})`;
@@ -946,7 +1271,7 @@ var require_to_regex_range = __commonJS({
946
1271
  return `(?:${result})`;
947
1272
  }
948
1273
  let isPadded = hasPadding(min) || hasPadding(max);
949
- let state = { min, max, a, b: b2 };
1274
+ let state = { min, max, a, b: b3 };
950
1275
  let positives = [];
951
1276
  let negatives = [];
952
1277
  if (isPadded) {
@@ -954,12 +1279,12 @@ var require_to_regex_range = __commonJS({
954
1279
  state.maxLen = String(state.max).length;
955
1280
  }
956
1281
  if (a < 0) {
957
- let newMin = b2 < 0 ? Math.abs(b2) : 1;
1282
+ let newMin = b3 < 0 ? Math.abs(b3) : 1;
958
1283
  negatives = splitToPatterns(newMin, Math.abs(a), state, opts);
959
1284
  a = state.a = 0;
960
1285
  }
961
- if (b2 >= 0) {
962
- positives = splitToPatterns(a, b2, state, opts);
1286
+ if (b3 >= 0) {
1287
+ positives = splitToPatterns(a, b3, state, opts);
963
1288
  }
964
1289
  state.negatives = negatives;
965
1290
  state.positives = positives;
@@ -1063,13 +1388,13 @@ var require_to_regex_range = __commonJS({
1063
1388
  }
1064
1389
  return result;
1065
1390
  }
1066
- function zip(a, b2) {
1391
+ function zip(a, b3) {
1067
1392
  let arr = [];
1068
- for (let i = 0; i < a.length; i++) arr.push([a[i], b2[i]]);
1393
+ for (let i = 0; i < a.length; i++) arr.push([a[i], b3[i]]);
1069
1394
  return arr;
1070
1395
  }
1071
- function compare(a, b2) {
1072
- return a > b2 ? 1 : b2 > a ? -1 : 0;
1396
+ function compare(a, b3) {
1397
+ return a > b3 ? 1 : b3 > a ? -1 : 0;
1073
1398
  }
1074
1399
  function contains(arr, key, val) {
1075
1400
  return arr.some((ele) => ele[key] === val);
@@ -1087,8 +1412,8 @@ var require_to_regex_range = __commonJS({
1087
1412
  }
1088
1413
  return "";
1089
1414
  }
1090
- function toCharacterClass(a, b2, options) {
1091
- return `[${a}${b2 - a === 1 ? "" : "-"}${b2}]`;
1415
+ function toCharacterClass(a, b3, options) {
1416
+ return `[${a}${b3 - a === 1 ? "" : "-"}${b3}]`;
1092
1417
  }
1093
1418
  function hasPadding(str) {
1094
1419
  return /^-?(0+)\d/.test(str);
@@ -1167,8 +1492,8 @@ var require_fill_range = __commonJS({
1167
1492
  return negative ? "-" + input : input;
1168
1493
  };
1169
1494
  var toSequence = (parts, options, maxLen) => {
1170
- parts.negatives.sort((a, b2) => a < b2 ? -1 : a > b2 ? 1 : 0);
1171
- parts.positives.sort((a, b2) => a < b2 ? -1 : a > b2 ? 1 : 0);
1495
+ parts.negatives.sort((a, b3) => a < b3 ? -1 : a > b3 ? 1 : 0);
1496
+ parts.positives.sort((a, b3) => a < b3 ? -1 : a > b3 ? 1 : 0);
1172
1497
  let prefix = options.capture ? "" : "?:";
1173
1498
  let positives = "";
1174
1499
  let negatives = "";
@@ -1189,13 +1514,13 @@ var require_fill_range = __commonJS({
1189
1514
  }
1190
1515
  return result;
1191
1516
  };
1192
- var toRange = (a, b2, isNumbers, options) => {
1517
+ var toRange = (a, b3, isNumbers, options) => {
1193
1518
  if (isNumbers) {
1194
- return toRegexRange(a, b2, { wrap: false, ...options });
1519
+ return toRegexRange(a, b3, { wrap: false, ...options });
1195
1520
  }
1196
1521
  let start = String.fromCharCode(a);
1197
- if (a === b2) return start;
1198
- let stop = String.fromCharCode(b2);
1522
+ if (a === b3) return start;
1523
+ let stop = String.fromCharCode(b3);
1199
1524
  return `[${start}-${stop}]`;
1200
1525
  };
1201
1526
  var toRegex = (start, end, options) => {
@@ -1221,14 +1546,14 @@ var require_fill_range = __commonJS({
1221
1546
  };
1222
1547
  var fillNumbers = (start, end, step = 1, options = {}) => {
1223
1548
  let a = Number(start);
1224
- let b2 = Number(end);
1225
- if (!Number.isInteger(a) || !Number.isInteger(b2)) {
1549
+ let b3 = Number(end);
1550
+ if (!Number.isInteger(a) || !Number.isInteger(b3)) {
1226
1551
  if (options.strictRanges === true) throw rangeError([start, end]);
1227
1552
  return [];
1228
1553
  }
1229
1554
  if (a === 0) a = 0;
1230
- if (b2 === 0) b2 = 0;
1231
- let descending = a > b2;
1555
+ if (b3 === 0) b3 = 0;
1556
+ let descending = a > b3;
1232
1557
  let startString = String(start);
1233
1558
  let endString = String(end);
1234
1559
  let stepString = String(step);
@@ -1244,7 +1569,7 @@ var require_fill_range = __commonJS({
1244
1569
  let push = (num) => parts[num < 0 ? "negatives" : "positives"].push(Math.abs(num));
1245
1570
  let range = [];
1246
1571
  let index = 0;
1247
- while (descending ? a >= b2 : a <= b2) {
1572
+ while (descending ? a >= b3 : a <= b3) {
1248
1573
  if (options.toRegex === true && step > 1) {
1249
1574
  push(a);
1250
1575
  } else {
@@ -1264,16 +1589,16 @@ var require_fill_range = __commonJS({
1264
1589
  }
1265
1590
  let format = options.transform || ((val) => String.fromCharCode(val));
1266
1591
  let a = `${start}`.charCodeAt(0);
1267
- let b2 = `${end}`.charCodeAt(0);
1268
- let descending = a > b2;
1269
- let min = Math.min(a, b2);
1270
- let max = Math.max(a, b2);
1592
+ let b3 = `${end}`.charCodeAt(0);
1593
+ let descending = a > b3;
1594
+ let min = Math.min(a, b3);
1595
+ let max = Math.max(a, b3);
1271
1596
  if (options.toRegex && step === 1) {
1272
1597
  return toRange(min, max, false, options);
1273
1598
  }
1274
1599
  let range = [];
1275
1600
  let index = 0;
1276
- while (descending ? a >= b2 : a <= b2) {
1601
+ while (descending ? a >= b3 : a <= b3) {
1277
1602
  range.push(format(a, index));
1278
1603
  a = descending ? a - step : a + step;
1279
1604
  index++;
@@ -1398,11 +1723,11 @@ var require_expand = __commonJS({
1398
1723
  const rangeLimit = options.rangeLimit === void 0 ? 1e3 : options.rangeLimit;
1399
1724
  const walk = (node, parent = {}) => {
1400
1725
  node.queue = [];
1401
- let p = parent;
1726
+ let p2 = parent;
1402
1727
  let q2 = parent.queue;
1403
- while (p.type !== "brace" && p.type !== "root" && p.parent) {
1404
- p = p.parent;
1405
- q2 = p.queue;
1728
+ while (p2.type !== "brace" && p2.type !== "root" && p2.parent) {
1729
+ p2 = p2.parent;
1730
+ q2 = p2.queue;
1406
1731
  }
1407
1732
  if (node.invalid || node.dollar) {
1408
1733
  q2.push(append(q2.pop(), stringify2(node, options)));
@@ -2646,10 +2971,10 @@ var require_parse2 = __commonJS({
2646
2971
  };
2647
2972
  if (opts.fastpaths !== false && !/(^[*!]|[/()[\]{}"])/.test(input)) {
2648
2973
  let backslashes = false;
2649
- let output = input.replace(REGEX_SPECIAL_CHARS_BACKREF, (m, esc, chars, first, rest, index) => {
2974
+ let output = input.replace(REGEX_SPECIAL_CHARS_BACKREF, (m2, esc, chars, first, rest, index) => {
2650
2975
  if (first === "\\") {
2651
2976
  backslashes = true;
2652
- return m;
2977
+ return m2;
2653
2978
  }
2654
2979
  if (first === "?") {
2655
2980
  if (esc) {
@@ -2669,14 +2994,14 @@ var require_parse2 = __commonJS({
2669
2994
  }
2670
2995
  return star;
2671
2996
  }
2672
- return esc ? m : `\\${m}`;
2997
+ return esc ? m2 : `\\${m2}`;
2673
2998
  });
2674
2999
  if (backslashes === true) {
2675
3000
  if (opts.unescape === true) {
2676
3001
  output = output.replace(/\\/g, "");
2677
3002
  } else {
2678
- output = output.replace(/\\+/g, (m) => {
2679
- return m.length % 2 === 0 ? "\\\\" : m ? "\\" : "";
3003
+ output = output.replace(/\\+/g, (m2) => {
3004
+ return m2.length % 2 === 0 ? "\\\\" : m2 ? "\\" : "";
2680
3005
  });
2681
3006
  }
2682
3007
  }
@@ -3323,7 +3648,7 @@ var require_picomatch = __commonJS({
3323
3648
  };
3324
3649
  picomatch.isMatch = (str, patterns, options) => picomatch(patterns, options)(str);
3325
3650
  picomatch.parse = (pattern, options) => {
3326
- if (Array.isArray(pattern)) return pattern.map((p) => picomatch.parse(p, options));
3651
+ if (Array.isArray(pattern)) return pattern.map((p2) => picomatch.parse(p2, options));
3327
3652
  return parse2(pattern, { ...options, fastpaths: false });
3328
3653
  };
3329
3654
  picomatch.scan = (input, options) => scan(input, options);
@@ -3430,7 +3755,7 @@ var require_micromatch = __commonJS({
3430
3755
  throw new Error(`No matches found for "${patterns.join(", ")}"`);
3431
3756
  }
3432
3757
  if (options.nonull === true || options.nullglob === true) {
3433
- return options.unescape ? patterns.map((p) => p.replace(/\\/g, "")) : patterns;
3758
+ return options.unescape ? patterns.map((p2) => p2.replace(/\\/g, "")) : patterns;
3434
3759
  }
3435
3760
  }
3436
3761
  return matches;
@@ -3460,7 +3785,7 @@ var require_micromatch = __commonJS({
3460
3785
  throw new TypeError(`Expected a string: "${util.inspect(str)}"`);
3461
3786
  }
3462
3787
  if (Array.isArray(pattern)) {
3463
- return pattern.some((p) => micromatch.contains(str, p, options));
3788
+ return pattern.some((p2) => micromatch.contains(str, p2, options));
3464
3789
  }
3465
3790
  if (typeof pattern === "string") {
3466
3791
  if (isEmptyString(str) || isEmptyString(pattern)) {
@@ -3505,7 +3830,7 @@ var require_micromatch = __commonJS({
3505
3830
  if (typeof str !== "string") {
3506
3831
  throw new TypeError(`Expected a string: "${util.inspect(str)}"`);
3507
3832
  }
3508
- return [].concat(patterns).every((p) => picomatch(p, options)(str));
3833
+ return [].concat(patterns).every((p2) => picomatch(p2, options)(str));
3509
3834
  };
3510
3835
  micromatch.capture = (glob, input, options) => {
3511
3836
  let posix = utils.isWindows(options);
@@ -3656,7 +3981,7 @@ var require_pattern = __commonJS({
3656
3981
  exports.expandPatternsWithBraceExpansion = expandPatternsWithBraceExpansion;
3657
3982
  function expandBraceExpansion(pattern) {
3658
3983
  const patterns = micromatch.braces(pattern, { expand: true, nodupes: true, keepEscaping: true });
3659
- patterns.sort((a, b2) => a.length - b2.length);
3984
+ patterns.sort((a, b3) => a.length - b3.length);
3660
3985
  return patterns.filter((pattern2) => pattern2 !== "");
3661
3986
  }
3662
3987
  exports.expandBraceExpansion = expandBraceExpansion;
@@ -4129,11 +4454,11 @@ var require_out = __commonJS({
4129
4454
  async.read(path, getSettings(optionsOrSettingsOrCallback), callback);
4130
4455
  }
4131
4456
  exports.stat = stat;
4132
- function statSync2(path, optionsOrSettings) {
4457
+ function statSync3(path, optionsOrSettings) {
4133
4458
  const settings = getSettings(optionsOrSettings);
4134
4459
  return sync.read(path, settings);
4135
4460
  }
4136
- exports.statSync = statSync2;
4461
+ exports.statSync = statSync3;
4137
4462
  function getSettings(settingsOrOptions = {}) {
4138
4463
  if (settingsOrOptions instanceof settings_1.default) {
4139
4464
  return settingsOrOptions;
@@ -4271,11 +4596,11 @@ var require_common = __commonJS({
4271
4596
  init_utils();
4272
4597
  Object.defineProperty(exports, "__esModule", { value: true });
4273
4598
  exports.joinPathSegments = void 0;
4274
- function joinPathSegments(a, b2, separator) {
4599
+ function joinPathSegments(a, b3, separator) {
4275
4600
  if (a.endsWith(separator)) {
4276
- return a + b2;
4601
+ return a + b3;
4277
4602
  }
4278
- return a + separator + b2;
4603
+ return a + separator + b3;
4279
4604
  }
4280
4605
  exports.joinPathSegments = joinPathSegments;
4281
4606
  }
@@ -4811,7 +5136,7 @@ var require_queue = __commonJS({
4811
5136
  queue.drained = drained;
4812
5137
  return queue;
4813
5138
  function push(value) {
4814
- var p = new Promise(function(resolve4, reject) {
5139
+ var p2 = new Promise(function(resolve4, reject) {
4815
5140
  pushCb(value, function(err, result) {
4816
5141
  if (err) {
4817
5142
  reject(err);
@@ -4820,11 +5145,11 @@ var require_queue = __commonJS({
4820
5145
  resolve4(result);
4821
5146
  });
4822
5147
  });
4823
- p.catch(noop);
4824
- return p;
5148
+ p2.catch(noop);
5149
+ return p2;
4825
5150
  }
4826
5151
  function unshift(value) {
4827
- var p = new Promise(function(resolve4, reject) {
5152
+ var p2 = new Promise(function(resolve4, reject) {
4828
5153
  unshiftCb(value, function(err, result) {
4829
5154
  if (err) {
4830
5155
  reject(err);
@@ -4833,11 +5158,11 @@ var require_queue = __commonJS({
4833
5158
  resolve4(result);
4834
5159
  });
4835
5160
  });
4836
- p.catch(noop);
4837
- return p;
5161
+ p2.catch(noop);
5162
+ return p2;
4838
5163
  }
4839
5164
  function drained() {
4840
- var p = new Promise(function(resolve4) {
5165
+ var p2 = new Promise(function(resolve4) {
4841
5166
  process.nextTick(function() {
4842
5167
  if (queue.idle()) {
4843
5168
  resolve4();
@@ -4851,7 +5176,7 @@ var require_queue = __commonJS({
4851
5176
  }
4852
5177
  });
4853
5178
  });
4854
- return p;
5179
+ return p2;
4855
5180
  }
4856
5181
  }
4857
5182
  module.exports = fastqueue;
@@ -4881,14 +5206,14 @@ var require_common2 = __commonJS({
4881
5206
  return filepath.split(/[/\\]/).join(separator);
4882
5207
  }
4883
5208
  exports.replacePathSegmentSeparator = replacePathSegmentSeparator;
4884
- function joinPathSegments(a, b2, separator) {
5209
+ function joinPathSegments(a, b3, separator) {
4885
5210
  if (a === "") {
4886
- return b2;
5211
+ return b3;
4887
5212
  }
4888
5213
  if (a.endsWith(separator)) {
4889
- return a + b2;
5214
+ return a + b3;
4890
5215
  }
4891
- return a + separator + b2;
5216
+ return a + separator + b3;
4892
5217
  }
4893
5218
  exports.joinPathSegments = joinPathSegments;
4894
5219
  }
@@ -7215,11 +7540,39 @@ var init_PathResolver = __esm({
7215
7540
  });
7216
7541
 
7217
7542
  // packages/tooling/src/utils/errors.ts
7218
- var DoNotDevError;
7543
+ var DO_NOT_DEV_ERROR_CODES, DoNotDevError;
7219
7544
  var init_errors = __esm({
7220
7545
  "packages/tooling/src/utils/errors.ts"() {
7221
7546
  "use strict";
7222
7547
  init_utils();
7548
+ DO_NOT_DEV_ERROR_CODES = {
7549
+ CONFIGURATION_ERROR: "configuration-error",
7550
+ CONFIG_NOT_FOUND: "config-not-found",
7551
+ CONFIG_INVALID: "config-invalid",
7552
+ PATH_RESOLUTION_ERROR: "path-resolution-error",
7553
+ FILE_OPERATION_ERROR: "file-operation-error",
7554
+ FILE_NOT_FOUND: "file-not-found",
7555
+ PERMISSION_DENIED: "permission-denied",
7556
+ GENERATION_ERROR: "generation-error",
7557
+ TEMPLATE_ERROR: "template-error",
7558
+ TEMPLATE_NOT_FOUND: "template-not-found",
7559
+ CLI_EXECUTION_ERROR: "cli-execution-error",
7560
+ COMMAND_NOT_FOUND: "command-not-found",
7561
+ COMMAND_FAILED: "command-failed",
7562
+ VALIDATION_ERROR: "validation-error",
7563
+ SCHEMA_ERROR: "schema-error",
7564
+ DEPENDENCY_ERROR: "dependency-error",
7565
+ DEPENDENCY_NOT_FOUND: "dependency-not-found",
7566
+ DEPENDENCY_VERSION_ERROR: "dependency-version-error",
7567
+ INVALID_ARGUMENT: "invalid-argument",
7568
+ MISSING_ARGUMENT: "missing-argument",
7569
+ MISSING_PROJECT_ID: "missing-project-id",
7570
+ FIREBASE_CLI_ERROR: "firebase-cli-error",
7571
+ DEPLOYMENT_FAILED: "deployment-failed",
7572
+ OPERATION_CANCELLED: "operation-cancelled",
7573
+ TIMEOUT_ERROR: "timeout-error",
7574
+ UNKNOWN_ERROR: "unknown-error"
7575
+ };
7223
7576
  DoNotDevError = class _DoNotDevError extends Error {
7224
7577
  /** The error code categorizing this error */
7225
7578
  code;
@@ -7239,7 +7592,7 @@ var init_errors = __esm({
7239
7592
  * @param {Record<string, any>} [options.context] - Additional context data
7240
7593
  * @param {boolean} [options.displayable=true] - Whether this error should be displayed to the user
7241
7594
  */
7242
- constructor(message, code = "unknown-error", options) {
7595
+ constructor(message, code = DO_NOT_DEV_ERROR_CODES.UNKNOWN_ERROR, options) {
7243
7596
  super(message);
7244
7597
  this.name = "DoNotDevError";
7245
7598
  this.code = code;
@@ -7270,7 +7623,7 @@ var init_errors = __esm({
7270
7623
  * @param {boolean} [options.displayable=true] - Whether this error should be displayed to the user
7271
7624
  * @returns {DoNotDevError} New DoNotDev error wrapping the original
7272
7625
  */
7273
- static from(error2, context, code = "unknown-error", options) {
7626
+ static from(error2, context, code = DO_NOT_DEV_ERROR_CODES.UNKNOWN_ERROR, options) {
7274
7627
  if (!(error2 instanceof Error)) {
7275
7628
  return new _DoNotDevError(
7276
7629
  `Unknown error: ${String(error2)}`,
@@ -7307,21 +7660,21 @@ var init_errors = __esm({
7307
7660
  }
7308
7661
  const message = error2.message.toLowerCase();
7309
7662
  if (error2.name === "ValidationError" || message.includes("validation")) {
7310
- return "validation-error";
7663
+ return DO_NOT_DEV_ERROR_CODES.VALIDATION_ERROR;
7311
7664
  }
7312
7665
  if (message.includes("not found") || message.includes("no such file")) {
7313
- return "file-not-found";
7666
+ return DO_NOT_DEV_ERROR_CODES.FILE_NOT_FOUND;
7314
7667
  }
7315
7668
  if (message.includes("permission") || message.includes("access denied")) {
7316
- return "permission-denied";
7669
+ return DO_NOT_DEV_ERROR_CODES.PERMISSION_DENIED;
7317
7670
  }
7318
7671
  if (message.includes("timeout") || message.includes("timed out")) {
7319
- return "timeout-error";
7672
+ return DO_NOT_DEV_ERROR_CODES.TIMEOUT_ERROR;
7320
7673
  }
7321
7674
  if (message.includes("dependency") || message.includes("module not found")) {
7322
- return "dependency-error";
7675
+ return DO_NOT_DEV_ERROR_CODES.DEPENDENCY_ERROR;
7323
7676
  }
7324
- return "unknown-error";
7677
+ return DO_NOT_DEV_ERROR_CODES.UNKNOWN_ERROR;
7325
7678
  }
7326
7679
  };
7327
7680
  }
@@ -7340,7 +7693,10 @@ import {
7340
7693
  isAbsolute as pathIsAbsolute
7341
7694
  } from "node:path";
7342
7695
  import { fileURLToPath as fileURLToPath2 } from "node:url";
7343
- var pathResolverInstance, normalizePath, pathExists, joinPath;
7696
+ function readdirSync2(dirPath, options) {
7697
+ return pathResolverInstance.readdirSync(dirPath, options);
7698
+ }
7699
+ var pathResolverInstance, normalizePath, pathExists, readSync, statSync2, joinPath;
7344
7700
  var init_pathResolver = __esm({
7345
7701
  "packages/tooling/src/utils/pathResolver.ts"() {
7346
7702
  "use strict";
@@ -7351,12 +7707,42 @@ var init_pathResolver = __esm({
7351
7707
  return pathResolverInstance.normalizePath(join2(...pathSegments));
7352
7708
  };
7353
7709
  pathExists = (filePath, silent = false) => pathResolverInstance.pathExists(filePath, silent);
7710
+ readSync = (filePath, options) => pathResolverInstance.readSync(filePath, options);
7711
+ statSync2 = (filePath) => pathResolverInstance.statSync(filePath);
7354
7712
  joinPath = (...pathSegments) => {
7355
7713
  return normalizePath(...pathSegments);
7356
7714
  };
7357
7715
  }
7358
7716
  });
7359
7717
 
7718
+ // packages/tooling/src/utils/typed-file-operations.ts
7719
+ function readPackageJson(filePath) {
7720
+ if (!pathExists(filePath)) {
7721
+ throw new DoNotDevError(
7722
+ `package.json not found: ${filePath}`,
7723
+ DO_NOT_DEV_ERROR_CODES.FILE_NOT_FOUND,
7724
+ { context: { filePath } }
7725
+ );
7726
+ }
7727
+ const content = readSync(filePath, { format: "json" });
7728
+ if (!content || typeof content !== "object" || !("name" in content)) {
7729
+ throw new DoNotDevError(
7730
+ `Invalid package.json: ${filePath}`,
7731
+ DO_NOT_DEV_ERROR_CODES.CONFIG_INVALID,
7732
+ { context: { filePath } }
7733
+ );
7734
+ }
7735
+ return content;
7736
+ }
7737
+ var init_typed_file_operations = __esm({
7738
+ "packages/tooling/src/utils/typed-file-operations.ts"() {
7739
+ "use strict";
7740
+ init_utils();
7741
+ init_pathResolver();
7742
+ init_errors();
7743
+ }
7744
+ });
7745
+
7360
7746
  // packages/tooling/src/bundler/utils.ts
7361
7747
  import { Buffer as Buffer2 } from "node:buffer";
7362
7748
  import { readFileSync as readFileSync2, writeFileSync as writeFileSync2, mkdirSync as mkdirSync2 } from "node:fs";
@@ -7384,77 +7770,750 @@ var init_utils = __esm({
7384
7770
  }
7385
7771
  });
7386
7772
 
7387
- // packages/cli/src/bin/commands/lint.ts
7388
- init_utils();
7773
+ // packages/tooling/src/utils/app-detection.ts
7774
+ function detectApps(projectRoot) {
7775
+ const apps = [];
7776
+ const appsDir = joinPath(projectRoot, "apps");
7777
+ const appsDirStat = statSync2(appsDir);
7778
+ if (pathExists(appsDir) && appsDirStat?.isDirectory()) {
7779
+ const appDirs = readdirSync2(appsDir, { withFileTypes: true }).filter((dirent) => dirent.isDirectory()).map((dirent) => dirent.name).sort();
7780
+ for (const appDir of appDirs) {
7781
+ const appPath = joinPath(appsDir, appDir);
7782
+ const packageJsonPath = joinPath(appPath, "package.json");
7783
+ if (pathExists(packageJsonPath)) {
7784
+ const appInfo = analyzeApp(appPath, appDir);
7785
+ if (appInfo) {
7786
+ apps.push(appInfo);
7787
+ }
7788
+ }
7789
+ }
7790
+ } else {
7791
+ const packageJsonPath = joinPath(projectRoot, "package.json");
7792
+ if (pathExists(packageJsonPath)) {
7793
+ try {
7794
+ const packageJson = readPackageJson(packageJsonPath);
7795
+ if (packageJson && (packageJson.dependencies?.vite || packageJson.devDependencies?.vite || packageJson.dependencies?.next || packageJson.devDependencies?.next)) {
7796
+ const pathParts = projectRoot.split(/[/\\]/);
7797
+ const appName = pathParts[pathParts.length - 1] || "app";
7798
+ const appInfo = analyzeApp(projectRoot, appName);
7799
+ if (appInfo) {
7800
+ apps.push(appInfo);
7801
+ }
7802
+ }
7803
+ } catch {
7804
+ }
7805
+ }
7806
+ }
7807
+ return apps;
7808
+ }
7809
+ function analyzeApp(appPath, appName) {
7810
+ const packageJsonPath = joinPath(appPath, "package.json");
7811
+ if (!pathExists(packageJsonPath)) {
7812
+ return null;
7813
+ }
7814
+ let packageJson = null;
7815
+ try {
7816
+ packageJson = readPackageJson(packageJsonPath);
7817
+ if (!packageJson.name) {
7818
+ return null;
7819
+ }
7820
+ } catch {
7821
+ return null;
7822
+ }
7823
+ let framework = "unknown";
7824
+ if (pathExists(joinPath(appPath, "next.config.js")) || pathExists(joinPath(appPath, "next.config.ts")) || pathExists(joinPath(appPath, "next.config.mjs")) || packageJson.dependencies?.next || packageJson.devDependencies?.next) {
7825
+ framework = "nextjs";
7826
+ } else if (pathExists(joinPath(appPath, "vite.config.ts")) || pathExists(joinPath(appPath, "vite.config.js")) || pathExists(joinPath(appPath, "vite.config.mjs")) || packageJson.dependencies?.vite || packageJson.devDependencies?.vite) {
7827
+ framework = "vite";
7828
+ }
7829
+ const functionsPath = joinPath(appPath, "functions");
7830
+ const functionsStat = statSync2(functionsPath);
7831
+ const hasFunctions = pathExists(functionsPath) && (functionsStat?.isDirectory() ?? false);
7832
+ let platform;
7833
+ const firebaseJsonInFunctions = hasFunctions && pathExists(joinPath(functionsPath, "firebase.json"));
7834
+ const firebaseJsonInApp = pathExists(joinPath(appPath, "firebase.json"));
7835
+ if (firebaseJsonInFunctions || firebaseJsonInApp) {
7836
+ platform = "firebase";
7837
+ }
7838
+ if (!platform) {
7839
+ const supabaseConfigPath = joinPath(appPath, "supabase", "config.toml");
7840
+ const hasSupabaseDep = !!(packageJson.dependencies?.["@donotdev/supabase"] || packageJson.dependencies?.["@supabase/supabase-js"]);
7841
+ if (pathExists(supabaseConfigPath) || hasSupabaseDep) {
7842
+ platform = "supabase";
7843
+ }
7844
+ }
7845
+ if (!platform) {
7846
+ const vercelJsonPath = joinPath(appPath, "vercel.json");
7847
+ if (pathExists(vercelJsonPath)) {
7848
+ platform = "vercel";
7849
+ }
7850
+ }
7851
+ return {
7852
+ name: appName,
7853
+ packageName: packageJson.name || appName,
7854
+ path: appPath,
7855
+ packageJsonPath,
7856
+ framework,
7857
+ hasFunctions,
7858
+ functionsPath: hasFunctions ? functionsPath : void 0,
7859
+ platform
7860
+ };
7861
+ }
7862
+ var init_app_detection = __esm({
7863
+ "packages/tooling/src/utils/app-detection.ts"() {
7864
+ "use strict";
7865
+ init_utils();
7866
+ init_pathResolver();
7867
+ init_typed_file_operations();
7868
+ }
7869
+ });
7389
7870
 
7390
- // packages/tooling/src/index.ts
7391
- init_utils();
7871
+ // packages/tooling/src/utils/app-selector.ts
7872
+ async function selectApp(projectRoot, appName) {
7873
+ const apps = detectApps(projectRoot);
7874
+ if (apps.length === 0) {
7875
+ log.error("No apps found in this project.");
7876
+ log.info('Run "dndev init" to create a new project.');
7877
+ return null;
7878
+ }
7879
+ if (appName) {
7880
+ const app = apps.find((a) => a.name === appName);
7881
+ if (!app) {
7882
+ log.warn(`App "${appName}" not found.`);
7883
+ log.info("Available apps:");
7884
+ apps.forEach((a) => log.info(` - ${a.name}`));
7885
+ log.info("Please select from the list:");
7886
+ } else {
7887
+ return app;
7888
+ }
7889
+ }
7890
+ if (apps.length === 1) {
7891
+ return apps[0] || null;
7892
+ }
7893
+ const selected = await ve({
7894
+ message: "Select app:",
7895
+ options: apps.map((app) => ({
7896
+ value: app.name,
7897
+ label: `${app.name} (${app.framework === "nextjs" ? "Next.js" : "Vite"}${app.hasFunctions ? ` + ${app.platform || "functions"}` : ""})`
7898
+ }))
7899
+ });
7900
+ if (typeof selected !== "string") {
7901
+ return null;
7902
+ }
7903
+ return apps.find((a) => a.name === selected) || null;
7904
+ }
7905
+ var init_app_selector = __esm({
7906
+ "packages/tooling/src/utils/app-selector.ts"() {
7907
+ "use strict";
7908
+ init_utils();
7909
+ init_dist2();
7910
+ init_app_detection();
7911
+ init_cli_output();
7912
+ }
7913
+ });
7392
7914
 
7393
- // packages/tooling/src/cli/index.ts
7394
- init_utils();
7915
+ // packages/tooling/src/cli/doctor/check-env.ts
7916
+ var check_env_exports = {};
7917
+ __export(check_env_exports, {
7918
+ envCheck: () => envCheck,
7919
+ parseEnvFile: () => parseEnvFile
7920
+ });
7921
+ function parseEnvFile(filePath) {
7922
+ const map = /* @__PURE__ */ new Map();
7923
+ if (!pathExists(filePath)) return map;
7924
+ const content = readSync(filePath, { format: "text" });
7925
+ if (typeof content !== "string") return map;
7926
+ for (const line of content.split(/\r?\n/)) {
7927
+ const trimmed = line.trim();
7928
+ if (!trimmed || trimmed.startsWith("#")) continue;
7929
+ const eqIdx = trimmed.indexOf("=");
7930
+ if (eqIdx < 0) continue;
7931
+ const key = trimmed.substring(0, eqIdx).trim();
7932
+ const value = trimmed.substring(eqIdx + 1).trim();
7933
+ if (key) map.set(key, value);
7934
+ }
7935
+ return map;
7936
+ }
7937
+ var envCheck;
7938
+ var init_check_env = __esm({
7939
+ "packages/tooling/src/cli/doctor/check-env.ts"() {
7940
+ "use strict";
7941
+ init_utils();
7942
+ init_pathResolver();
7943
+ envCheck = {
7944
+ id: "env",
7945
+ name: "Environment Files",
7946
+ isRelevant(_ctx) {
7947
+ return true;
7948
+ },
7949
+ async run(ctx) {
7950
+ const results = [];
7951
+ const envPath = joinPath(ctx.appDir, ".env");
7952
+ const examplePath = joinPath(ctx.appDir, ".env.example");
7953
+ if (!pathExists(envPath)) {
7954
+ results.push({ name: ".env file", status: "fail", message: "Not found \u2014 run dndev setup" });
7955
+ return results;
7956
+ }
7957
+ results.push({ name: ".env file", status: "pass", message: "Found" });
7958
+ if (pathExists(examplePath)) {
7959
+ const example = parseEnvFile(examplePath);
7960
+ const actual = parseEnvFile(envPath);
7961
+ const missing = [];
7962
+ const empty = [];
7963
+ for (const [key] of example) {
7964
+ if (!actual.has(key)) {
7965
+ missing.push(key);
7966
+ } else if (!actual.get(key)) {
7967
+ empty.push(key);
7968
+ }
7969
+ }
7970
+ if (missing.length > 0) {
7971
+ results.push({
7972
+ name: "Missing vars",
7973
+ status: "fail",
7974
+ message: `${missing.length} var(s) in .env.example not in .env: ${missing.join(", ")}`
7975
+ });
7976
+ }
7977
+ if (empty.length > 0) {
7978
+ results.push({
7979
+ name: "Empty vars",
7980
+ status: "warn",
7981
+ message: `${empty.length} var(s) are empty: ${empty.join(", ")}`
7982
+ });
7983
+ }
7984
+ if (missing.length === 0 && empty.length === 0) {
7985
+ results.push({
7986
+ name: ".env vs .env.example",
7987
+ status: "pass",
7988
+ message: `All ${example.size} expected vars present`
7989
+ });
7990
+ }
7991
+ }
7992
+ const gitignorePath = joinPath(ctx.projectRoot, ".gitignore");
7993
+ if (pathExists(gitignorePath)) {
7994
+ const content = readSync(gitignorePath, { format: "text" });
7995
+ if (typeof content === "string") {
7996
+ const hasEnvIgnore = content.split("\n").some((line) => {
7997
+ const trimmed = line.trim();
7998
+ if (!trimmed || trimmed.startsWith("#")) return false;
7999
+ return /^\.env(\*|\..*)?$/.test(trimmed);
8000
+ });
8001
+ if (hasEnvIgnore) {
8002
+ results.push({ name: ".gitignore", status: "pass", message: ".env is gitignored" });
8003
+ } else {
8004
+ results.push({ name: ".gitignore", status: "warn", message: ".env might not be gitignored \u2014 verify manually" });
8005
+ }
8006
+ }
8007
+ }
8008
+ return results;
8009
+ }
8010
+ };
8011
+ }
8012
+ });
7395
8013
 
7396
- // packages/tooling/src/quality/lint.ts
7397
- init_utils();
7398
- init_cli_output();
7399
- init_errors();
7400
- init_pathResolver();
8014
+ // packages/tooling/src/cli/doctor/check-firebase.ts
8015
+ var check_firebase_exports = {};
8016
+ __export(check_firebase_exports, {
8017
+ firebaseCheck: () => firebaseCheck
8018
+ });
7401
8019
  import { spawnSync } from "node:child_process";
7402
- async function main(options = {}) {
7403
- const fix = options.fix ?? false;
7404
- const cwd = process.cwd();
7405
- const eslintConfigs = [
7406
- "eslint.config.js",
7407
- "eslint.config.mjs",
7408
- "eslint.config.cjs"
7409
- ];
7410
- const hasEslintConfig = eslintConfigs.some(
7411
- (config) => pathExists(joinPath(cwd, config))
7412
- );
7413
- if (!hasEslintConfig) {
7414
- log.info("No eslint.config.js found in current directory. Skipping lint.");
7415
- log.info("To enable linting, create an eslint.config.js file.");
7416
- return 0;
8020
+ var firebaseCheck;
8021
+ var init_check_firebase = __esm({
8022
+ "packages/tooling/src/cli/doctor/check-firebase.ts"() {
8023
+ "use strict";
8024
+ init_utils();
8025
+ init_pathResolver();
8026
+ firebaseCheck = {
8027
+ id: "firebase",
8028
+ name: "Firebase",
8029
+ isRelevant(ctx) {
8030
+ return pathExists(joinPath(ctx.appDir, "firebase.json")) || pathExists(joinPath(ctx.projectRoot, "firebase.json")) || pathExists(joinPath(ctx.projectRoot, ".firebaserc"));
8031
+ },
8032
+ async run(ctx) {
8033
+ const results = [];
8034
+ try {
8035
+ const result = spawnSync("firebase", ["--version"], {
8036
+ stdio: "pipe",
8037
+ encoding: "utf-8",
8038
+ timeout: 1e4
8039
+ });
8040
+ if (result.status === 0) {
8041
+ results.push({ name: "Firebase CLI", status: "pass", message: result.stdout.trim() });
8042
+ } else {
8043
+ results.push({ name: "Firebase CLI", status: "fail", message: "Not installed" });
8044
+ }
8045
+ } catch {
8046
+ results.push({ name: "Firebase CLI", status: "fail", message: "Not installed" });
8047
+ }
8048
+ const rcPath = joinPath(ctx.projectRoot, ".firebaserc");
8049
+ if (pathExists(rcPath)) {
8050
+ try {
8051
+ const raw = readSync(rcPath, { format: "text" });
8052
+ if (typeof raw !== "string") throw new Error("Not a string");
8053
+ const rc = JSON.parse(raw);
8054
+ const projects = rc?.projects;
8055
+ const projectId = projects && typeof projects === "object" ? projects.default : void 0;
8056
+ if (projectId && typeof projectId === "string") {
8057
+ results.push({ name: ".firebaserc", status: "pass", message: `Project: ${projectId}` });
8058
+ } else {
8059
+ results.push({ name: ".firebaserc", status: "warn", message: "No default project set" });
8060
+ }
8061
+ } catch {
8062
+ results.push({ name: ".firebaserc", status: "warn", message: "Invalid JSON" });
8063
+ }
8064
+ } else {
8065
+ results.push({ name: ".firebaserc", status: "fail", message: "Missing \u2014 run dndev setup firebase" });
8066
+ }
8067
+ const framework = ctx.app?.framework ?? "vite";
8068
+ const prefix = framework === "nextjs" ? "NEXT_PUBLIC_" : "VITE_";
8069
+ const envPath = joinPath(ctx.appDir, ".env");
8070
+ if (pathExists(envPath)) {
8071
+ const content = readSync(envPath, { format: "text" });
8072
+ if (typeof content === "string") {
8073
+ const requiredKeys = ["FIREBASE_API_KEY", "FIREBASE_PROJECT_ID", "FIREBASE_AUTH_DOMAIN"];
8074
+ const missing = requiredKeys.filter((key) => !content.includes(`${prefix}${key}=`));
8075
+ if (missing.length === 0) {
8076
+ results.push({ name: "Firebase .env", status: "pass", message: "All required keys present" });
8077
+ } else {
8078
+ results.push({ name: "Firebase .env", status: "fail", message: `Missing: ${missing.join(", ")}` });
8079
+ }
8080
+ }
8081
+ } else {
8082
+ results.push({ name: "Firebase .env", status: "fail", message: ".env file not found" });
8083
+ }
8084
+ const saKeyPaths = [
8085
+ joinPath(ctx.appDir, "service-account-key.json"),
8086
+ joinPath(ctx.projectRoot, "service-account-key.json")
8087
+ ];
8088
+ const saFound = saKeyPaths.some((p2) => pathExists(p2));
8089
+ if (saFound) {
8090
+ results.push({ name: "Service account key", status: "pass", message: "Found" });
8091
+ } else {
8092
+ results.push({ name: "Service account key", status: "warn", message: "Not found (needed for deploy/emu)" });
8093
+ }
8094
+ return results;
8095
+ }
8096
+ };
7417
8097
  }
7418
- const eslintArgs = fix ? ["--fix"] : [];
7419
- if (options.debug) {
7420
- eslintArgs.push("--debug");
8098
+ });
8099
+
8100
+ // packages/tooling/src/cli/setup/supabase.ts
8101
+ function isValidSupabaseUrl(url) {
8102
+ try {
8103
+ const parsed = new URL(url);
8104
+ return parsed.protocol === "https:" && (parsed.hostname.endsWith(".supabase.co") || parsed.hostname.endsWith(".supabase.in") || // Self-hosted or local
8105
+ parsed.hostname === "localhost" || parsed.hostname === "127.0.0.1");
8106
+ } catch {
8107
+ return false;
7421
8108
  }
7422
- if (options.quiet) {
7423
- eslintArgs.push("--quiet");
8109
+ }
8110
+ function isValidPublicKey(key) {
8111
+ return key.trim().length > 0;
8112
+ }
8113
+ var init_supabase = __esm({
8114
+ "packages/tooling/src/cli/setup/supabase.ts"() {
8115
+ "use strict";
8116
+ init_utils();
7424
8117
  }
7425
- if (options.debug || options.verbose) {
7426
- log.debug(`Linting code${fix ? " and fixing issues" : ""}...`);
7427
- log.debug(` Working directory: ${cwd}`);
7428
- log.debug(` ESLint args: ${eslintArgs.join(" ")}`);
7429
- } else {
7430
- log.info(fix ? "Linting and fixing code..." : "Linting code...");
8118
+ });
8119
+
8120
+ // packages/tooling/src/cli/doctor/check-supabase.ts
8121
+ var check_supabase_exports = {};
8122
+ __export(check_supabase_exports, {
8123
+ supabaseCheck: () => supabaseCheck
8124
+ });
8125
+ import { spawnSync as spawnSync2 } from "node:child_process";
8126
+ var supabaseCheck;
8127
+ var init_check_supabase = __esm({
8128
+ "packages/tooling/src/cli/doctor/check-supabase.ts"() {
8129
+ "use strict";
8130
+ init_utils();
8131
+ init_pathResolver();
8132
+ init_supabase();
8133
+ supabaseCheck = {
8134
+ id: "supabase",
8135
+ name: "Supabase",
8136
+ isRelevant(ctx) {
8137
+ return pathExists(joinPath(ctx.appDir, "supabase")) || pathExists(joinPath(ctx.appDir, "supabase", "config.toml"));
8138
+ },
8139
+ async run(ctx) {
8140
+ const results = [];
8141
+ const framework = ctx.app?.framework === "nextjs" ? "nextjs" : "vite";
8142
+ const prefix = framework === "nextjs" ? "NEXT_PUBLIC_" : "VITE_";
8143
+ try {
8144
+ const result = spawnSync2("supabase", ["--version"], {
8145
+ stdio: "pipe",
8146
+ encoding: "utf-8",
8147
+ timeout: 1e4
8148
+ });
8149
+ if (result.status === 0) {
8150
+ results.push({ name: "Supabase CLI", status: "pass", message: result.stdout.trim() });
8151
+ } else {
8152
+ results.push({ name: "Supabase CLI", status: "warn", message: "Not installed (needed for migrations)" });
8153
+ }
8154
+ } catch {
8155
+ results.push({ name: "Supabase CLI", status: "warn", message: "Not installed" });
8156
+ }
8157
+ const configPath = joinPath(ctx.appDir, "supabase", "config.toml");
8158
+ if (pathExists(configPath)) {
8159
+ results.push({ name: "config.toml", status: "pass", message: "Found" });
8160
+ } else {
8161
+ results.push({ name: "config.toml", status: "warn", message: "Missing (expected at supabase/config.toml)" });
8162
+ }
8163
+ const envPath = joinPath(ctx.appDir, ".env");
8164
+ if (pathExists(envPath)) {
8165
+ const content = readSync(envPath, { format: "text" });
8166
+ if (typeof content === "string") {
8167
+ const urlMatch = content.match(new RegExp(`${prefix}SUPABASE_URL=(.+)`));
8168
+ const url = urlMatch?.[1]?.trim();
8169
+ if (url && isValidSupabaseUrl(url)) {
8170
+ results.push({ name: "Supabase URL", status: "pass", message: url });
8171
+ } else if (url) {
8172
+ results.push({ name: "Supabase URL", status: "fail", message: "Invalid URL format" });
8173
+ } else {
8174
+ results.push({ name: "Supabase URL", status: "fail", message: "Missing in .env" });
8175
+ }
8176
+ const keyMatch = content.match(new RegExp(`${prefix}SUPABASE_(?:PUBLIC_KEY|ANON_KEY)=(.+)`));
8177
+ const key = keyMatch?.[1]?.trim();
8178
+ if (key && isValidPublicKey(key)) {
8179
+ results.push({ name: "Supabase public key", status: "pass", message: "Present" });
8180
+ } else {
8181
+ results.push({ name: "Supabase public key", status: "fail", message: "Missing in .env" });
8182
+ }
8183
+ }
8184
+ } else {
8185
+ results.push({ name: "Supabase .env", status: "fail", message: ".env file not found" });
8186
+ }
8187
+ const functionsEnvCandidates = [
8188
+ joinPath(ctx.appDir, "supabase", "functions", ".env"),
8189
+ joinPath(ctx.appDir, "functions", ".env")
8190
+ ];
8191
+ let secretFound = false;
8192
+ for (const fenvPath of functionsEnvCandidates) {
8193
+ if (!pathExists(fenvPath)) continue;
8194
+ const content = readSync(fenvPath, { format: "text" });
8195
+ if (typeof content === "string" && content.match(/SUPABASE_(?:SECRET|SERVICE_ROLE)_KEY=.+/)) {
8196
+ secretFound = true;
8197
+ results.push({ name: "Secret key", status: "pass", message: `Found in ${fenvPath.split("/").pop()}` });
8198
+ break;
8199
+ }
8200
+ }
8201
+ if (!secretFound) {
8202
+ results.push({ name: "Secret key", status: "warn", message: "Not found (needed for migrations + deploy)" });
8203
+ }
8204
+ return results;
8205
+ }
8206
+ };
7431
8207
  }
7432
- try {
7433
- const result = spawnSync("bunx", ["eslint", ".", ...eslintArgs], {
7434
- cwd,
7435
- stdio: "inherit",
7436
- env: process.env,
7437
- shell: true
7438
- });
7439
- const exitCode = result.status ?? 1;
7440
- if (exitCode === 0) {
7441
- if (!options.debug && !options.verbose) {
7442
- log.success("Linting completed successfully");
8208
+ });
8209
+
8210
+ // packages/tooling/src/cli/doctor/check-stripe.ts
8211
+ var check_stripe_exports = {};
8212
+ __export(check_stripe_exports, {
8213
+ stripeCheck: () => stripeCheck
8214
+ });
8215
+ function readEnvValue(envPath, varName) {
8216
+ if (!pathExists(envPath)) return null;
8217
+ const content = readSync(envPath, { format: "text" });
8218
+ if (typeof content !== "string") return null;
8219
+ for (const line of content.split(/\r?\n/)) {
8220
+ const trimmed = line.trim();
8221
+ if (!trimmed || trimmed.startsWith("#")) continue;
8222
+ if (trimmed.startsWith(`${varName}=`)) {
8223
+ let val = trimmed.substring(`${varName}=`.length).trim();
8224
+ if (val.startsWith('"') && val.endsWith('"') || val.startsWith("'") && val.endsWith("'")) {
8225
+ val = val.slice(1, -1);
8226
+ }
8227
+ return val || null;
8228
+ }
8229
+ }
8230
+ return null;
8231
+ }
8232
+ function findFunctionsEnv(ctx) {
8233
+ const candidates = [
8234
+ joinPath(ctx.appDir, "supabase", "functions", ".env"),
8235
+ joinPath(ctx.appDir, "functions", ".env")
8236
+ ];
8237
+ return candidates.find((p2) => pathExists(p2)) ?? null;
8238
+ }
8239
+ var stripeCheck;
8240
+ var init_check_stripe = __esm({
8241
+ "packages/tooling/src/cli/doctor/check-stripe.ts"() {
8242
+ "use strict";
8243
+ init_utils();
8244
+ init_pathResolver();
8245
+ stripeCheck = {
8246
+ id: "stripe",
8247
+ name: "Stripe",
8248
+ isRelevant(ctx) {
8249
+ const pkgPath = joinPath(ctx.appDir, "package.json");
8250
+ if (pathExists(pkgPath)) {
8251
+ const pkg = readSync(pkgPath, { format: "json" });
8252
+ if (pkg && typeof pkg === "object") {
8253
+ const deps = pkg.dependencies;
8254
+ if (deps?.["@donotdev/billing"]) return true;
8255
+ }
8256
+ }
8257
+ const envPath = joinPath(ctx.appDir, ".env");
8258
+ if (pathExists(envPath)) {
8259
+ const content = readSync(envPath, { format: "text" });
8260
+ if (typeof content === "string" && content.includes("STRIPE_PUBLISHABLE_KEY")) return true;
8261
+ }
8262
+ return false;
8263
+ },
8264
+ async run(ctx) {
8265
+ const results = [];
8266
+ const framework = ctx.app?.framework ?? "vite";
8267
+ const prefix = framework === "nextjs" ? "NEXT_PUBLIC_" : "VITE_";
8268
+ const envPath = joinPath(ctx.appDir, ".env");
8269
+ const functionsEnvPath = findFunctionsEnv(ctx);
8270
+ const pk = readEnvValue(envPath, `${prefix}STRIPE_PUBLISHABLE_KEY`);
8271
+ let pkMode = null;
8272
+ if (pk) {
8273
+ if (pk.startsWith("pk_test_") || pk.startsWith("pk_live_")) {
8274
+ pkMode = pk.startsWith("pk_test_") ? "test" : "live";
8275
+ results.push({ name: "Publishable key", status: "pass", message: `Valid (${pkMode} mode)` });
8276
+ } else {
8277
+ results.push({ name: "Publishable key", status: "fail", message: "Invalid format \u2014 must start with pk_test_ or pk_live_" });
8278
+ }
8279
+ } else {
8280
+ results.push({ name: "Publishable key", status: "fail", message: "Missing in .env" });
8281
+ }
8282
+ let skMode = null;
8283
+ if (functionsEnvPath) {
8284
+ const sk = readEnvValue(functionsEnvPath, "STRIPE_SECRET_KEY");
8285
+ if (sk) {
8286
+ if (sk.startsWith("sk_test_") || sk.startsWith("sk_live_") || sk.startsWith("rk_test_") || sk.startsWith("rk_live_")) {
8287
+ skMode = sk.includes("_test_") ? "test" : "live";
8288
+ results.push({ name: "Secret key", status: "pass", message: `Valid (${skMode} mode)` });
8289
+ } else {
8290
+ results.push({ name: "Secret key", status: "fail", message: "STRIPE_SECRET_KEY has invalid format" });
8291
+ }
8292
+ } else {
8293
+ results.push({ name: "Secret key", status: "warn", message: "Not found in functions/.env" });
8294
+ }
8295
+ } else {
8296
+ results.push({ name: "Secret key", status: "warn", message: "No functions/.env found" });
8297
+ }
8298
+ if (functionsEnvPath) {
8299
+ const wh = readEnvValue(functionsEnvPath, "STRIPE_WEBHOOK_SECRET");
8300
+ if (wh) {
8301
+ if (wh.startsWith("whsec_")) {
8302
+ results.push({ name: "Webhook secret", status: "pass", message: "Valid format" });
8303
+ } else {
8304
+ results.push({ name: "Webhook secret", status: "fail", message: "STRIPE_WEBHOOK_SECRET has invalid format" });
8305
+ }
8306
+ } else {
8307
+ results.push({ name: "Webhook secret", status: "warn", message: "Not found \u2014 webhooks won't verify" });
8308
+ }
8309
+ }
8310
+ if (pkMode && skMode) {
8311
+ if (pkMode !== skMode) {
8312
+ results.push({ name: "Key mode", status: "warn", message: `Publishable key is ${pkMode} but secret key is ${skMode}` });
8313
+ } else {
8314
+ results.push({ name: "Key mode", status: "pass", message: `Both keys are ${pkMode}` });
8315
+ }
8316
+ }
8317
+ return results;
7443
8318
  }
7444
- } else {
7445
- if (!options.debug && !options.verbose) {
7446
- log.error("Linting found issues (see above for details)");
8319
+ };
8320
+ }
8321
+ });
8322
+
8323
+ // packages/tooling/src/cli/doctor/check-auth.ts
8324
+ var check_auth_exports = {};
8325
+ __export(check_auth_exports, {
8326
+ authCheck: () => authCheck
8327
+ });
8328
+ var authCheck;
8329
+ var init_check_auth = __esm({
8330
+ "packages/tooling/src/cli/doctor/check-auth.ts"() {
8331
+ "use strict";
8332
+ init_utils();
8333
+ init_pathResolver();
8334
+ authCheck = {
8335
+ id: "auth",
8336
+ name: "Authentication",
8337
+ isRelevant(ctx) {
8338
+ const pkgPath = joinPath(ctx.appDir, "package.json");
8339
+ if (pathExists(pkgPath)) {
8340
+ const content = readSync(pkgPath, { format: "text" });
8341
+ if (typeof content === "string" && content.includes("@donotdev/auth")) return true;
8342
+ }
8343
+ return false;
8344
+ },
8345
+ async run(ctx) {
8346
+ const results = [];
8347
+ results.push({ name: "@donotdev/auth", status: "pass", message: "Installed" });
8348
+ const candidates = [
8349
+ joinPath(ctx.appDir, "src", "providers.ts"),
8350
+ joinPath(ctx.appDir, "src", "providers.tsx"),
8351
+ joinPath(ctx.appDir, "src", "config", "providers.ts"),
8352
+ joinPath(ctx.appDir, "src", "lib", "providers.ts")
8353
+ ];
8354
+ const providerFile = candidates.find((c) => pathExists(c));
8355
+ if (providerFile) {
8356
+ results.push({
8357
+ name: "Providers config",
8358
+ status: "pass",
8359
+ message: `Found: ${providerFile.split("/").slice(-2).join("/")}`
8360
+ });
8361
+ const content = readSync(providerFile, { format: "text" });
8362
+ if (typeof content === "string") {
8363
+ const providers = [];
8364
+ if (content.includes("email") || content.includes("Email")) providers.push("email");
8365
+ if (content.includes("google") || content.includes("Google")) providers.push("google");
8366
+ if (content.includes("github") || content.includes("GitHub")) providers.push("github");
8367
+ if (content.includes("apple") || content.includes("Apple")) providers.push("apple");
8368
+ if (providers.length > 0) {
8369
+ results.push({
8370
+ name: "Auth providers",
8371
+ status: "pass",
8372
+ message: `Configured: ${providers.join(", ")}`
8373
+ });
8374
+ }
8375
+ }
8376
+ } else {
8377
+ results.push({ name: "Providers config", status: "warn", message: "No providers.ts found \u2014 auth may not work" });
8378
+ }
8379
+ const hasFirebase = pathExists(joinPath(ctx.projectRoot, ".firebaserc"));
8380
+ const hasSupabase = pathExists(joinPath(ctx.appDir, "supabase"));
8381
+ if (hasFirebase) {
8382
+ results.push({
8383
+ name: "Backend",
8384
+ status: "pass",
8385
+ message: "Firebase Auth (verify providers are enabled in console)",
8386
+ detail: "Run dndev setup auth for setup coaching"
8387
+ });
8388
+ } else if (hasSupabase) {
8389
+ results.push({
8390
+ name: "Backend",
8391
+ status: "pass",
8392
+ message: "Supabase Auth (verify providers are enabled in dashboard)",
8393
+ detail: "Run dndev setup auth for setup coaching"
8394
+ });
8395
+ } else {
8396
+ results.push({ name: "Backend", status: "warn", message: "No backend detected for auth" });
8397
+ }
8398
+ return results;
8399
+ }
8400
+ };
8401
+ }
8402
+ });
8403
+
8404
+ // packages/tooling/src/cli/doctor/doctor.ts
8405
+ function renderResults(allResults, verbose) {
8406
+ const lines = [];
8407
+ for (const { checkName, results } of allResults) {
8408
+ lines.push(checkName);
8409
+ for (const result of results) {
8410
+ const icon = STATUS_ICONS[result.status];
8411
+ lines.push(` ${icon} ${result.name}: ${result.message}`);
8412
+ if (verbose && result.detail) {
8413
+ lines.push(` ${result.detail}`);
7447
8414
  }
7448
8415
  }
7449
- return exitCode;
7450
- } catch (err) {
7451
- throw DoNotDevError.from(
7452
- err,
7453
- "Failed to run ESLint",
7454
- "cli-execution-error"
7455
- );
8416
+ lines.push("");
7456
8417
  }
8418
+ Me(lines.join("\n"), "Health Check Results");
7457
8419
  }
8420
+ async function main(options = {}) {
8421
+ Ie("DoNotDev Doctor");
8422
+ const projectRoot = process.cwd();
8423
+ let appDir = projectRoot;
8424
+ let app = null;
8425
+ const appsDir = joinPath(projectRoot, "apps");
8426
+ if (pathExists(appsDir)) {
8427
+ try {
8428
+ app = await selectApp(projectRoot, options.app);
8429
+ if (app) {
8430
+ appDir = app.path;
8431
+ }
8432
+ } catch {
8433
+ }
8434
+ }
8435
+ const ctx = {
8436
+ projectRoot,
8437
+ appDir,
8438
+ app,
8439
+ verbose: options.verbose
8440
+ };
8441
+ const allResults = [];
8442
+ let hasFail = false;
8443
+ const registry = options.check ? CHECK_REGISTRY.filter((e2) => e2.id === options.check) : CHECK_REGISTRY;
8444
+ if (options.check && registry.length === 0) {
8445
+ log.error(`Unknown check: ${options.check}. Available: ${CHECK_REGISTRY.map((e2) => e2.id).join(", ")}`);
8446
+ Se("Doctor aborted.");
8447
+ return 1;
8448
+ }
8449
+ for (const entry of registry) {
8450
+ const check = await entry.load();
8451
+ if (!check.isRelevant(ctx)) continue;
8452
+ const results = await check.run(ctx);
8453
+ allResults.push({ checkName: check.name, results });
8454
+ if (results.some((r2) => r2.status === "fail")) {
8455
+ hasFail = true;
8456
+ }
8457
+ }
8458
+ if (allResults.length === 0) {
8459
+ log.warn("No checks were relevant for this project.");
8460
+ Se("Nothing to check.");
8461
+ return 0;
8462
+ }
8463
+ renderResults(allResults, options.verbose ?? false);
8464
+ let passes = 0;
8465
+ let warnings = 0;
8466
+ let fails = 0;
8467
+ for (const { results } of allResults) {
8468
+ for (const r2 of results) {
8469
+ if (r2.status === "pass") passes++;
8470
+ else if (r2.status === "warn") warnings++;
8471
+ else if (r2.status === "fail") fails++;
8472
+ }
8473
+ }
8474
+ const totalChecks = passes + warnings + fails;
8475
+ const summaryParts = [`${passes}/${totalChecks} passed`];
8476
+ if (warnings > 0) summaryParts.push(`${warnings} warning(s)`);
8477
+ if (fails > 0) summaryParts.push(`${fails} failure(s)`);
8478
+ const exitCode = hasFail ? 1 : 0;
8479
+ Se(hasFail ? `Health check failed: ${summaryParts.join(", ")}` : `All clear: ${summaryParts.join(", ")}`);
8480
+ return exitCode;
8481
+ }
8482
+ var CHECK_REGISTRY, STATUS_ICONS;
8483
+ var init_doctor = __esm({
8484
+ "packages/tooling/src/cli/doctor/doctor.ts"() {
8485
+ "use strict";
8486
+ init_utils();
8487
+ init_cli_output();
8488
+ init_app_selector();
8489
+ init_pathResolver();
8490
+ CHECK_REGISTRY = [
8491
+ { id: "env", load: async () => (await Promise.resolve().then(() => (init_check_env(), check_env_exports))).envCheck },
8492
+ { id: "firebase", load: async () => (await Promise.resolve().then(() => (init_check_firebase(), check_firebase_exports))).firebaseCheck },
8493
+ { id: "supabase", load: async () => (await Promise.resolve().then(() => (init_check_supabase(), check_supabase_exports))).supabaseCheck },
8494
+ { id: "stripe", load: async () => (await Promise.resolve().then(() => (init_check_stripe(), check_stripe_exports))).stripeCheck },
8495
+ { id: "auth", load: async () => (await Promise.resolve().then(() => (init_check_auth(), check_auth_exports))).authCheck }
8496
+ ];
8497
+ STATUS_ICONS = {
8498
+ pass: "\u2705",
8499
+ // green check
8500
+ warn: "\u26A0\uFE0F",
8501
+ // warning
8502
+ fail: "\u274C"
8503
+ // red x
8504
+ };
8505
+ }
8506
+ });
8507
+
8508
+ // packages/cli/src/bin/commands/doctor.ts
8509
+ init_utils();
8510
+
8511
+ // packages/tooling/src/index.ts
8512
+ init_utils();
8513
+
8514
+ // packages/tooling/src/cli/index.ts
8515
+ init_utils();
8516
+ init_doctor();
7458
8517
  export {
7459
8518
  main
7460
8519
  };