create-better-fullstack 2.1.6 → 2.1.8

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 (28) hide show
  1. package/dist/{add-handler-CuPmSJRM.mjs → add-handler-ztNjzoMN.mjs} +43 -5
  2. package/dist/addons-setup-DnLjAzTw.mjs +7 -0
  3. package/dist/{addons-setup-C_lxdJqU.mjs → addons-setup-LaAj43NP.mjs} +3 -24
  4. package/dist/analytics-DVltG11u.mjs +170 -0
  5. package/dist/{bts-config-BceXPcpI.mjs → bts-config-DQVWvPDs.mjs} +70 -66
  6. package/dist/cli.mjs +2 -2
  7. package/dist/{config-processing-B_1wTe3g.mjs → config-processing-D9-F2Us9.mjs} +1 -1
  8. package/dist/{doctor-DucDyWfl.mjs → doctor-a4ca3SMd.mjs} +2 -2
  9. package/dist/{file-formatter-XU6ti05V.mjs → file-formatter-gvmrpd-g.mjs} +13 -1
  10. package/dist/{gen-DWx3Xu_K.mjs → gen-CCClL7Ve.mjs} +1 -1
  11. package/dist/{generated-checks-Dt4Xqp1x.mjs → generated-checks-BV9jol5h.mjs} +1 -1
  12. package/dist/index.d.mts +27 -21
  13. package/dist/index.mjs +10 -8
  14. package/dist/{install-dependencies-DHoYa3P-.mjs → install-dependencies-RoUyaE8o.mjs} +7 -2
  15. package/dist/mcp-492OkjcS.mjs +11 -0
  16. package/dist/mcp-entry.mjs +56 -18
  17. package/dist/prompt-environment-BR0Kkw2W.mjs +26 -0
  18. package/dist/{registry-CxeEOPot.mjs → registry-DSf2CEaU.mjs} +27 -13
  19. package/dist/run-CD8f7PHh.mjs +15 -0
  20. package/dist/{run-D80ZtSO8.mjs → run-T6g1jkfy.mjs} +1810 -444
  21. package/dist/scaffold-manifest-DGRyepdb.mjs +4 -0
  22. package/dist/{scaffold-manifest-GV1fbhpD.mjs → scaffold-manifest-Dyi0voqE.mjs} +13 -1
  23. package/dist/{update-C9_x2yBF.mjs → update-DJ8CI5KW.mjs} +3 -3
  24. package/package.json +3 -3
  25. package/dist/addons-setup-DEPfsn6z.mjs +0 -6
  26. package/dist/mcp-D9O5zgAA.mjs +0 -8
  27. package/dist/run-3AkXloH1.mjs +0 -13
  28. /package/dist/{update-deps-DLZAuT3V.mjs → update-deps-aD-iQw4U.mjs} +0 -0
@@ -1,14 +1,16 @@
1
1
  #!/usr/bin/env node
2
- import { c as DEFAULT_CONFIG, d as getUserPkgManager, g as getGraphSummary, h as getGraphPart, i as readBtsConfigFromFile, l as DEFAULT_UI_LIBRARY_BY_FRONTEND, m as getGraphBackendUrl, o as writeBtsConfig, p as getGraphBackendDeployInstructions, s as getLatestCLIVersion, t as buildBtsConfigForPersistence, u as getDefaultConfig, v as hasGraphPart, y as types_exports } from "./bts-config-BceXPcpI.mjs";
2
+ import { _ as DEFAULT_UI_LIBRARY_BY_FRONTEND, b as types_exports, c as getGraphBackendDeployInstructions, d as getGraphSummary, g as DEFAULT_CONFIG, h as BUILDER_URL, i as readBtsConfigFromFile, l as getGraphBackendUrl, m as getLatestCLIVersion, o as writeBtsConfig, p as hasGraphPart, t as buildBtsConfigForPersistence, u as getGraphPart, v as getDefaultConfig, y as getUserPkgManager } from "./bts-config-DQVWvPDs.mjs";
3
3
  import { t as renderTitle } from "./render-title-zvyKC1ej.mjs";
4
4
  import { a as handleError, c as isSilent, d as setLastPromptShownUI, i as exitWithError, l as runWithContextAsync, n as UserCancelledError, o as didLastPromptShowUI, r as exitCancelled, s as isFirstPrompt, t as CLIError, u as setIsFirstPrompt } from "./errors-ns_o2OKg.mjs";
5
- import { i as canPromptInteractively, n as getPackageExecutionArgs, r as addPackageDependency, t as setupAddons } from "./addons-setup-C_lxdJqU.mjs";
6
- import { _ as CreateCommandInputSchema, a as allowedApisForFrontends$1, c as getCompatibleUILibraries$1, d as isExampleChatSdkAllowed$1, f as isFrontendAllowedWithBackend$1, h as splitFrontends$1, i as validateFullConfig, l as hasWebStyling$1, m as requiresChatSdkVercelAI, n as formatProject, p as isWebFrontend$1, r as validateConfigForProgrammaticUse, s as getCompatibleCSSFrameworks$1, u as isExampleAIAllowed$1, v as CreateCommandOptionsSchema } from "./file-formatter-XU6ti05V.mjs";
7
- import { _ as isGoBack, a as runMavenTests, c as applyDependencyVersionChannel, d as isCancel$1, f as navigableConfirm, g as GO_BACK_SYMBOL, h as setIsFirstPrompt$1, i as runGradleTests, l as getAddonsChoice, m as navigableSelect, n as runCargoBuild, o as runMixCompile, p as navigableMultiselect, r as runGoModTidy, s as runUvSync, t as installDependencies } from "./install-dependencies-DHoYa3P-.mjs";
8
- import { n as commandExists, t as runGeneratedChecks } from "./generated-checks-Dt4Xqp1x.mjs";
9
- import { a as getTemplateConfig, i as validateArrayOptions, n as getProvidedFlags, o as getTemplateDescription, r as processFlags, s as generateReproducibleCommand, t as applyEffectBackendDefaults } from "./config-processing-B_1wTe3g.mjs";
10
- import { r as recordScaffoldManifest } from "./scaffold-manifest-GV1fbhpD.mjs";
11
- import { cancel, confirm, intro, isCancel, log, outro, select, spinner, text } from "@clack/prompts";
5
+ import { t as canPromptInteractively } from "./prompt-environment-BR0Kkw2W.mjs";
6
+ import { a as trackProjectCreation, i as trackEvent, n as isTelemetryEnabled, o as getPersistedTelemetryPreference, r as maybeShowTelemetryNotice, s as setTelemetryPreference, t as hasTelemetryEnvOverride } from "./analytics-DVltG11u.mjs";
7
+ import { _ as CreateCommandInputSchema, a as allowedApisForFrontends$1, c as getCompatibleUILibraries$1, d as isExampleChatSdkAllowed$1, f as isFrontendAllowedWithBackend$1, h as splitFrontends$1, i as validateFullConfig, l as hasWebStyling$1, m as requiresChatSdkVercelAI, n as formatProject, p as isWebFrontend$1, r as validateConfigForProgrammaticUse, s as getCompatibleCSSFrameworks$1, u as isExampleAIAllowed$1, v as CreateCommandOptionsSchema } from "./file-formatter-gvmrpd-g.mjs";
8
+ import { _ as isGoBack, a as runMavenTests, c as applyDependencyVersionChannel, d as isCancel$1, f as navigableConfirm, g as GO_BACK_SYMBOL, h as setIsFirstPrompt$1, i as runGradleTests, l as getAddonsChoice, m as navigableSelect, n as runCargoBuild, o as runMixCompile, p as navigableMultiselect, r as runGoModTidy, s as runUvSync, t as installDependencies } from "./install-dependencies-RoUyaE8o.mjs";
9
+ import { n as commandExists, t as runGeneratedChecks } from "./generated-checks-BV9jol5h.mjs";
10
+ import { a as getTemplateConfig, i as validateArrayOptions, n as getProvidedFlags, o as getTemplateDescription, r as processFlags, s as generateReproducibleCommand, t as applyEffectBackendDefaults } from "./config-processing-D9-F2Us9.mjs";
11
+ import { a as recordScaffoldManifest } from "./scaffold-manifest-Dyi0voqE.mjs";
12
+ import { n as getPackageExecutionArgs, r as addPackageDependency, t as setupAddons } from "./addons-setup-LaAj43NP.mjs";
13
+ import { cancel, confirm, intro, isCancel, log, note, outro, select, spinner, text } from "@clack/prompts";
12
14
  import { createRouterClient, os } from "@orpc/server";
13
15
  import pc from "picocolors";
14
16
  import { createCli } from "trpc-cli";
@@ -22,10 +24,10 @@ import { $, execa } from "execa";
22
24
  import os$1 from "node:os";
23
25
 
24
26
  //#region src/utils/project-history.ts
25
- const paths$1 = envPaths("better-fullstack", { suffix: "" });
27
+ const paths = envPaths("better-fullstack", { suffix: "" });
26
28
  const HISTORY_FILE = "history.json";
27
29
  function getHistoryPath() {
28
- return path.join(paths$1.data, HISTORY_FILE);
30
+ return path.join(paths.data, HISTORY_FILE);
29
31
  }
30
32
  function generateId() {
31
33
  return `${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;
@@ -48,7 +50,7 @@ async function readHistory() {
48
50
  }
49
51
  }
50
52
  async function writeHistory(history$1) {
51
- await fs.ensureDir(paths$1.data);
53
+ await fs.ensureDir(paths.data);
52
54
  await fs.writeJson(getHistoryPath(), history$1, { spaces: 2 });
53
55
  }
54
56
  async function addToHistory(config, reproducibleCommand) {
@@ -155,141 +157,13 @@ async function historyHandler(input) {
155
157
  }
156
158
  }
157
159
 
158
- //#endregion
159
- //#region src/utils/telemetry-settings.ts
160
- const paths = envPaths("better-fullstack", { suffix: "" });
161
- const SETTINGS_FILE = "telemetry.json";
162
- function getSettingsPath() {
163
- return path.join(paths.data, SETTINGS_FILE);
164
- }
165
- function emptySettings() {
166
- return {
167
- version: 1,
168
- noticeShown: false
169
- };
170
- }
171
- async function readTelemetrySettings() {
172
- const settingsPath = getSettingsPath();
173
- if (!await fs.pathExists(settingsPath)) return emptySettings();
174
- try {
175
- const data = await fs.readJson(settingsPath);
176
- if (!data || typeof data !== "object") return emptySettings();
177
- return {
178
- version: typeof data.version === "number" ? data.version : 1,
179
- enabled: typeof data.enabled === "boolean" ? data.enabled : void 0,
180
- noticeShown: data.noticeShown === true
181
- };
182
- } catch {
183
- return emptySettings();
184
- }
185
- }
186
- async function writeTelemetrySettings(settings) {
187
- await fs.ensureDir(paths.data);
188
- await fs.writeJson(getSettingsPath(), settings, { spaces: 2 });
189
- }
190
- /**
191
- * The user's explicit persisted preference, or `undefined` when they never chose.
192
- */
193
- async function getPersistedTelemetryPreference() {
194
- return (await readTelemetrySettings()).enabled;
195
- }
196
- /**
197
- * Persist an explicit opt-in/opt-out. Choosing a preference also marks the
198
- * first-run notice as shown so it never appears afterwards.
199
- */
200
- async function setTelemetryPreference(enabled) {
201
- const settings = await readTelemetrySettings();
202
- settings.enabled = enabled;
203
- settings.noticeShown = true;
204
- await writeTelemetrySettings(settings);
205
- }
206
- async function hasTelemetryNoticeBeenShown() {
207
- return (await readTelemetrySettings()).noticeShown;
208
- }
209
- async function markTelemetryNoticeShown() {
210
- const settings = await readTelemetrySettings();
211
- settings.noticeShown = true;
212
- await writeTelemetrySettings(settings);
213
- }
214
-
215
- //#endregion
216
- //#region src/utils/analytics.ts
217
- const CONVEX_INGEST_URL = "https://curious-elephant-653.convex.site/api/analytics/ingest";
218
- /**
219
- * Whether telemetry is explicitly overridden at runtime.
220
- *
221
- * Only `BTS_TELEMETRY_DISABLED` is a runtime override: `BTS_TELEMETRY` is inlined
222
- * by the bundler at build time (see tsdown.config.ts) and therefore acts as a
223
- * build-time default, not a runtime switch.
224
- */
225
- function hasTelemetryEnvOverride() {
226
- return process.env.BTS_TELEMETRY_DISABLED !== void 0;
227
- }
228
- /**
229
- * Resolve whether telemetry is enabled.
230
- *
231
- * Precedence: runtime env override (`BTS_TELEMETRY_DISABLED`) > persisted
232
- * preference > default. The default honors the build-time `BTS_TELEMETRY` flag
233
- * (inlined by the bundler, "0" by default) and falls back to enabled when the
234
- * flag is unset (e.g. running from source).
235
- *
236
- * `BTS_TELEMETRY` is intentionally evaluated last: the bundler replaces it with
237
- * a literal, so an early `!== undefined` check would always short-circuit and
238
- * make the persisted preference unreachable in the shipped CLI.
239
- */
240
- async function isTelemetryEnabled() {
241
- const disabled = process.env.BTS_TELEMETRY_DISABLED;
242
- if (disabled !== void 0) return disabled !== "1";
243
- const persisted = await getPersistedTelemetryPreference();
244
- if (persisted !== void 0) return persisted;
245
- const buildDefault = "1";
246
- return buildDefault === void 0 ? true : buildDefault === "1";
247
- }
248
- /**
249
- * Print a one-time notice describing the anonymous telemetry the CLI collects
250
- * and how to opt out, then remember that it was shown so it never repeats.
251
- *
252
- * No-ops when telemetry is explicitly configured via env var, when a persisted
253
- * preference already exists, when the notice was already shown, when telemetry
254
- * is disabled by the build default, or when the CLI is not running interactively
255
- * (CI / silent / non-TTY).
256
- */
257
- async function maybeShowTelemetryNotice() {
258
- if (hasTelemetryEnvOverride()) return;
259
- if (!canPromptInteractively()) return;
260
- if (await getPersistedTelemetryPreference() !== void 0) return;
261
- if (await hasTelemetryNoticeBeenShown()) return;
262
- if (!await isTelemetryEnabled()) return;
263
- log.info(`${pc.bold("Anonymous usage telemetry is enabled.")}\n${pc.dim("We collect your selected stack options (e.g. frontend, backend, database),")}\n${pc.dim("plus CLI version, Node.js version, and OS platform — never project names,")}\n${pc.dim("file paths, or any personal data.")}\nOpt out anytime with ${pc.cyan("create-better-fullstack telemetry disable")} or ${pc.cyan("BTS_TELEMETRY_DISABLED=1")}.`);
264
- try {
265
- await markTelemetryNoticeShown();
266
- } catch {}
267
- }
268
- async function sendConvexEvent(payload) {
269
- try {
270
- await fetch(CONVEX_INGEST_URL, {
271
- method: "POST",
272
- headers: { "Content-Type": "application/json" },
273
- body: JSON.stringify(payload)
274
- });
275
- } catch {}
276
- }
277
- async function trackProjectCreation(config, disableAnalytics = false) {
278
- if (disableAnalytics || !await isTelemetryEnabled()) return;
279
- const { projectName: _projectName, projectDir: _projectDir, relativePath: _relativePath, ...safeConfig } = config;
280
- try {
281
- await sendConvexEvent({
282
- ...safeConfig,
283
- cli_version: getLatestCLIVersion(),
284
- node_version: typeof process !== "undefined" ? process.version : "",
285
- platform: typeof process !== "undefined" ? process.platform : ""
286
- });
287
- } catch {}
288
- }
289
-
290
160
  //#endregion
291
161
  //#region src/commands/telemetry.ts
292
- const COLLECTED = ["Selected stack options (frontend, backend, database, ORM, auth, API, etc.)", "CLI version, Node.js version, and OS platform"];
162
+ const COLLECTED = [
163
+ "Selected stack options (frontend, backend, database, ORM, auth, API, etc.)",
164
+ "CLI version, Node.js version, and OS platform",
165
+ "A random anonymous install ID used to count unique and returning installs"
166
+ ];
293
167
  const NOT_COLLECTED = ["Project names, directory paths, or file contents", "Personal or otherwise identifying information"];
294
168
  function resolveSource(persisted) {
295
169
  if (hasTelemetryEnvOverride()) return "env";
@@ -1020,6 +894,475 @@ async function getCMSChoice(cms, backend) {
1020
894
  return response;
1021
895
  }
1022
896
 
897
+ //#endregion
898
+ //#region src/prompts/config-scope.ts
899
+ const CONFIG_SCOPE_ALWAYS_KEYS = [
900
+ "aiDocs",
901
+ "git",
902
+ "workspaceShape",
903
+ "packageManager",
904
+ "install"
905
+ ];
906
+ const sharedServiceSection = {
907
+ id: "shared-services",
908
+ label: "Shared Services",
909
+ promptKeys: [
910
+ "email",
911
+ "caching",
912
+ "search",
913
+ "observability"
914
+ ]
915
+ };
916
+ const typescriptSections = [
917
+ {
918
+ id: "ui-styling",
919
+ label: "UI & Styling",
920
+ promptKeys: [
921
+ "uiLibrary",
922
+ "shadcnOptions",
923
+ "cssFramework"
924
+ ]
925
+ },
926
+ {
927
+ id: "state-forms",
928
+ label: "State, Forms & Animation",
929
+ promptKeys: [
930
+ "stateManagement",
931
+ "forms",
932
+ "animation"
933
+ ]
934
+ },
935
+ {
936
+ id: "type-safety",
937
+ label: "Validation & Effect",
938
+ promptKeys: ["validation", "effect"]
939
+ },
940
+ {
941
+ id: "payments-email",
942
+ label: "Payments & Email",
943
+ promptKeys: ["payments", "email"]
944
+ },
945
+ {
946
+ id: "ai",
947
+ label: "AI & Vector DB",
948
+ promptKeys: ["ai", "vectorDb"]
949
+ },
950
+ {
951
+ id: "data-storage",
952
+ label: "Data & Storage",
953
+ promptKeys: [
954
+ "caching",
955
+ "search",
956
+ "fileStorage",
957
+ "fileUpload"
958
+ ]
959
+ },
960
+ {
961
+ id: "backend-extras",
962
+ label: "Jobs, Realtime & Rate Limiting",
963
+ promptKeys: [
964
+ "jobQueue",
965
+ "realtime",
966
+ "rateLimit"
967
+ ]
968
+ },
969
+ {
970
+ id: "quality",
971
+ label: "Testing & Observability",
972
+ promptKeys: [
973
+ "testing",
974
+ "logging",
975
+ "observability"
976
+ ]
977
+ },
978
+ {
979
+ id: "content",
980
+ label: "Content, Analytics & i18n",
981
+ promptKeys: [
982
+ "cms",
983
+ "analytics",
984
+ "i18n",
985
+ "featureFlags"
986
+ ]
987
+ },
988
+ {
989
+ id: "deploy",
990
+ label: "Deployment",
991
+ promptKeys: ["webDeploy", "serverDeploy"]
992
+ },
993
+ {
994
+ id: "addons-examples",
995
+ label: "Addons & Examples",
996
+ promptKeys: ["addons", "examples"]
997
+ }
998
+ ];
999
+ const CONFIG_SCOPE_REGISTRY = {
1000
+ typescript: {
1001
+ core: [
1002
+ "frontend",
1003
+ "astroIntegration",
1004
+ "backend",
1005
+ "runtime",
1006
+ "database",
1007
+ "orm",
1008
+ "api",
1009
+ "auth",
1010
+ "dbSetup"
1011
+ ],
1012
+ sections: typescriptSections
1013
+ },
1014
+ "react-native": {
1015
+ core: [
1016
+ "frontend",
1017
+ "mobileNavigation",
1018
+ "backend",
1019
+ "runtime",
1020
+ "database",
1021
+ "orm",
1022
+ "api",
1023
+ "auth",
1024
+ "dbSetup"
1025
+ ],
1026
+ sections: [
1027
+ {
1028
+ id: "mobile-experience",
1029
+ label: "Mobile Experience",
1030
+ promptKeys: [
1031
+ "mobileUI",
1032
+ "mobileStorage",
1033
+ "mobileDeepLinking"
1034
+ ]
1035
+ },
1036
+ {
1037
+ id: "mobile-delivery",
1038
+ label: "Mobile Delivery",
1039
+ promptKeys: [
1040
+ "mobilePush",
1041
+ "mobileOTA",
1042
+ "mobileTesting"
1043
+ ]
1044
+ },
1045
+ {
1046
+ id: "commerce",
1047
+ label: "Payments",
1048
+ promptKeys: ["payments"]
1049
+ },
1050
+ {
1051
+ id: "extras",
1052
+ label: "Data & Discovery",
1053
+ promptKeys: [
1054
+ "caching",
1055
+ "search",
1056
+ "observability"
1057
+ ]
1058
+ }
1059
+ ]
1060
+ },
1061
+ rust: {
1062
+ core: [
1063
+ "rustWebFramework",
1064
+ "rustFrontend",
1065
+ "database",
1066
+ "dbSetup",
1067
+ "rustOrm",
1068
+ "rustApi",
1069
+ "rustAuth"
1070
+ ],
1071
+ sections: [
1072
+ sharedServiceSection,
1073
+ {
1074
+ id: "cli-libraries",
1075
+ label: "CLI & Libraries",
1076
+ promptKeys: [
1077
+ "rustCli",
1078
+ "rustLibraries",
1079
+ "rustTemplating"
1080
+ ]
1081
+ },
1082
+ {
1083
+ id: "quality",
1084
+ label: "Logging & Error Handling",
1085
+ promptKeys: ["rustLogging", "rustErrorHandling"]
1086
+ },
1087
+ {
1088
+ id: "backend-extras",
1089
+ label: "Caching, Realtime & Queues",
1090
+ promptKeys: [
1091
+ "rustCaching",
1092
+ "rustRealtime",
1093
+ "rustMessageQueue"
1094
+ ]
1095
+ },
1096
+ {
1097
+ id: "observability",
1098
+ label: "Observability",
1099
+ promptKeys: ["rustObservability"]
1100
+ }
1101
+ ]
1102
+ },
1103
+ python: {
1104
+ core: [
1105
+ "pythonWebFramework",
1106
+ "database",
1107
+ "dbSetup",
1108
+ "pythonOrm",
1109
+ "pythonAuth",
1110
+ "pythonApi"
1111
+ ],
1112
+ sections: [
1113
+ sharedServiceSection,
1114
+ {
1115
+ id: "type-safety-ai",
1116
+ label: "Validation & AI",
1117
+ promptKeys: ["pythonValidation", "pythonAi"]
1118
+ },
1119
+ {
1120
+ id: "api-jobs",
1121
+ label: "GraphQL, Tasks & CLI",
1122
+ promptKeys: [
1123
+ "pythonGraphql",
1124
+ "pythonTaskQueue",
1125
+ "pythonCli"
1126
+ ]
1127
+ },
1128
+ {
1129
+ id: "data-realtime",
1130
+ label: "Caching & Realtime",
1131
+ promptKeys: ["pythonCaching", "pythonRealtime"]
1132
+ },
1133
+ {
1134
+ id: "quality",
1135
+ label: "Quality, Testing & Observability",
1136
+ promptKeys: [
1137
+ "pythonQuality",
1138
+ "pythonTesting",
1139
+ "pythonObservability"
1140
+ ]
1141
+ }
1142
+ ]
1143
+ },
1144
+ go: {
1145
+ core: [
1146
+ "goWebFramework",
1147
+ "database",
1148
+ "dbSetup",
1149
+ "goOrm",
1150
+ "goApi",
1151
+ "goAuth"
1152
+ ],
1153
+ sections: [
1154
+ sharedServiceSection,
1155
+ {
1156
+ id: "cli-config",
1157
+ label: "CLI, Config & Logging",
1158
+ promptKeys: [
1159
+ "goCli",
1160
+ "goConfig",
1161
+ "goLogging"
1162
+ ]
1163
+ },
1164
+ {
1165
+ id: "backend-extras",
1166
+ label: "Realtime, Queues & Caching",
1167
+ promptKeys: [
1168
+ "goRealtime",
1169
+ "goMessageQueue",
1170
+ "goCaching"
1171
+ ]
1172
+ },
1173
+ {
1174
+ id: "quality",
1175
+ label: "Testing & Observability",
1176
+ promptKeys: ["goTesting", "goObservability"]
1177
+ }
1178
+ ]
1179
+ },
1180
+ java: {
1181
+ core: [
1182
+ "javaWebFramework",
1183
+ "javaLanguage",
1184
+ "javaBuildTool",
1185
+ "database",
1186
+ "dbSetup",
1187
+ "javaOrm",
1188
+ "javaAuth",
1189
+ "javaApi"
1190
+ ],
1191
+ sections: [
1192
+ sharedServiceSection,
1193
+ {
1194
+ id: "libraries",
1195
+ label: "Libraries",
1196
+ promptKeys: ["javaLibraries"]
1197
+ },
1198
+ {
1199
+ id: "quality",
1200
+ label: "Logging & Testing",
1201
+ promptKeys: ["javaLogging", "javaTestingLibraries"]
1202
+ }
1203
+ ]
1204
+ },
1205
+ dotnet: {
1206
+ core: [
1207
+ "dotnetWebFramework",
1208
+ "database",
1209
+ "dbSetup",
1210
+ "dotnetOrm",
1211
+ "dotnetAuth",
1212
+ "dotnetApi"
1213
+ ],
1214
+ sections: [
1215
+ sharedServiceSection,
1216
+ {
1217
+ id: "quality",
1218
+ label: "Testing & Observability",
1219
+ promptKeys: ["dotnetTesting", "dotnetObservability"]
1220
+ },
1221
+ {
1222
+ id: "backend-extras",
1223
+ label: "Jobs, Realtime & Caching",
1224
+ promptKeys: [
1225
+ "dotnetJobQueue",
1226
+ "dotnetRealtime",
1227
+ "dotnetCaching"
1228
+ ]
1229
+ },
1230
+ {
1231
+ id: "validation-deploy",
1232
+ label: "Validation & Deployment",
1233
+ promptKeys: ["dotnetValidation", "dotnetDeploy"]
1234
+ }
1235
+ ]
1236
+ },
1237
+ elixir: {
1238
+ core: [
1239
+ "elixirWebFramework",
1240
+ "database",
1241
+ "dbSetup",
1242
+ "elixirOrm",
1243
+ "elixirAuth",
1244
+ "elixirApi"
1245
+ ],
1246
+ sections: [
1247
+ {
1248
+ id: "backend-extras",
1249
+ label: "Realtime & Jobs",
1250
+ promptKeys: ["elixirRealtime", "elixirJobs"]
1251
+ },
1252
+ {
1253
+ id: "type-safety-http",
1254
+ label: "Validation, HTTP & JSON",
1255
+ promptKeys: [
1256
+ "elixirValidation",
1257
+ "elixirHttp",
1258
+ "elixirJson"
1259
+ ]
1260
+ },
1261
+ {
1262
+ id: "data-email",
1263
+ label: "Email & Caching",
1264
+ promptKeys: ["elixirEmail", "elixirCaching"]
1265
+ },
1266
+ {
1267
+ id: "quality",
1268
+ label: "Testing, Quality & Observability",
1269
+ promptKeys: [
1270
+ "elixirTesting",
1271
+ "elixirQuality",
1272
+ "elixirObservability"
1273
+ ]
1274
+ },
1275
+ {
1276
+ id: "deploy-libraries",
1277
+ label: "Deployment & Libraries",
1278
+ promptKeys: ["elixirDeploy", "elixirLibraries"]
1279
+ }
1280
+ ]
1281
+ }
1282
+ };
1283
+ const SCOPED_CONFIG_PROMPT_KEYS = [...new Set(Object.values(CONFIG_SCOPE_REGISTRY).flatMap((registry) => [
1284
+ ...registry.core,
1285
+ ...registry.sections.flatMap((section) => section.promptKeys),
1286
+ ...CONFIG_SCOPE_ALWAYS_KEYS
1287
+ ]))].sort();
1288
+ function getConfigScopePromptKeys(ecosystem, scope, selectedSectionIds = []) {
1289
+ const registry = CONFIG_SCOPE_REGISTRY[ecosystem];
1290
+ const keys = new Set([...registry.core, ...CONFIG_SCOPE_ALWAYS_KEYS]);
1291
+ if (scope === "full") for (const section of registry.sections) for (const key of section.promptKeys) keys.add(key);
1292
+ if (scope === "custom") {
1293
+ const selected = new Set(selectedSectionIds);
1294
+ for (const section of registry.sections) {
1295
+ if (!selected.has(section.id)) continue;
1296
+ for (const key of section.promptKeys) keys.add(key);
1297
+ }
1298
+ }
1299
+ return keys;
1300
+ }
1301
+ function shouldAskConfigPromptKey(ecosystem, key, scope, selectedSectionIds) {
1302
+ if (!ecosystem || !scope || scope === "full") return true;
1303
+ const registry = CONFIG_SCOPE_REGISTRY[ecosystem];
1304
+ if (!new Set([
1305
+ ...registry.core,
1306
+ ...registry.sections.flatMap((section) => section.promptKeys),
1307
+ ...CONFIG_SCOPE_ALWAYS_KEYS
1308
+ ]).has(key)) return true;
1309
+ return getConfigScopePromptKeys(ecosystem, scope, selectedSectionIds).has(key);
1310
+ }
1311
+ function getDefaultPromptValue(key) {
1312
+ if (key === "astroIntegration") return void 0;
1313
+ const defaults = getDefaultConfig();
1314
+ if (key === "shadcnOptions") return {
1315
+ shadcnBase: defaults.shadcnBase,
1316
+ shadcnStyle: defaults.shadcnStyle,
1317
+ shadcnIconLibrary: defaults.shadcnIconLibrary,
1318
+ shadcnColorTheme: defaults.shadcnColorTheme,
1319
+ shadcnBaseColor: defaults.shadcnBaseColor,
1320
+ shadcnFont: defaults.shadcnFont,
1321
+ shadcnRadius: defaults.shadcnRadius
1322
+ };
1323
+ return defaults[key];
1324
+ }
1325
+ async function getConfigScopeChoice() {
1326
+ const response = await navigableSelect({
1327
+ message: "How much do you want to configure?",
1328
+ options: [
1329
+ {
1330
+ value: "core",
1331
+ label: "Core",
1332
+ hint: "essentials only — framework, database, auth, API; sensible defaults for everything else"
1333
+ },
1334
+ {
1335
+ value: "full",
1336
+ label: "Full",
1337
+ hint: "walk through every option"
1338
+ },
1339
+ {
1340
+ value: "custom",
1341
+ label: "Custom",
1342
+ hint: "pick which sections to configure"
1343
+ }
1344
+ ],
1345
+ initialValue: "core"
1346
+ });
1347
+ if (isCancel$1(response)) return exitCancelled("Operation cancelled");
1348
+ return response;
1349
+ }
1350
+ async function getConfigSectionsChoice(ecosystem, initialValues = [], availableSectionIds) {
1351
+ const sections = CONFIG_SCOPE_REGISTRY[ecosystem].sections.filter((section) => !availableSectionIds || availableSectionIds.includes(section.id));
1352
+ const response = await navigableMultiselect({
1353
+ message: `Which sections do you want to configure? ${pc.dim("(essentials are always included)")}`,
1354
+ options: sections.map((section) => ({
1355
+ value: section.id,
1356
+ label: section.label
1357
+ })),
1358
+ initialValues,
1359
+ required: false
1360
+ });
1361
+ if (isCancel$1(response)) return exitCancelled("Operation cancelled");
1362
+ if (isGoBack(response)) return response;
1363
+ return response;
1364
+ }
1365
+
1023
1366
  //#endregion
1024
1367
  //#region src/prompts/css-framework.ts
1025
1368
  const CSS_FRAMEWORK_OPTIONS = {
@@ -1565,6 +1908,16 @@ const DEPLOY_OPTIONS$1 = [
1565
1908
  hint: "No .NET deploy target"
1566
1909
  }
1567
1910
  ];
1911
+ const resolveDotnetWebFrameworkPrompt = (value) => createStaticSinglePromptResolution(WEB_FRAMEWORK_OPTIONS$1, "aspnet-minimal", value);
1912
+ const resolveDotnetOrmPrompt = (value) => createStaticSinglePromptResolution(ORM_OPTIONS$1, "ef-core", value);
1913
+ const resolveDotnetAuthPrompt = (value) => createStaticSinglePromptResolution(AUTH_OPTIONS$1, "aspnet-identity", value);
1914
+ const resolveDotnetApiPrompt = (value) => createStaticSinglePromptResolution(API_OPTIONS$1, "minimal-api", value);
1915
+ const resolveDotnetTestingPrompt = (value) => createStaticMultiPromptResolution(TESTING_OPTIONS$1, ["xunit"], value);
1916
+ const resolveDotnetJobQueuePrompt = (value) => createStaticSinglePromptResolution(JOB_QUEUE_OPTIONS, "none", value);
1917
+ const resolveDotnetRealtimePrompt = (value) => createStaticSinglePromptResolution(REALTIME_OPTIONS$1, "signalr", value);
1918
+ const resolveDotnetObservabilityPrompt = (value) => createStaticMultiPromptResolution(OBSERVABILITY_OPTIONS$1, ["serilog"], value);
1919
+ const resolveDotnetCachingPrompt = (value) => createStaticSinglePromptResolution(CACHING_OPTIONS$1, "none", value);
1920
+ const resolveDotnetDeployPrompt = (value) => createStaticSinglePromptResolution(DEPLOY_OPTIONS$1, "docker", value);
1568
1921
  const getDotnetWebFrameworkChoice = (value) => makeChoice$1("Select .NET web framework", WEB_FRAMEWORK_OPTIONS$1, "aspnet-minimal", value);
1569
1922
  const getDotnetOrmChoice = (value) => makeChoice$1("Select .NET data access", ORM_OPTIONS$1, "ef-core", value);
1570
1923
  const getDotnetAuthChoice = (value) => makeChoice$1("Select .NET auth", AUTH_OPTIONS$1, "aspnet-identity", value);
@@ -1907,6 +2260,21 @@ const DEPLOY_OPTIONS = [
1907
2260
  hint: "No deploy files"
1908
2261
  }
1909
2262
  ];
2263
+ const resolveElixirWebFrameworkPrompt = (value) => createStaticSinglePromptResolution(WEB_FRAMEWORK_OPTIONS, "phoenix", value);
2264
+ const resolveElixirOrmPrompt = (value) => createStaticSinglePromptResolution(ORM_OPTIONS, "ecto-sql", value);
2265
+ const resolveElixirAuthPrompt = (value) => createStaticSinglePromptResolution(AUTH_OPTIONS, "none", value);
2266
+ const resolveElixirApiPrompt = (value) => createStaticSinglePromptResolution(API_OPTIONS, "rest", value);
2267
+ const resolveElixirRealtimePrompt = (value) => createStaticSinglePromptResolution(REALTIME_OPTIONS, "channels", value);
2268
+ const resolveElixirJobsPrompt = (value) => createStaticSinglePromptResolution(JOB_OPTIONS, "none", value);
2269
+ const resolveElixirValidationPrompt = (value) => createStaticSinglePromptResolution(VALIDATION_OPTIONS, "ecto-changesets", value);
2270
+ const resolveElixirHttpPrompt = (value) => createStaticSinglePromptResolution(HTTP_OPTIONS, "req", value);
2271
+ const resolveElixirJsonPrompt = (value) => createStaticSinglePromptResolution(JSON_OPTIONS, "jason", value);
2272
+ const resolveElixirEmailPrompt = (value) => createStaticSinglePromptResolution(EMAIL_OPTIONS, "none", value);
2273
+ const resolveElixirCachingPrompt = (value) => createStaticSinglePromptResolution(CACHING_OPTIONS, "none", value);
2274
+ const resolveElixirObservabilityPrompt = (value) => createStaticSinglePromptResolution(OBSERVABILITY_OPTIONS, "telemetry", value);
2275
+ const resolveElixirTestingPrompt = (value) => createStaticSinglePromptResolution(TESTING_OPTIONS, "ex_unit", value);
2276
+ const resolveElixirQualityPrompt = (value) => createStaticSinglePromptResolution(QUALITY_OPTIONS, "credo", value);
2277
+ const resolveElixirDeployPrompt = (value) => createStaticSinglePromptResolution(DEPLOY_OPTIONS, "none", value);
1910
2278
  const getElixirWebFrameworkChoice = (value) => makeChoice("Select Elixir web framework", WEB_FRAMEWORK_OPTIONS, "phoenix", value);
1911
2279
  const getElixirOrmChoice = (value) => makeChoice("Select Elixir database layer", ORM_OPTIONS, "ecto-sql", value);
1912
2280
  const getElixirAuthChoice = (value) => makeChoice("Select Elixir auth", AUTH_OPTIONS, "none", value);
@@ -3330,11 +3698,11 @@ async function getJavaLanguageChoice(javaLanguage) {
3330
3698
  if (isCancel$1(response)) return exitCancelled("Operation cancelled");
3331
3699
  return response;
3332
3700
  }
3333
- function resolveJavaBuildToolPrompt(javaBuildTool) {
3334
- return createStaticSinglePromptResolution(JAVA_BUILD_TOOL_PROMPT_OPTIONS, "maven", javaBuildTool);
3701
+ function resolveJavaBuildToolPrompt(javaBuildTool, javaLanguage) {
3702
+ return createStaticSinglePromptResolution(javaLanguage === "kotlin" ? JAVA_BUILD_TOOL_PROMPT_OPTIONS.filter((option) => option.value !== "none") : JAVA_BUILD_TOOL_PROMPT_OPTIONS, "maven", javaBuildTool);
3335
3703
  }
3336
- async function getJavaBuildToolChoice(javaBuildTool) {
3337
- const resolution = resolveJavaBuildToolPrompt(javaBuildTool);
3704
+ async function getJavaBuildToolChoice(javaBuildTool, javaLanguage) {
3705
+ const resolution = resolveJavaBuildToolPrompt(javaBuildTool, javaLanguage);
3338
3706
  if (!resolution.shouldPrompt) return resolution.autoValue ?? "none";
3339
3707
  const response = await navigableSelect({
3340
3708
  message: "Select Java build tool",
@@ -3344,11 +3712,11 @@ async function getJavaBuildToolChoice(javaBuildTool) {
3344
3712
  if (isCancel$1(response)) return exitCancelled("Operation cancelled");
3345
3713
  return response;
3346
3714
  }
3347
- function resolveJavaOrmPrompt(javaOrm) {
3348
- return createStaticSinglePromptResolution(JAVA_ORM_PROMPT_OPTIONS, "none", javaOrm);
3715
+ function resolveJavaOrmPrompt(javaOrm, javaLanguage) {
3716
+ return createStaticSinglePromptResolution(javaLanguage === "kotlin" ? JAVA_ORM_PROMPT_OPTIONS.filter((option) => option.value !== "jooq" && option.value !== "mybatis") : JAVA_ORM_PROMPT_OPTIONS, "none", javaOrm);
3349
3717
  }
3350
- async function getJavaOrmChoice(javaOrm) {
3351
- const resolution = resolveJavaOrmPrompt(javaOrm);
3718
+ async function getJavaOrmChoice(javaOrm, javaLanguage) {
3719
+ const resolution = resolveJavaOrmPrompt(javaOrm, javaLanguage);
3352
3720
  if (!resolution.shouldPrompt) return resolution.autoValue ?? "none";
3353
3721
  const response = await navigableSelect({
3354
3722
  message: "Select Java ORM/database layer",
@@ -3372,11 +3740,11 @@ async function getJavaAuthChoice(javaAuth) {
3372
3740
  if (isCancel$1(response)) return exitCancelled("Operation cancelled");
3373
3741
  return response;
3374
3742
  }
3375
- function resolveJavaLibrariesPrompt(javaLibraries) {
3376
- return createStaticMultiPromptResolution(JAVA_LIBRARY_PROMPT_OPTIONS, [], javaLibraries);
3743
+ function resolveJavaLibrariesPrompt(javaLibraries, javaLanguage) {
3744
+ return createStaticMultiPromptResolution(javaLanguage === "kotlin" ? JAVA_LIBRARY_PROMPT_OPTIONS.filter((option) => !types_exports.KOTLIN_DROPPED_JAVA_LIBRARIES.has(option.value)) : JAVA_LIBRARY_PROMPT_OPTIONS, [], javaLibraries);
3377
3745
  }
3378
- async function getJavaLibrariesChoice(javaLibraries) {
3379
- const resolution = resolveJavaLibrariesPrompt(javaLibraries);
3746
+ async function getJavaLibrariesChoice(javaLibraries, javaLanguage) {
3747
+ const resolution = resolveJavaLibrariesPrompt(javaLibraries, javaLanguage);
3380
3748
  if (!resolution.shouldPrompt) return resolution.autoValue ?? [];
3381
3749
  const response = await navigableMultiselect({
3382
3750
  message: "Select Java application libraries",
@@ -3388,11 +3756,11 @@ async function getJavaLibrariesChoice(javaLibraries) {
3388
3756
  if (response.includes("none")) return [];
3389
3757
  return response;
3390
3758
  }
3391
- function resolveJavaTestingLibrariesPrompt(javaTestingLibraries) {
3392
- return createStaticMultiPromptResolution(JAVA_TESTING_LIBRARY_PROMPT_OPTIONS, ["junit5"], javaTestingLibraries);
3759
+ function resolveJavaTestingLibrariesPrompt(javaTestingLibraries, javaLanguage) {
3760
+ return createStaticMultiPromptResolution(javaLanguage === "kotlin" ? JAVA_TESTING_LIBRARY_PROMPT_OPTIONS.filter((option) => !types_exports.KOTLIN_UNSUPPORTED_JAVA_TESTING_LIBRARIES.has(option.value)) : JAVA_TESTING_LIBRARY_PROMPT_OPTIONS, ["junit5"], javaTestingLibraries);
3393
3761
  }
3394
- async function getJavaTestingLibrariesChoice(javaTestingLibraries) {
3395
- const resolution = resolveJavaTestingLibrariesPrompt(javaTestingLibraries);
3762
+ async function getJavaTestingLibrariesChoice(javaTestingLibraries, javaLanguage) {
3763
+ const resolution = resolveJavaTestingLibrariesPrompt(javaTestingLibraries, javaLanguage);
3396
3764
  if (!resolution.shouldPrompt) return resolution.autoValue ?? [];
3397
3765
  const response = await navigableMultiselect({
3398
3766
  message: "Select Java testing libraries",
@@ -3443,11 +3811,11 @@ const JAVA_LOGGING_PROMPT_OPTIONS = [
3443
3811
  hint: "Spring Boot logging defaults"
3444
3812
  }
3445
3813
  ];
3446
- function resolveJavaApiPrompt(javaApi) {
3447
- return createStaticSinglePromptResolution(JAVA_API_PROMPT_OPTIONS, "none", javaApi);
3814
+ function resolveJavaApiPrompt(javaApi, javaLanguage) {
3815
+ return createStaticSinglePromptResolution(javaLanguage === "kotlin" ? JAVA_API_PROMPT_OPTIONS.filter((option) => option.value !== "grpc" && option.value !== "openapi-generator") : JAVA_API_PROMPT_OPTIONS, "none", javaApi);
3448
3816
  }
3449
- async function getJavaApiChoice(javaApi) {
3450
- const resolution = resolveJavaApiPrompt(javaApi);
3817
+ async function getJavaApiChoice(javaApi, javaLanguage) {
3818
+ const resolution = resolveJavaApiPrompt(javaApi, javaLanguage);
3451
3819
  if (!resolution.shouldPrompt) return resolution.autoValue ?? "none";
3452
3820
  const response = await navigableSelect({
3453
3821
  message: "Select Java API layer",
@@ -3709,6 +4077,27 @@ async function promptMobileOption(options, defaultValue, selected, message) {
3709
4077
  if (isCancel$1(response)) return exitCancelled("Operation cancelled");
3710
4078
  return response;
3711
4079
  }
4080
+ function resolveMobileNavigationPrompt(mobileNavigation) {
4081
+ return createStaticSinglePromptResolution(MOBILE_NAVIGATION_OPTIONS, "expo-router", mobileNavigation);
4082
+ }
4083
+ function resolveMobileUIPrompt(mobileUI) {
4084
+ return createStaticSinglePromptResolution(MOBILE_UI_OPTIONS, "none", mobileUI);
4085
+ }
4086
+ function resolveMobileStoragePrompt(mobileStorage) {
4087
+ return createStaticSinglePromptResolution(MOBILE_STORAGE_OPTIONS, "none", mobileStorage);
4088
+ }
4089
+ function resolveMobileTestingPrompt(mobileTesting) {
4090
+ return createStaticSinglePromptResolution(MOBILE_TESTING_OPTIONS, "none", mobileTesting);
4091
+ }
4092
+ function resolveMobilePushPrompt(mobilePush) {
4093
+ return createStaticSinglePromptResolution(MOBILE_PUSH_OPTIONS, "none", mobilePush);
4094
+ }
4095
+ function resolveMobileOTAPrompt(mobileOTA) {
4096
+ return createStaticSinglePromptResolution(MOBILE_OTA_OPTIONS, "none", mobileOTA);
4097
+ }
4098
+ function resolveMobileDeepLinkingPrompt(mobileDeepLinking) {
4099
+ return createStaticSinglePromptResolution(MOBILE_DEEP_LINKING_OPTIONS, "expo-linking", mobileDeepLinking);
4100
+ }
3712
4101
  function getMobileNavigationChoice(mobileNavigation) {
3713
4102
  return promptMobileOption(MOBILE_NAVIGATION_OPTIONS, "expo-router", mobileNavigation, "Select mobile navigation");
3714
4103
  }
@@ -5445,6 +5834,13 @@ function promptValue(value) {
5445
5834
  if (isCancel$1(value) || isGoBack(value)) return exitCancelled("Operation cancelled");
5446
5835
  return value;
5447
5836
  }
5837
+ function hasMultiStackPromptFlags(flags) {
5838
+ return Object.keys(flags).some((key) => key !== "projectName" && key !== "projectDir" && key !== "relativePath");
5839
+ }
5840
+ async function scopedPromptValue(ecosystem, key, scope, selectedSectionIds, prompt) {
5841
+ if (!shouldAskConfigPromptKey(ecosystem, key, scope, selectedSectionIds)) return getDefaultPromptValue(key);
5842
+ return promptValue(await prompt());
5843
+ }
5448
5844
  async function selectDatabaseConfig(flags) {
5449
5845
  const database = promptValue(await getDatabaseChoice(flags.database, "hono", "bun"));
5450
5846
  return {
@@ -5454,6 +5850,12 @@ async function selectDatabaseConfig(flags) {
5454
5850
  }
5455
5851
  async function gatherMultiEcosystemConfig(flags, projectName, projectDir, relativePath) {
5456
5852
  const baseConfig = getDefaultConfig();
5853
+ const configScope = !hasMultiStackPromptFlags(flags) ? promptValue(await getConfigScopeChoice()) : "full";
5854
+ const typeScriptSections = configScope === "custom" ? promptValue(await getConfigSectionsChoice("typescript", [], [
5855
+ "ui-styling",
5856
+ "deploy",
5857
+ "addons-examples"
5858
+ ])) : [];
5457
5859
  const frontend = promptValue(await navigableSelect({
5458
5860
  message: "Select TypeScript web frontend",
5459
5861
  options: WEB_FRONTEND_PROMPT_OPTIONS,
@@ -5461,8 +5863,8 @@ async function gatherMultiEcosystemConfig(flags, projectName, projectDir, relati
5461
5863
  }));
5462
5864
  const frontendList = [frontend];
5463
5865
  const astroIntegration = frontend === "astro" ? promptValue(await getAstroIntegrationChoice(flags.astroIntegration)) : void 0;
5464
- const uiLibrary = hasWebStyling$1(frontendList) ? promptValue(await getUILibraryChoice(flags.uiLibrary, frontendList, astroIntegration)) : "none";
5465
- const shadcnOptions = uiLibrary === "shadcn-ui" ? promptValue(await getShadcnOptions({
5866
+ const uiLibrary = hasWebStyling$1(frontendList) ? await scopedPromptValue("typescript", "uiLibrary", configScope, typeScriptSections, () => getUILibraryChoice(flags.uiLibrary, frontendList, astroIntegration)) : "none";
5867
+ const shadcnOptions = uiLibrary === "shadcn-ui" ? shouldAskConfigPromptKey("typescript", "shadcnOptions", configScope, typeScriptSections) ? promptValue(await getShadcnOptions({
5466
5868
  shadcnBase: flags.shadcnBase,
5467
5869
  shadcnStyle: flags.shadcnStyle,
5468
5870
  shadcnIconLibrary: flags.shadcnIconLibrary,
@@ -5470,9 +5872,10 @@ async function gatherMultiEcosystemConfig(flags, projectName, projectDir, relati
5470
5872
  shadcnBaseColor: flags.shadcnBaseColor,
5471
5873
  shadcnFont: flags.shadcnFont,
5472
5874
  shadcnRadius: flags.shadcnRadius
5473
- })) : void 0;
5474
- const cssFramework = hasWebStyling$1(frontendList) ? promptValue(await getCSSFrameworkChoice(flags.cssFramework, uiLibrary)) : "none";
5875
+ })) : getDefaultPromptValue("shadcnOptions") : void 0;
5876
+ const cssFramework = hasWebStyling$1(frontendList) ? await scopedPromptValue("typescript", "cssFramework", configScope, typeScriptSections, () => getCSSFrameworkChoice(flags.cssFramework, uiLibrary)) : "none";
5475
5877
  const backendEcosystem = await selectBackendEcosystem();
5878
+ const backendSections = configScope === "custom" ? promptValue(await getConfigSectionsChoice(backendEcosystem)) : [];
5476
5879
  const stackPartSpecs = [`frontend:typescript:${frontend}`];
5477
5880
  const backendChoices = {};
5478
5881
  let database = "none";
@@ -5487,14 +5890,14 @@ async function gatherMultiEcosystemConfig(flags, projectName, projectDir, relati
5487
5890
  const goOrm = database === "none" || goWebFramework === "none" ? "none" : promptValue(await getGoOrmChoice(flags.goOrm));
5488
5891
  const goApi = goWebFramework === "none" ? "none" : promptValue(await getGoApiChoice(flags.goApi));
5489
5892
  const goAuth = goWebFramework === "none" ? "none" : promptValue(await getGoAuthChoice(flags.goAuth));
5490
- const goCli = goWebFramework === "none" ? "none" : promptValue(await getGoCliChoice(flags.goCli));
5491
- const goLogging = goWebFramework === "none" ? "none" : promptValue(await getGoLoggingChoice(flags.goLogging));
5492
- const goTesting = goWebFramework === "none" ? [] : promptValue(await getGoTestingChoice(flags.goTesting));
5493
- const goRealtime = goWebFramework === "none" ? "none" : promptValue(await getGoRealtimeChoice(flags.goRealtime));
5494
- const goMessageQueue = goWebFramework === "none" ? "none" : promptValue(await getGoMessageQueueChoice(flags.goMessageQueue));
5495
- const goCaching = goWebFramework === "none" ? "none" : promptValue(await getGoCachingChoice(flags.goCaching));
5496
- const goConfig = goWebFramework === "none" ? "none" : promptValue(await getGoConfigChoice(flags.goConfig));
5497
- const goObservability = goWebFramework === "none" ? "none" : promptValue(await getGoObservabilityChoice(flags.goObservability));
5893
+ const goCli = goWebFramework === "none" ? "none" : await scopedPromptValue("go", "goCli", configScope, backendSections, () => getGoCliChoice(flags.goCli));
5894
+ const goLogging = goWebFramework === "none" ? "none" : await scopedPromptValue("go", "goLogging", configScope, backendSections, () => getGoLoggingChoice(flags.goLogging));
5895
+ const goTesting = goWebFramework === "none" ? [] : await scopedPromptValue("go", "goTesting", configScope, backendSections, () => getGoTestingChoice(flags.goTesting));
5896
+ const goRealtime = goWebFramework === "none" ? "none" : await scopedPromptValue("go", "goRealtime", configScope, backendSections, () => getGoRealtimeChoice(flags.goRealtime));
5897
+ const goMessageQueue = goWebFramework === "none" ? "none" : await scopedPromptValue("go", "goMessageQueue", configScope, backendSections, () => getGoMessageQueueChoice(flags.goMessageQueue));
5898
+ const goCaching = goWebFramework === "none" ? "none" : await scopedPromptValue("go", "goCaching", configScope, backendSections, () => getGoCachingChoice(flags.goCaching));
5899
+ const goConfig = goWebFramework === "none" ? "none" : await scopedPromptValue("go", "goConfig", configScope, backendSections, () => getGoConfigChoice(flags.goConfig));
5900
+ const goObservability = goWebFramework === "none" ? "none" : await scopedPromptValue("go", "goObservability", configScope, backendSections, () => getGoObservabilityChoice(flags.goObservability));
5498
5901
  Object.assign(backendChoices, {
5499
5902
  goWebFramework,
5500
5903
  goOrm,
@@ -5531,15 +5934,15 @@ async function gatherMultiEcosystemConfig(flags, projectName, projectDir, relati
5531
5934
  const rustApi = rustWebFramework === "none" ? "none" : promptValue(await getRustApiChoice(flags.rustApi));
5532
5935
  const rustAuth = rustWebFramework === "none" ? "none" : promptValue(await getRustAuthChoice(flags.rustAuth));
5533
5936
  const rustFrontend = "none";
5534
- const rustCli = rustWebFramework === "none" ? "none" : promptValue(await getRustCliChoice(flags.rustCli));
5535
- const rustLibraries = rustWebFramework === "none" ? [] : promptValue(await getRustLibrariesChoice(flags.rustLibraries));
5536
- const rustLogging = rustWebFramework === "none" ? "none" : promptValue(await getRustLoggingChoice(flags.rustLogging));
5537
- const rustErrorHandling = promptValue(await getRustErrorHandlingChoice(flags.rustErrorHandling));
5538
- const rustCaching = rustWebFramework === "none" ? "none" : promptValue(await getRustCachingChoice(flags.rustCaching));
5539
- const rustRealtime = rustWebFramework === "none" ? "none" : promptValue(await getRustRealtimeChoice(flags.rustRealtime));
5540
- const rustMessageQueue = rustWebFramework === "none" ? "none" : promptValue(await getRustMessageQueueChoice(flags.rustMessageQueue));
5541
- const rustObservability = rustWebFramework === "none" ? "none" : promptValue(await getRustObservabilityChoice(flags.rustObservability));
5542
- const rustTemplating = rustWebFramework === "none" ? "none" : promptValue(await getRustTemplatingChoice(flags.rustTemplating));
5937
+ const rustCli = rustWebFramework === "none" ? "none" : await scopedPromptValue("rust", "rustCli", configScope, backendSections, () => getRustCliChoice(flags.rustCli));
5938
+ const rustLibraries = rustWebFramework === "none" ? [] : await scopedPromptValue("rust", "rustLibraries", configScope, backendSections, () => getRustLibrariesChoice(flags.rustLibraries));
5939
+ const rustLogging = rustWebFramework === "none" ? "none" : await scopedPromptValue("rust", "rustLogging", configScope, backendSections, () => getRustLoggingChoice(flags.rustLogging));
5940
+ const rustErrorHandling = await scopedPromptValue("rust", "rustErrorHandling", configScope, backendSections, () => getRustErrorHandlingChoice(flags.rustErrorHandling));
5941
+ const rustCaching = rustWebFramework === "none" ? "none" : await scopedPromptValue("rust", "rustCaching", configScope, backendSections, () => getRustCachingChoice(flags.rustCaching));
5942
+ const rustRealtime = rustWebFramework === "none" ? "none" : await scopedPromptValue("rust", "rustRealtime", configScope, backendSections, () => getRustRealtimeChoice(flags.rustRealtime));
5943
+ const rustMessageQueue = rustWebFramework === "none" ? "none" : await scopedPromptValue("rust", "rustMessageQueue", configScope, backendSections, () => getRustMessageQueueChoice(flags.rustMessageQueue));
5944
+ const rustObservability = rustWebFramework === "none" ? "none" : await scopedPromptValue("rust", "rustObservability", configScope, backendSections, () => getRustObservabilityChoice(flags.rustObservability));
5945
+ const rustTemplating = rustWebFramework === "none" ? "none" : await scopedPromptValue("rust", "rustTemplating", configScope, backendSections, () => getRustTemplatingChoice(flags.rustTemplating));
5543
5946
  Object.assign(backendChoices, {
5544
5947
  rustWebFramework,
5545
5948
  rustOrm,
@@ -5573,17 +5976,17 @@ async function gatherMultiEcosystemConfig(flags, projectName, projectDir, relati
5573
5976
  dbSetup = databaseConfig.dbSetup;
5574
5977
  }
5575
5978
  const pythonOrm = database === "none" || pythonWebFramework === "none" ? "none" : promptValue(await getPythonOrmChoice(flags.pythonOrm));
5576
- const pythonValidation = pythonWebFramework === "none" ? "none" : promptValue(await getPythonValidationChoice(flags.pythonValidation));
5577
- const pythonAi = pythonWebFramework === "none" ? [] : promptValue(await getPythonAiChoice(flags.pythonAi));
5979
+ const pythonValidation = pythonWebFramework === "none" ? "none" : await scopedPromptValue("python", "pythonValidation", configScope, backendSections, () => getPythonValidationChoice(flags.pythonValidation));
5980
+ const pythonAi = pythonWebFramework === "none" ? [] : await scopedPromptValue("python", "pythonAi", configScope, backendSections, () => getPythonAiChoice(flags.pythonAi));
5578
5981
  const pythonAuth = pythonWebFramework === "none" ? "none" : promptValue(await getPythonAuthChoice(flags.pythonAuth));
5579
- const pythonTaskQueue = pythonWebFramework === "none" ? "none" : promptValue(await getPythonTaskQueueChoice(flags.pythonTaskQueue));
5580
- const pythonGraphql = pythonWebFramework === "none" ? "none" : promptValue(await getPythonGraphqlChoice(flags.pythonGraphql));
5581
- const pythonQuality = pythonWebFramework === "none" ? "none" : promptValue(await getPythonQualityChoice(flags.pythonQuality));
5582
- const pythonTesting = pythonWebFramework === "none" ? [] : promptValue(await getPythonTestingChoice(flags.pythonTesting));
5583
- const pythonCaching = pythonWebFramework === "none" ? "none" : promptValue(await getPythonCachingChoice(flags.pythonCaching));
5584
- const pythonRealtime = pythonWebFramework === "none" ? "none" : promptValue(await getPythonRealtimeChoice(flags.pythonRealtime));
5585
- const pythonObservability = pythonWebFramework === "none" ? "none" : promptValue(await getPythonObservabilityChoice(flags.pythonObservability));
5586
- const pythonCli = pythonWebFramework === "none" ? [] : promptValue(await getPythonCliChoice(flags.pythonCli));
5982
+ const pythonTaskQueue = pythonWebFramework === "none" ? "none" : await scopedPromptValue("python", "pythonTaskQueue", configScope, backendSections, () => getPythonTaskQueueChoice(flags.pythonTaskQueue));
5983
+ const pythonGraphql = pythonWebFramework === "none" ? "none" : await scopedPromptValue("python", "pythonGraphql", configScope, backendSections, () => getPythonGraphqlChoice(flags.pythonGraphql));
5984
+ const pythonQuality = pythonWebFramework === "none" ? "none" : await scopedPromptValue("python", "pythonQuality", configScope, backendSections, () => getPythonQualityChoice(flags.pythonQuality));
5985
+ const pythonTesting = pythonWebFramework === "none" ? [] : await scopedPromptValue("python", "pythonTesting", configScope, backendSections, () => getPythonTestingChoice(flags.pythonTesting));
5986
+ const pythonCaching = pythonWebFramework === "none" ? "none" : await scopedPromptValue("python", "pythonCaching", configScope, backendSections, () => getPythonCachingChoice(flags.pythonCaching));
5987
+ const pythonRealtime = pythonWebFramework === "none" ? "none" : await scopedPromptValue("python", "pythonRealtime", configScope, backendSections, () => getPythonRealtimeChoice(flags.pythonRealtime));
5988
+ const pythonObservability = pythonWebFramework === "none" ? "none" : await scopedPromptValue("python", "pythonObservability", configScope, backendSections, () => getPythonObservabilityChoice(flags.pythonObservability));
5989
+ const pythonCli = pythonWebFramework === "none" ? [] : await scopedPromptValue("python", "pythonCli", configScope, backendSections, () => getPythonCliChoice(flags.pythonCli));
5587
5990
  Object.assign(backendChoices, {
5588
5991
  pythonWebFramework,
5589
5992
  pythonOrm,
@@ -5612,19 +6015,21 @@ async function gatherMultiEcosystemConfig(flags, projectName, projectDir, relati
5612
6015
  }
5613
6016
  if (backendEcosystem === "java") {
5614
6017
  const javaWebFramework = promptValue(await getJavaWebFrameworkChoice(flags.javaWebFramework));
5615
- const javaBuildTool = promptValue(await getJavaBuildToolChoice(flags.javaBuildTool));
6018
+ const javaLanguage = javaWebFramework !== "spring-boot" ? "java" : flags.javaLanguage !== void 0 ? promptValue(await getJavaLanguageChoice(flags.javaLanguage)) : flags.javaWebFramework !== void 0 ? "java" : promptValue(await getJavaLanguageChoice(flags.javaLanguage));
6019
+ const javaBuildTool = promptValue(await getJavaBuildToolChoice(flags.javaBuildTool, javaLanguage));
5616
6020
  if (javaWebFramework !== "none" && javaBuildTool !== "none") {
5617
6021
  const databaseConfig = await selectDatabaseConfig(flags);
5618
6022
  database = databaseConfig.database;
5619
6023
  dbSetup = databaseConfig.dbSetup;
5620
6024
  }
5621
- const javaOrm = database === "none" || javaWebFramework !== "spring-boot" || javaBuildTool === "none" ? "none" : promptValue(await getJavaOrmChoice(flags.javaOrm));
6025
+ const javaOrm = database === "none" || javaWebFramework !== "spring-boot" || javaBuildTool === "none" ? "none" : promptValue(await getJavaOrmChoice(flags.javaOrm, javaLanguage));
5622
6026
  const javaAuth = javaWebFramework !== "spring-boot" || javaBuildTool === "none" ? "none" : promptValue(await getJavaAuthChoice(flags.javaAuth));
5623
- const javaLibraries = javaWebFramework !== "spring-boot" || javaBuildTool === "none" ? [] : promptValue(await getJavaLibrariesChoice(flags.javaLibraries));
5624
- const javaTestingLibraries = promptValue(await getJavaTestingLibrariesChoice(flags.javaTestingLibraries));
5625
- const javaApi = javaWebFramework !== "spring-boot" || javaBuildTool === "none" ? "none" : promptValue(await getJavaApiChoice(flags.javaApi));
5626
- const javaLogging = javaWebFramework !== "spring-boot" || javaBuildTool === "none" ? "none" : promptValue(await getJavaLoggingChoice(flags.javaLogging));
6027
+ const javaLibraries = javaWebFramework !== "spring-boot" || javaBuildTool === "none" ? [] : await scopedPromptValue("java", "javaLibraries", configScope, backendSections, () => getJavaLibrariesChoice(flags.javaLibraries, javaLanguage));
6028
+ const javaTestingLibraries = await scopedPromptValue("java", "javaTestingLibraries", configScope, backendSections, () => getJavaTestingLibrariesChoice(flags.javaTestingLibraries, javaLanguage));
6029
+ const javaApi = javaWebFramework !== "spring-boot" || javaBuildTool === "none" ? "none" : promptValue(await getJavaApiChoice(flags.javaApi, javaLanguage));
6030
+ const javaLogging = javaWebFramework !== "spring-boot" || javaBuildTool === "none" ? "none" : await scopedPromptValue("java", "javaLogging", configScope, backendSections, () => getJavaLoggingChoice(flags.javaLogging));
5627
6031
  Object.assign(backendChoices, {
6032
+ javaLanguage,
5628
6033
  javaWebFramework,
5629
6034
  javaBuildTool,
5630
6035
  javaOrm,
@@ -5635,6 +6040,7 @@ async function gatherMultiEcosystemConfig(flags, projectName, projectDir, relati
5635
6040
  javaTestingLibraries
5636
6041
  });
5637
6042
  if (javaWebFramework !== "none") stackPartSpecs.push(`backend:java:${javaWebFramework}`);
6043
+ if (javaWebFramework !== "none") stackPartSpecs.push(`backend.language:java:${javaLanguage}`);
5638
6044
  if (javaOrm !== "none") stackPartSpecs.push(`backend.orm:java:${javaOrm}`);
5639
6045
  if (javaAuth !== "none") stackPartSpecs.push(`backend.auth:java:${javaAuth}`);
5640
6046
  if (javaApi !== "none") stackPartSpecs.push(`backend.api:java:${javaApi}`);
@@ -5650,13 +6056,13 @@ async function gatherMultiEcosystemConfig(flags, projectName, projectDir, relati
5650
6056
  const dotnetOrm = database === "none" || dotnetWebFramework === "none" ? "none" : promptValue(await getDotnetOrmChoice(flags.dotnetOrm));
5651
6057
  const dotnetAuth = dotnetWebFramework === "none" ? "none" : promptValue(await getDotnetAuthChoice(flags.dotnetAuth));
5652
6058
  const dotnetApi = dotnetWebFramework === "none" ? "none" : promptValue(await getDotnetApiChoice(flags.dotnetApi));
5653
- const dotnetTesting = dotnetWebFramework === "none" ? [] : promptValue(await getDotnetTestingChoice(flags.dotnetTesting));
5654
- const dotnetJobQueue = dotnetWebFramework === "none" ? "none" : promptValue(await getDotnetJobQueueChoice(flags.dotnetJobQueue));
5655
- const dotnetRealtime = dotnetWebFramework === "none" ? "none" : promptValue(await getDotnetRealtimeChoice(flags.dotnetRealtime));
5656
- const dotnetObservability = dotnetWebFramework === "none" ? [] : promptValue(await getDotnetObservabilityChoice(flags.dotnetObservability));
5657
- const dotnetValidation = dotnetWebFramework === "none" ? "none" : promptValue(await getDotnetValidationChoice(flags.dotnetValidation));
5658
- const dotnetCaching = dotnetWebFramework === "none" ? "none" : promptValue(await getDotnetCachingChoice(flags.dotnetCaching));
5659
- const dotnetDeploy = dotnetWebFramework === "none" ? "none" : promptValue(await getDotnetDeployChoice(flags.dotnetDeploy));
6059
+ const dotnetTesting = dotnetWebFramework === "none" ? [] : await scopedPromptValue("dotnet", "dotnetTesting", configScope, backendSections, () => getDotnetTestingChoice(flags.dotnetTesting));
6060
+ const dotnetJobQueue = dotnetWebFramework === "none" ? "none" : await scopedPromptValue("dotnet", "dotnetJobQueue", configScope, backendSections, () => getDotnetJobQueueChoice(flags.dotnetJobQueue));
6061
+ const dotnetRealtime = dotnetWebFramework === "none" ? "none" : await scopedPromptValue("dotnet", "dotnetRealtime", configScope, backendSections, () => getDotnetRealtimeChoice(flags.dotnetRealtime));
6062
+ const dotnetObservability = dotnetWebFramework === "none" ? [] : await scopedPromptValue("dotnet", "dotnetObservability", configScope, backendSections, () => getDotnetObservabilityChoice(flags.dotnetObservability));
6063
+ const dotnetValidation = dotnetWebFramework === "none" ? "none" : await scopedPromptValue("dotnet", "dotnetValidation", configScope, backendSections, () => getDotnetValidationChoice(flags.dotnetValidation));
6064
+ const dotnetCaching = dotnetWebFramework === "none" ? "none" : await scopedPromptValue("dotnet", "dotnetCaching", configScope, backendSections, () => getDotnetCachingChoice(flags.dotnetCaching));
6065
+ const dotnetDeploy = dotnetWebFramework === "none" ? "none" : await scopedPromptValue("dotnet", "dotnetDeploy", configScope, backendSections, () => getDotnetDeployChoice(flags.dotnetDeploy));
5660
6066
  Object.assign(backendChoices, {
5661
6067
  dotnetWebFramework,
5662
6068
  dotnetOrm,
@@ -5692,18 +6098,18 @@ async function gatherMultiEcosystemConfig(flags, projectName, projectDir, relati
5692
6098
  const elixirOrm = database === "none" || elixirWebFramework === "none" ? "none" : promptValue(await getElixirOrmChoice(flags.elixirOrm));
5693
6099
  const elixirAuth = elixirWebFramework === "none" ? "none" : promptValue(await getElixirAuthChoice(flags.elixirAuth));
5694
6100
  const elixirApi = elixirWebFramework === "none" ? "none" : promptValue(await getElixirApiChoice(flags.elixirApi));
5695
- const elixirRealtime = elixirWebFramework === "none" ? "none" : promptValue(await getElixirRealtimeChoice(flags.elixirRealtime));
5696
- const elixirJobs = elixirWebFramework === "none" ? "none" : promptValue(await getElixirJobsChoice(flags.elixirJobs));
5697
- const elixirValidation = elixirWebFramework === "none" ? "none" : promptValue(await getElixirValidationChoice(flags.elixirValidation));
5698
- const elixirHttp = elixirWebFramework === "none" ? "none" : promptValue(await getElixirHttpChoice(flags.elixirHttp));
5699
- const elixirJson = elixirWebFramework === "none" ? "none" : promptValue(await getElixirJsonChoice(flags.elixirJson));
5700
- const elixirEmail = elixirWebFramework === "none" ? "none" : promptValue(await getElixirEmailChoice(flags.elixirEmail));
5701
- const elixirCaching = elixirWebFramework === "none" ? "none" : promptValue(await getElixirCachingChoice(flags.elixirCaching));
5702
- const elixirObservability = elixirWebFramework === "none" ? "none" : promptValue(await getElixirObservabilityChoice(flags.elixirObservability));
5703
- const elixirTesting = elixirWebFramework === "none" ? "none" : promptValue(await getElixirTestingChoice(flags.elixirTesting));
5704
- const elixirQuality = elixirWebFramework === "none" ? "none" : promptValue(await getElixirQualityChoice(flags.elixirQuality));
5705
- const elixirDeploy = elixirWebFramework === "none" ? "none" : promptValue(await getElixirDeployChoice(flags.elixirDeploy));
5706
- const elixirLibraries = elixirWebFramework === "none" ? [] : promptValue(await getElixirLibrariesChoice(flags.elixirLibraries));
6101
+ const elixirRealtime = elixirWebFramework === "none" ? "none" : await scopedPromptValue("elixir", "elixirRealtime", configScope, backendSections, () => getElixirRealtimeChoice(flags.elixirRealtime));
6102
+ const elixirJobs = elixirWebFramework === "none" ? "none" : await scopedPromptValue("elixir", "elixirJobs", configScope, backendSections, () => getElixirJobsChoice(flags.elixirJobs));
6103
+ const elixirValidation = elixirWebFramework === "none" ? "none" : await scopedPromptValue("elixir", "elixirValidation", configScope, backendSections, () => getElixirValidationChoice(flags.elixirValidation));
6104
+ const elixirHttp = elixirWebFramework === "none" ? "none" : await scopedPromptValue("elixir", "elixirHttp", configScope, backendSections, () => getElixirHttpChoice(flags.elixirHttp));
6105
+ const elixirJson = elixirWebFramework === "none" ? "none" : await scopedPromptValue("elixir", "elixirJson", configScope, backendSections, () => getElixirJsonChoice(flags.elixirJson));
6106
+ const elixirEmail = elixirWebFramework === "none" ? "none" : await scopedPromptValue("elixir", "elixirEmail", configScope, backendSections, () => getElixirEmailChoice(flags.elixirEmail));
6107
+ const elixirCaching = elixirWebFramework === "none" ? "none" : await scopedPromptValue("elixir", "elixirCaching", configScope, backendSections, () => getElixirCachingChoice(flags.elixirCaching));
6108
+ const elixirObservability = elixirWebFramework === "none" ? "none" : await scopedPromptValue("elixir", "elixirObservability", configScope, backendSections, () => getElixirObservabilityChoice(flags.elixirObservability));
6109
+ const elixirTesting = elixirWebFramework === "none" ? "none" : await scopedPromptValue("elixir", "elixirTesting", configScope, backendSections, () => getElixirTestingChoice(flags.elixirTesting));
6110
+ const elixirQuality = elixirWebFramework === "none" ? "none" : await scopedPromptValue("elixir", "elixirQuality", configScope, backendSections, () => getElixirQualityChoice(flags.elixirQuality));
6111
+ const elixirDeploy = elixirWebFramework === "none" ? "none" : await scopedPromptValue("elixir", "elixirDeploy", configScope, backendSections, () => getElixirDeployChoice(flags.elixirDeploy));
6112
+ const elixirLibraries = elixirWebFramework === "none" ? [] : await scopedPromptValue("elixir", "elixirLibraries", configScope, backendSections, () => getElixirLibrariesChoice(flags.elixirLibraries));
5707
6113
  Object.assign(backendChoices, {
5708
6114
  elixirWebFramework,
5709
6115
  elixirOrm,
@@ -5738,9 +6144,9 @@ async function gatherMultiEcosystemConfig(flags, projectName, projectDir, relati
5738
6144
  if (database !== "none") stackPartSpecs.push(`database:universal:${database}`);
5739
6145
  const stackParts = (0, types_exports.parseStackPartSpecs)(stackPartSpecs, "selected");
5740
6146
  const graphPartial = (0, types_exports.stackPartsToLegacyProjectConfigPartial)(stackParts);
5741
- const addons = promptValue(await getAddonsChoice(flags.addons, frontendList, "none", "none", "bun"));
5742
- const webDeploy = promptValue(await getDeploymentChoice(flags.webDeploy, "bun", "none", frontendList));
5743
- const serverDeploy = await selectServerDeployment(flags.serverDeploy);
6147
+ const addons = await scopedPromptValue("typescript", "addons", configScope, typeScriptSections, () => getAddonsChoice(flags.addons, frontendList, "none", "none", "bun"));
6148
+ const webDeploy = await scopedPromptValue("typescript", "webDeploy", configScope, typeScriptSections, () => getDeploymentChoice(flags.webDeploy, "bun", "none", frontendList));
6149
+ const serverDeploy = shouldAskConfigPromptKey("typescript", "serverDeploy", configScope, typeScriptSections) ? await selectServerDeployment(flags.serverDeploy) : getDefaultPromptValue("serverDeploy");
5744
6150
  const aiDocs = promptValue(await getAiDocsChoice(flags.aiDocs));
5745
6151
  const git = promptValue(await getGitChoice(flags.git));
5746
6152
  const packageManager = promptValue(await getPackageManagerChoice(flags.packageManager));
@@ -6325,192 +6731,16 @@ async function getRuntimeChoice(runtime, backend) {
6325
6731
  }
6326
6732
 
6327
6733
  //#endregion
6328
- //#region src/prompts/search.ts
6329
- const SEARCH_PROMPT_OPTIONS = [
6330
- {
6331
- value: "meilisearch",
6332
- label: "Meilisearch",
6333
- hint: "Lightning-fast search engine with typo tolerance"
6334
- },
6335
- {
6336
- value: "typesense",
6337
- label: "Typesense",
6338
- hint: "Fast, typo-tolerant search with built-in vector search"
6339
- },
6340
- {
6341
- value: "elasticsearch",
6342
- label: "Elasticsearch",
6343
- hint: "Distributed search and analytics engine with local and cloud deployments"
6344
- },
6345
- {
6346
- value: "opensearch",
6347
- label: "OpenSearch",
6348
- hint: "Open-source search and analytics suite compatible with Elasticsearch APIs"
6349
- },
6350
- {
6351
- value: "algolia",
6352
- label: "Algolia",
6353
- hint: "Hosted search API with instant results, typo tolerance, and analytics"
6354
- },
6355
- {
6356
- value: "none",
6357
- label: "None",
6358
- hint: "Skip search engine setup"
6359
- }
6360
- ];
6361
- const NON_TYPESCRIPT_SEARCH_PROMPT_OPTIONS = SEARCH_PROMPT_OPTIONS.filter((option) => option.value === "meilisearch" || option.value === "none");
6362
- const PYTHON_SEARCH_PROMPT_OPTIONS = SEARCH_PROMPT_OPTIONS.filter((option) => option.value === "meilisearch" || option.value === "elasticsearch" || option.value === "none");
6363
- const GO_SEARCH_PROMPT_OPTIONS = [
6364
- {
6365
- value: "meilisearch",
6366
- label: "Meilisearch",
6367
- hint: "Lightning-fast search engine with typo tolerance"
6368
- },
6369
- {
6370
- value: "bleve",
6371
- label: "Bleve",
6372
- hint: "Embedded, server-less full-text search for Go (no external service)"
6373
- },
6374
- {
6375
- value: "none",
6376
- label: "None",
6377
- hint: "Skip search engine setup"
6378
- }
6379
- ];
6380
- function resolveSearchPrompt(context = {}) {
6381
- if (context.ecosystem === "react-native" || context.ecosystem === "elixir") return {
6734
+ //#region src/prompts/state-management.ts
6735
+ function resolveStateManagementPrompt(context = {}) {
6736
+ if (context.stateManagement !== void 0) return {
6382
6737
  shouldPrompt: false,
6383
6738
  mode: "single",
6384
6739
  options: [],
6385
- autoValue: "none"
6740
+ autoValue: context.stateManagement
6386
6741
  };
6387
- const options = context.ecosystem === "go" ? GO_SEARCH_PROMPT_OPTIONS : context.ecosystem === "python" ? PYTHON_SEARCH_PROMPT_OPTIONS : context.ecosystem && context.ecosystem !== "typescript" ? NON_TYPESCRIPT_SEARCH_PROMPT_OPTIONS : SEARCH_PROMPT_OPTIONS;
6388
- if ((!context.ecosystem || context.ecosystem === "typescript") && (context.backend === "none" || context.backend === "convex")) return {
6389
- shouldPrompt: false,
6390
- mode: "single",
6391
- options: [],
6392
- autoValue: "none"
6393
- };
6394
- return context.search !== void 0 ? {
6395
- shouldPrompt: false,
6396
- mode: "single",
6397
- options,
6398
- autoValue: context.search
6399
- } : {
6400
- shouldPrompt: true,
6401
- mode: "single",
6402
- options,
6403
- initialValue: "none"
6404
- };
6405
- }
6406
- async function getSearchChoice(search, backend, ecosystem) {
6407
- const resolution = resolveSearchPrompt({
6408
- search,
6409
- backend,
6410
- ecosystem
6411
- });
6412
- if (!resolution.shouldPrompt) return resolution.autoValue ?? "none";
6413
- const response = await navigableSelect({
6414
- message: "Select search engine",
6415
- options: resolution.options,
6416
- initialValue: resolution.initialValue
6417
- });
6418
- if (isCancel$1(response)) return exitCancelled("Operation cancelled");
6419
- return response;
6420
- }
6421
-
6422
- //#endregion
6423
- //#region src/prompts/vector-db.ts
6424
- const VECTOR_DB_PROMPT_OPTIONS = [
6425
- {
6426
- value: "pgvector",
6427
- label: "pgvector",
6428
- hint: "Self-hosted Postgres + pgvector extension for embeddings"
6429
- },
6430
- {
6431
- value: "qdrant",
6432
- label: "Qdrant",
6433
- hint: "High-performance open-source vector database"
6434
- },
6435
- {
6436
- value: "chroma",
6437
- label: "Chroma",
6438
- hint: "Lightweight open-source embedding database"
6439
- },
6440
- {
6441
- value: "pinecone",
6442
- label: "Pinecone",
6443
- hint: "Fully managed serverless vector database"
6444
- },
6445
- {
6446
- value: "none",
6447
- label: "None",
6448
- hint: "Skip vector database setup"
6449
- }
6450
- ];
6451
- /**
6452
- * Vector DB is a TypeScript-ecosystem feature backed by a standalone server.
6453
- * Every provider (including pgvector via a dedicated Postgres instance) is a
6454
- * separate service, so there is no dependency on the primary database choice.
6455
- */
6456
- function resolveVectorDbPrompt(context = {}) {
6457
- const skip = () => ({
6458
- shouldPrompt: false,
6459
- mode: "single",
6460
- options: [],
6461
- autoValue: "none"
6462
- });
6463
- if (context.ecosystem && context.ecosystem !== "typescript") return skip();
6464
- if (context.backend === "none" || context.backend === "convex") return skip();
6465
- return context.vectorDb !== void 0 ? {
6466
- shouldPrompt: false,
6467
- mode: "single",
6468
- options: VECTOR_DB_PROMPT_OPTIONS,
6469
- autoValue: context.vectorDb
6470
- } : {
6471
- shouldPrompt: true,
6472
- mode: "single",
6473
- options: VECTOR_DB_PROMPT_OPTIONS,
6474
- initialValue: "none"
6475
- };
6476
- }
6477
- async function getVectorDbChoice(vectorDb, backend, ecosystem) {
6478
- const resolution = resolveVectorDbPrompt({
6479
- vectorDb,
6480
- backend,
6481
- ecosystem
6482
- });
6483
- if (!resolution.shouldPrompt) return resolution.autoValue ?? "none";
6484
- const response = await navigableSelect({
6485
- message: "Select vector database",
6486
- options: resolution.options,
6487
- initialValue: resolution.initialValue
6488
- });
6489
- if (isCancel$1(response)) return exitCancelled("Operation cancelled");
6490
- return response;
6491
- }
6492
-
6493
- //#endregion
6494
- //#region src/prompts/server-deploy.ts
6495
- async function getServerDeploymentChoice(deployment, runtime, backend, _webDeploy) {
6496
- if (deployment !== void 0) return deployment;
6497
- if (backend === "none" || backend === "convex") return "none";
6498
- if (backend !== "hono") return "none";
6499
- if (runtime === "workers") return "cloudflare";
6500
- return "none";
6501
- }
6502
-
6503
- //#endregion
6504
- //#region src/prompts/state-management.ts
6505
- function resolveStateManagementPrompt(context = {}) {
6506
- if (context.stateManagement !== void 0) return {
6507
- shouldPrompt: false,
6508
- mode: "single",
6509
- options: [],
6510
- autoValue: context.stateManagement
6511
- };
6512
- const { web } = splitFrontends$1(context.frontends);
6513
- if (web.length === 0) return {
6742
+ const { web } = splitFrontends$1(context.frontends);
6743
+ if (web.length === 0) return {
6514
6744
  shouldPrompt: false,
6515
6745
  mode: "single",
6516
6746
  options: [],
@@ -6700,14 +6930,1043 @@ async function getValidationChoice(validation) {
6700
6930
  return response;
6701
6931
  }
6702
6932
 
6933
+ //#endregion
6934
+ //#region src/prompts/prompt-resolver-registry.ts
6935
+ const PROMPT_RESOLVER_REGISTRY = {
6936
+ frontend: {
6937
+ schemaValues: types_exports.FRONTEND_VALUES,
6938
+ resolve: resolveFrontendPrompt,
6939
+ coverageContexts: [{ backend: "hono" }, { frontendOptions: ["none"] }]
6940
+ },
6941
+ backend: {
6942
+ schemaValues: types_exports.BACKEND_VALUES,
6943
+ resolve: resolveBackendPrompt,
6944
+ coverageContexts: [{ frontends: ["next"] }]
6945
+ },
6946
+ ai: {
6947
+ schemaValues: types_exports.AI_VALUES,
6948
+ resolve: ({ value } = {}) => resolveAIPrompt(value),
6949
+ coverageContexts: [{}]
6950
+ },
6951
+ animation: {
6952
+ schemaValues: types_exports.ANIMATION_VALUES,
6953
+ resolve: resolveAnimationPrompt,
6954
+ coverageContexts: [{ frontends: ["react-vite"] }]
6955
+ },
6956
+ api: {
6957
+ schemaValues: types_exports.API_VALUES,
6958
+ resolve: resolveApiPrompt,
6959
+ coverageContexts: [{
6960
+ frontend: ["next"],
6961
+ backend: "hono"
6962
+ }, { backend: "convex" }]
6963
+ },
6964
+ auth: {
6965
+ schemaValues: types_exports.AUTH_VALUES,
6966
+ resolve: resolveAuthPrompt,
6967
+ coverageContexts: [{
6968
+ ecosystem: "typescript",
6969
+ backend: "self",
6970
+ frontend: ["next"]
6971
+ }, {
6972
+ ecosystem: "go",
6973
+ backend: "none",
6974
+ frontend: []
6975
+ }]
6976
+ },
6977
+ caching: {
6978
+ schemaValues: types_exports.CACHING_VALUES,
6979
+ resolve: resolveCachingPrompt,
6980
+ coverageContexts: [{ backend: "hono" }, { backend: "none" }]
6981
+ },
6982
+ rateLimit: {
6983
+ schemaValues: types_exports.RATE_LIMIT_VALUES,
6984
+ resolve: resolveRateLimitPrompt,
6985
+ coverageContexts: [{ backend: "hono" }, { backend: "none" }]
6986
+ },
6987
+ cms: {
6988
+ schemaValues: types_exports.CMS_VALUES,
6989
+ resolve: resolveCMSPrompt,
6990
+ coverageContexts: [{ backend: "hono" }, { backend: "none" }]
6991
+ },
6992
+ cssFramework: {
6993
+ schemaValues: types_exports.CSS_FRAMEWORK_VALUES,
6994
+ resolve: resolveCSSFrameworkPrompt,
6995
+ coverageContexts: [{}, { uiLibrary: "radix-ui" }]
6996
+ },
6997
+ database: {
6998
+ schemaValues: types_exports.DATABASE_VALUES,
6999
+ resolve: resolveDatabasePrompt,
7000
+ coverageContexts: [{
7001
+ backend: "hono",
7002
+ runtime: "node"
7003
+ }, { backend: "none" }]
7004
+ },
7005
+ dbSetup: {
7006
+ schemaValues: types_exports.DATABASE_SETUP_VALUES,
7007
+ resolve: resolveDBSetupPrompt,
7008
+ coverageContexts: [
7009
+ {
7010
+ databaseType: "sqlite",
7011
+ runtime: "workers"
7012
+ },
7013
+ { databaseType: "postgres" },
7014
+ { databaseType: "mongodb" },
7015
+ { databaseType: "redis" }
7016
+ ]
7017
+ },
7018
+ email: {
7019
+ schemaValues: types_exports.EMAIL_VALUES,
7020
+ resolve: resolveEmailPrompt,
7021
+ coverageContexts: [{ backend: "hono" }, { backend: "none" }]
7022
+ },
7023
+ fileUpload: {
7024
+ schemaValues: types_exports.FILE_UPLOAD_VALUES,
7025
+ resolve: resolveFileUploadPrompt,
7026
+ coverageContexts: [{ backend: "hono" }, { backend: "none" }]
7027
+ },
7028
+ forms: {
7029
+ schemaValues: types_exports.FORMS_VALUES,
7030
+ resolve: resolveFormsPrompt,
7031
+ coverageContexts: [{ frontends: ["react-vite"] }, { frontends: ["solid"] }]
7032
+ },
7033
+ jobQueue: {
7034
+ schemaValues: types_exports.JOB_QUEUE_VALUES,
7035
+ resolve: resolveJobQueuePrompt,
7036
+ coverageContexts: [{ backend: "hono" }, { backend: "none" }]
7037
+ },
7038
+ logging: {
7039
+ schemaValues: types_exports.LOGGING_VALUES,
7040
+ resolve: resolveLoggingPrompt,
7041
+ coverageContexts: [{ backend: "hono" }, { backend: "none" }]
7042
+ },
7043
+ observability: {
7044
+ schemaValues: types_exports.OBSERVABILITY_VALUES,
7045
+ resolve: resolveObservabilityPrompt,
7046
+ coverageContexts: [{ backend: "hono" }, { backend: "none" }]
7047
+ },
7048
+ orm: {
7049
+ schemaValues: types_exports.ORM_VALUES,
7050
+ resolve: resolveORMPrompt,
7051
+ coverageContexts: [
7052
+ {
7053
+ hasDatabase: true,
7054
+ database: "postgres",
7055
+ runtime: "node"
7056
+ },
7057
+ {
7058
+ hasDatabase: true,
7059
+ database: "mongodb"
7060
+ },
7061
+ { hasDatabase: false }
7062
+ ]
7063
+ },
7064
+ payments: {
7065
+ schemaValues: types_exports.PAYMENTS_VALUES,
7066
+ resolve: resolvePaymentsPrompt,
7067
+ coverageContexts: [{
7068
+ auth: "better-auth",
7069
+ backend: "hono",
7070
+ frontends: ["next"]
7071
+ }, {
7072
+ auth: "better-auth",
7073
+ backend: "hono",
7074
+ frontends: ["native-bare"]
7075
+ }]
7076
+ },
7077
+ realtime: {
7078
+ schemaValues: types_exports.REALTIME_VALUES,
7079
+ resolve: resolveRealtimePrompt,
7080
+ coverageContexts: [{ backend: "hono" }, { backend: "none" }]
7081
+ },
7082
+ runtime: {
7083
+ schemaValues: types_exports.RUNTIME_VALUES,
7084
+ resolve: resolveRuntimePrompt,
7085
+ coverageContexts: [{ backend: "hono" }, { backend: "self" }]
7086
+ },
7087
+ stateManagement: {
7088
+ schemaValues: types_exports.STATE_MANAGEMENT_VALUES,
7089
+ resolve: resolveStateManagementPrompt,
7090
+ coverageContexts: [{ frontends: ["react-vite"] }]
7091
+ },
7092
+ testing: {
7093
+ schemaValues: types_exports.TESTING_VALUES,
7094
+ resolve: ({ value } = {}) => resolveTestingPrompt(value),
7095
+ coverageContexts: [{}]
7096
+ },
7097
+ mobileNavigation: {
7098
+ schemaValues: types_exports.MOBILE_NAVIGATION_VALUES,
7099
+ resolve: ({ value } = {}) => resolveMobileNavigationPrompt(value),
7100
+ coverageContexts: [{}]
7101
+ },
7102
+ mobileUI: {
7103
+ schemaValues: types_exports.MOBILE_UI_VALUES,
7104
+ resolve: ({ value } = {}) => resolveMobileUIPrompt(value),
7105
+ coverageContexts: [{}]
7106
+ },
7107
+ mobileStorage: {
7108
+ schemaValues: types_exports.MOBILE_STORAGE_VALUES,
7109
+ resolve: ({ value } = {}) => resolveMobileStoragePrompt(value),
7110
+ coverageContexts: [{}]
7111
+ },
7112
+ mobileTesting: {
7113
+ schemaValues: types_exports.MOBILE_TESTING_VALUES,
7114
+ resolve: ({ value } = {}) => resolveMobileTestingPrompt(value),
7115
+ coverageContexts: [{}]
7116
+ },
7117
+ mobilePush: {
7118
+ schemaValues: types_exports.MOBILE_PUSH_VALUES,
7119
+ resolve: ({ value } = {}) => resolveMobilePushPrompt(value),
7120
+ coverageContexts: [{}]
7121
+ },
7122
+ mobileOTA: {
7123
+ schemaValues: types_exports.MOBILE_OTA_VALUES,
7124
+ resolve: ({ value } = {}) => resolveMobileOTAPrompt(value),
7125
+ coverageContexts: [{}]
7126
+ },
7127
+ mobileDeepLinking: {
7128
+ schemaValues: types_exports.MOBILE_DEEP_LINKING_VALUES,
7129
+ resolve: ({ value } = {}) => resolveMobileDeepLinkingPrompt(value),
7130
+ coverageContexts: [{}]
7131
+ },
7132
+ uiLibrary: {
7133
+ schemaValues: types_exports.UI_LIBRARY_VALUES,
7134
+ resolve: resolveUILibraryPrompt,
7135
+ coverageContexts: [
7136
+ { frontends: ["react-vite"] },
7137
+ { frontends: ["svelte"] },
7138
+ { frontends: ["solid"] },
7139
+ { frontends: ["vue"] }
7140
+ ]
7141
+ },
7142
+ validation: {
7143
+ schemaValues: types_exports.VALIDATION_VALUES,
7144
+ resolve: ({ value } = {}) => resolveValidationPrompt(value),
7145
+ coverageContexts: [{}]
7146
+ },
7147
+ astroIntegration: {
7148
+ schemaValues: types_exports.ASTRO_INTEGRATION_VALUES,
7149
+ resolve: ({ value } = {}) => resolveAstroIntegrationPrompt(value),
7150
+ coverageContexts: [{}]
7151
+ },
7152
+ rustWebFramework: {
7153
+ schemaValues: types_exports.RUST_WEB_FRAMEWORK_VALUES,
7154
+ resolve: ({ value } = {}) => resolveRustWebFrameworkPrompt(value),
7155
+ coverageContexts: [{}]
7156
+ },
7157
+ rustFrontend: {
7158
+ schemaValues: types_exports.RUST_FRONTEND_VALUES,
7159
+ resolve: ({ value } = {}) => resolveRustFrontendPrompt(value),
7160
+ coverageContexts: [{}]
7161
+ },
7162
+ rustOrm: {
7163
+ schemaValues: types_exports.RUST_ORM_VALUES,
7164
+ resolve: ({ value } = {}) => resolveRustOrmPrompt(value),
7165
+ coverageContexts: [{}]
7166
+ },
7167
+ rustApi: {
7168
+ schemaValues: types_exports.RUST_API_VALUES,
7169
+ resolve: ({ value } = {}) => resolveRustApiPrompt(value),
7170
+ coverageContexts: [{}]
7171
+ },
7172
+ rustCli: {
7173
+ schemaValues: types_exports.RUST_CLI_VALUES,
7174
+ resolve: ({ value } = {}) => resolveRustCliPrompt(value),
7175
+ coverageContexts: [{}]
7176
+ },
7177
+ rustLogging: {
7178
+ schemaValues: types_exports.RUST_LOGGING_VALUES,
7179
+ resolve: ({ value } = {}) => resolveRustLoggingPrompt(value),
7180
+ coverageContexts: [{}]
7181
+ },
7182
+ rustErrorHandling: {
7183
+ schemaValues: types_exports.RUST_ERROR_HANDLING_VALUES,
7184
+ resolve: ({ value } = {}) => resolveRustErrorHandlingPrompt(value),
7185
+ coverageContexts: [{}]
7186
+ },
7187
+ rustLibraries: {
7188
+ schemaValues: types_exports.RUST_LIBRARIES_VALUES,
7189
+ resolve: ({ value } = {}) => resolveRustLibrariesPrompt(value),
7190
+ coverageContexts: [{}, { value: ["none"] }]
7191
+ },
7192
+ rustCaching: {
7193
+ schemaValues: types_exports.RUST_CACHING_VALUES,
7194
+ resolve: ({ value } = {}) => resolveRustCachingPrompt(value),
7195
+ coverageContexts: [{}]
7196
+ },
7197
+ pythonWebFramework: {
7198
+ schemaValues: types_exports.PYTHON_WEB_FRAMEWORK_VALUES,
7199
+ resolve: ({ value } = {}) => resolvePythonWebFrameworkPrompt(value),
7200
+ coverageContexts: [{}]
7201
+ },
7202
+ pythonOrm: {
7203
+ schemaValues: types_exports.PYTHON_ORM_VALUES,
7204
+ resolve: ({ value } = {}) => resolvePythonOrmPrompt(value),
7205
+ coverageContexts: [{}]
7206
+ },
7207
+ pythonValidation: {
7208
+ schemaValues: types_exports.PYTHON_VALIDATION_VALUES,
7209
+ resolve: ({ value } = {}) => resolvePythonValidationPrompt(value),
7210
+ coverageContexts: [{}]
7211
+ },
7212
+ pythonAi: {
7213
+ schemaValues: types_exports.PYTHON_AI_VALUES,
7214
+ resolve: ({ value } = {}) => resolvePythonAiPrompt(value),
7215
+ coverageContexts: [{}, { value: ["none"] }]
7216
+ },
7217
+ pythonAuth: {
7218
+ schemaValues: types_exports.PYTHON_AUTH_VALUES,
7219
+ resolve: ({ value } = {}) => resolvePythonAuthPrompt(value),
7220
+ coverageContexts: [{}]
7221
+ },
7222
+ pythonApi: {
7223
+ schemaValues: types_exports.PYTHON_API_VALUES,
7224
+ resolve: ({ value } = {}) => resolvePythonApiPrompt(value),
7225
+ coverageContexts: [{}]
7226
+ },
7227
+ pythonTaskQueue: {
7228
+ schemaValues: types_exports.PYTHON_TASK_QUEUE_VALUES,
7229
+ resolve: ({ value } = {}) => resolvePythonTaskQueuePrompt(value),
7230
+ coverageContexts: [{}]
7231
+ },
7232
+ pythonGraphql: {
7233
+ schemaValues: types_exports.PYTHON_GRAPHQL_VALUES,
7234
+ resolve: ({ value } = {}) => resolvePythonGraphqlPrompt(value),
7235
+ coverageContexts: [{}]
7236
+ },
7237
+ pythonQuality: {
7238
+ schemaValues: types_exports.PYTHON_QUALITY_VALUES,
7239
+ resolve: ({ value } = {}) => resolvePythonQualityPrompt(value),
7240
+ coverageContexts: [{}]
7241
+ },
7242
+ goWebFramework: {
7243
+ schemaValues: types_exports.GO_WEB_FRAMEWORK_VALUES,
7244
+ resolve: ({ value } = {}) => resolveGoWebFrameworkPrompt(value),
7245
+ coverageContexts: [{}]
7246
+ },
7247
+ goOrm: {
7248
+ schemaValues: types_exports.GO_ORM_VALUES,
7249
+ resolve: ({ value } = {}) => resolveGoOrmPrompt(value),
7250
+ coverageContexts: [{}]
7251
+ },
7252
+ goApi: {
7253
+ schemaValues: types_exports.GO_API_VALUES,
7254
+ resolve: ({ value } = {}) => resolveGoApiPrompt(value),
7255
+ coverageContexts: [{}]
7256
+ },
7257
+ goCli: {
7258
+ schemaValues: types_exports.GO_CLI_VALUES,
7259
+ resolve: ({ value } = {}) => resolveGoCliPrompt(value),
7260
+ coverageContexts: [{}]
7261
+ },
7262
+ goLogging: {
7263
+ schemaValues: types_exports.GO_LOGGING_VALUES,
7264
+ resolve: ({ value } = {}) => resolveGoLoggingPrompt(value),
7265
+ coverageContexts: [{}]
7266
+ },
7267
+ goAuth: {
7268
+ schemaValues: types_exports.GO_AUTH_VALUES,
7269
+ resolve: ({ value } = {}) => resolveGoAuthPrompt(value),
7270
+ coverageContexts: [{}]
7271
+ },
7272
+ javaWebFramework: {
7273
+ schemaValues: types_exports.JAVA_WEB_FRAMEWORK_VALUES,
7274
+ resolve: ({ value } = {}) => resolveJavaWebFrameworkPrompt(value),
7275
+ coverageContexts: [{}]
7276
+ },
7277
+ javaBuildTool: {
7278
+ schemaValues: types_exports.JAVA_BUILD_TOOL_VALUES,
7279
+ resolve: ({ value } = {}) => resolveJavaBuildToolPrompt(value),
7280
+ coverageContexts: [{}]
7281
+ },
7282
+ javaOrm: {
7283
+ schemaValues: types_exports.JAVA_ORM_VALUES,
7284
+ resolve: ({ value } = {}) => resolveJavaOrmPrompt(value),
7285
+ coverageContexts: [{}]
7286
+ },
7287
+ javaAuth: {
7288
+ schemaValues: types_exports.JAVA_AUTH_VALUES,
7289
+ resolve: ({ value } = {}) => resolveJavaAuthPrompt(value),
7290
+ coverageContexts: [{}]
7291
+ },
7292
+ javaLibraries: {
7293
+ schemaValues: types_exports.JAVA_LIBRARIES_VALUES,
7294
+ resolve: ({ value } = {}) => resolveJavaLibrariesPrompt(value),
7295
+ coverageContexts: [{}, { value: ["none"] }]
7296
+ },
7297
+ javaTestingLibraries: {
7298
+ schemaValues: types_exports.JAVA_TESTING_LIBRARIES_VALUES,
7299
+ resolve: ({ value } = {}) => resolveJavaTestingLibrariesPrompt(value),
7300
+ coverageContexts: [{}, { value: ["none"] }]
7301
+ },
7302
+ dotnetWebFramework: {
7303
+ schemaValues: types_exports.DOTNET_WEB_FRAMEWORK_VALUES,
7304
+ resolve: ({ value } = {}) => resolveDotnetWebFrameworkPrompt(value),
7305
+ coverageContexts: [{}]
7306
+ },
7307
+ dotnetOrm: {
7308
+ schemaValues: types_exports.DOTNET_ORM_VALUES,
7309
+ resolve: ({ value } = {}) => resolveDotnetOrmPrompt(value),
7310
+ coverageContexts: [{}]
7311
+ },
7312
+ dotnetAuth: {
7313
+ schemaValues: types_exports.DOTNET_AUTH_VALUES,
7314
+ resolve: ({ value } = {}) => resolveDotnetAuthPrompt(value),
7315
+ coverageContexts: [{}]
7316
+ },
7317
+ dotnetApi: {
7318
+ schemaValues: types_exports.DOTNET_API_VALUES,
7319
+ resolve: ({ value } = {}) => resolveDotnetApiPrompt(value),
7320
+ coverageContexts: [{}]
7321
+ },
7322
+ dotnetTesting: {
7323
+ schemaValues: types_exports.DOTNET_TESTING_VALUES,
7324
+ resolve: ({ value } = {}) => resolveDotnetTestingPrompt(value),
7325
+ coverageContexts: [{}, { value: ["none"] }]
7326
+ },
7327
+ dotnetJobQueue: {
7328
+ schemaValues: types_exports.DOTNET_JOB_QUEUE_VALUES,
7329
+ resolve: ({ value } = {}) => resolveDotnetJobQueuePrompt(value),
7330
+ coverageContexts: [{}]
7331
+ },
7332
+ dotnetRealtime: {
7333
+ schemaValues: types_exports.DOTNET_REALTIME_VALUES,
7334
+ resolve: ({ value } = {}) => resolveDotnetRealtimePrompt(value),
7335
+ coverageContexts: [{}]
7336
+ },
7337
+ dotnetObservability: {
7338
+ schemaValues: types_exports.DOTNET_OBSERVABILITY_VALUES,
7339
+ resolve: ({ value } = {}) => resolveDotnetObservabilityPrompt(value),
7340
+ coverageContexts: [{}, { value: ["none"] }]
7341
+ },
7342
+ dotnetCaching: {
7343
+ schemaValues: types_exports.DOTNET_CACHING_VALUES,
7344
+ resolve: ({ value } = {}) => resolveDotnetCachingPrompt(value),
7345
+ coverageContexts: [{}]
7346
+ },
7347
+ dotnetDeploy: {
7348
+ schemaValues: types_exports.DOTNET_DEPLOY_VALUES,
7349
+ resolve: ({ value } = {}) => resolveDotnetDeployPrompt(value),
7350
+ coverageContexts: [{}]
7351
+ },
7352
+ elixirWebFramework: {
7353
+ schemaValues: types_exports.ELIXIR_WEB_FRAMEWORK_VALUES,
7354
+ resolve: ({ value } = {}) => resolveElixirWebFrameworkPrompt(value),
7355
+ coverageContexts: [{}]
7356
+ },
7357
+ elixirOrm: {
7358
+ schemaValues: types_exports.ELIXIR_ORM_VALUES,
7359
+ resolve: ({ value } = {}) => resolveElixirOrmPrompt(value),
7360
+ coverageContexts: [{}]
7361
+ },
7362
+ elixirAuth: {
7363
+ schemaValues: types_exports.ELIXIR_AUTH_VALUES,
7364
+ resolve: ({ value } = {}) => resolveElixirAuthPrompt(value),
7365
+ coverageContexts: [{}]
7366
+ },
7367
+ elixirApi: {
7368
+ schemaValues: types_exports.ELIXIR_API_VALUES,
7369
+ resolve: ({ value } = {}) => resolveElixirApiPrompt(value),
7370
+ coverageContexts: [{}]
7371
+ },
7372
+ elixirRealtime: {
7373
+ schemaValues: types_exports.ELIXIR_REALTIME_VALUES,
7374
+ resolve: ({ value } = {}) => resolveElixirRealtimePrompt(value),
7375
+ coverageContexts: [{}]
7376
+ },
7377
+ elixirJobs: {
7378
+ schemaValues: types_exports.ELIXIR_JOBS_VALUES,
7379
+ resolve: ({ value } = {}) => resolveElixirJobsPrompt(value),
7380
+ coverageContexts: [{}]
7381
+ },
7382
+ elixirValidation: {
7383
+ schemaValues: types_exports.ELIXIR_VALIDATION_VALUES,
7384
+ resolve: ({ value } = {}) => resolveElixirValidationPrompt(value),
7385
+ coverageContexts: [{}]
7386
+ },
7387
+ elixirHttp: {
7388
+ schemaValues: types_exports.ELIXIR_HTTP_VALUES,
7389
+ resolve: ({ value } = {}) => resolveElixirHttpPrompt(value),
7390
+ coverageContexts: [{}]
7391
+ },
7392
+ elixirJson: {
7393
+ schemaValues: types_exports.ELIXIR_JSON_VALUES,
7394
+ resolve: ({ value } = {}) => resolveElixirJsonPrompt(value),
7395
+ coverageContexts: [{}]
7396
+ },
7397
+ elixirEmail: {
7398
+ schemaValues: types_exports.ELIXIR_EMAIL_VALUES,
7399
+ resolve: ({ value } = {}) => resolveElixirEmailPrompt(value),
7400
+ coverageContexts: [{}]
7401
+ },
7402
+ elixirCaching: {
7403
+ schemaValues: types_exports.ELIXIR_CACHING_VALUES,
7404
+ resolve: ({ value } = {}) => resolveElixirCachingPrompt(value),
7405
+ coverageContexts: [{}]
7406
+ },
7407
+ elixirObservability: {
7408
+ schemaValues: types_exports.ELIXIR_OBSERVABILITY_VALUES,
7409
+ resolve: ({ value } = {}) => resolveElixirObservabilityPrompt(value),
7410
+ coverageContexts: [{}]
7411
+ },
7412
+ elixirTesting: {
7413
+ schemaValues: types_exports.ELIXIR_TESTING_VALUES,
7414
+ resolve: ({ value } = {}) => resolveElixirTestingPrompt(value),
7415
+ coverageContexts: [{}]
7416
+ },
7417
+ elixirQuality: {
7418
+ schemaValues: types_exports.ELIXIR_QUALITY_VALUES,
7419
+ resolve: ({ value } = {}) => resolveElixirQualityPrompt(value),
7420
+ coverageContexts: [{}]
7421
+ },
7422
+ elixirDeploy: {
7423
+ schemaValues: types_exports.ELIXIR_DEPLOY_VALUES,
7424
+ resolve: ({ value } = {}) => resolveElixirDeployPrompt(value),
7425
+ coverageContexts: [{}]
7426
+ }
7427
+ };
7428
+
7429
+ //#endregion
7430
+ //#region src/prompts/search.ts
7431
+ const SEARCH_PROMPT_OPTIONS = [
7432
+ {
7433
+ value: "meilisearch",
7434
+ label: "Meilisearch",
7435
+ hint: "Lightning-fast search engine with typo tolerance"
7436
+ },
7437
+ {
7438
+ value: "typesense",
7439
+ label: "Typesense",
7440
+ hint: "Fast, typo-tolerant search with built-in vector search"
7441
+ },
7442
+ {
7443
+ value: "elasticsearch",
7444
+ label: "Elasticsearch",
7445
+ hint: "Distributed search and analytics engine with local and cloud deployments"
7446
+ },
7447
+ {
7448
+ value: "opensearch",
7449
+ label: "OpenSearch",
7450
+ hint: "Open-source search and analytics suite compatible with Elasticsearch APIs"
7451
+ },
7452
+ {
7453
+ value: "algolia",
7454
+ label: "Algolia",
7455
+ hint: "Hosted search API with instant results, typo tolerance, and analytics"
7456
+ },
7457
+ {
7458
+ value: "none",
7459
+ label: "None",
7460
+ hint: "Skip search engine setup"
7461
+ }
7462
+ ];
7463
+ const NON_TYPESCRIPT_SEARCH_PROMPT_OPTIONS = SEARCH_PROMPT_OPTIONS.filter((option) => option.value === "meilisearch" || option.value === "none");
7464
+ const PYTHON_SEARCH_PROMPT_OPTIONS = SEARCH_PROMPT_OPTIONS.filter((option) => option.value === "meilisearch" || option.value === "elasticsearch" || option.value === "none");
7465
+ const GO_SEARCH_PROMPT_OPTIONS = [
7466
+ {
7467
+ value: "meilisearch",
7468
+ label: "Meilisearch",
7469
+ hint: "Lightning-fast search engine with typo tolerance"
7470
+ },
7471
+ {
7472
+ value: "bleve",
7473
+ label: "Bleve",
7474
+ hint: "Embedded, server-less full-text search for Go (no external service)"
7475
+ },
7476
+ {
7477
+ value: "none",
7478
+ label: "None",
7479
+ hint: "Skip search engine setup"
7480
+ }
7481
+ ];
7482
+ function resolveSearchPrompt(context = {}) {
7483
+ if (context.ecosystem === "react-native" || context.ecosystem === "elixir") return {
7484
+ shouldPrompt: false,
7485
+ mode: "single",
7486
+ options: [],
7487
+ autoValue: "none"
7488
+ };
7489
+ const options = context.ecosystem === "go" ? GO_SEARCH_PROMPT_OPTIONS : context.ecosystem === "python" ? PYTHON_SEARCH_PROMPT_OPTIONS : context.ecosystem && context.ecosystem !== "typescript" ? NON_TYPESCRIPT_SEARCH_PROMPT_OPTIONS : SEARCH_PROMPT_OPTIONS;
7490
+ if ((!context.ecosystem || context.ecosystem === "typescript") && (context.backend === "none" || context.backend === "convex")) return {
7491
+ shouldPrompt: false,
7492
+ mode: "single",
7493
+ options: [],
7494
+ autoValue: "none"
7495
+ };
7496
+ return context.search !== void 0 ? {
7497
+ shouldPrompt: false,
7498
+ mode: "single",
7499
+ options,
7500
+ autoValue: context.search
7501
+ } : {
7502
+ shouldPrompt: true,
7503
+ mode: "single",
7504
+ options,
7505
+ initialValue: "none"
7506
+ };
7507
+ }
7508
+ async function getSearchChoice(search, backend, ecosystem) {
7509
+ const resolution = resolveSearchPrompt({
7510
+ search,
7511
+ backend,
7512
+ ecosystem
7513
+ });
7514
+ if (!resolution.shouldPrompt) return resolution.autoValue ?? "none";
7515
+ const response = await navigableSelect({
7516
+ message: "Select search engine",
7517
+ options: resolution.options,
7518
+ initialValue: resolution.initialValue
7519
+ });
7520
+ if (isCancel$1(response)) return exitCancelled("Operation cancelled");
7521
+ return response;
7522
+ }
7523
+
7524
+ //#endregion
7525
+ //#region src/prompts/vector-db.ts
7526
+ const VECTOR_DB_PROMPT_OPTIONS = [
7527
+ {
7528
+ value: "pgvector",
7529
+ label: "pgvector",
7530
+ hint: "Self-hosted Postgres + pgvector extension for embeddings"
7531
+ },
7532
+ {
7533
+ value: "qdrant",
7534
+ label: "Qdrant",
7535
+ hint: "High-performance open-source vector database"
7536
+ },
7537
+ {
7538
+ value: "chroma",
7539
+ label: "Chroma",
7540
+ hint: "Lightweight open-source embedding database"
7541
+ },
7542
+ {
7543
+ value: "pinecone",
7544
+ label: "Pinecone",
7545
+ hint: "Fully managed serverless vector database"
7546
+ },
7547
+ {
7548
+ value: "none",
7549
+ label: "None",
7550
+ hint: "Skip vector database setup"
7551
+ }
7552
+ ];
7553
+ /**
7554
+ * Vector DB is a TypeScript-ecosystem feature backed by a standalone server.
7555
+ * Every provider (including pgvector via a dedicated Postgres instance) is a
7556
+ * separate service, so there is no dependency on the primary database choice.
7557
+ */
7558
+ function resolveVectorDbPrompt(context = {}) {
7559
+ const skip = () => ({
7560
+ shouldPrompt: false,
7561
+ mode: "single",
7562
+ options: [],
7563
+ autoValue: "none"
7564
+ });
7565
+ if (context.ecosystem && context.ecosystem !== "typescript") return skip();
7566
+ if (context.backend === "none" || context.backend === "convex") return skip();
7567
+ return context.vectorDb !== void 0 ? {
7568
+ shouldPrompt: false,
7569
+ mode: "single",
7570
+ options: VECTOR_DB_PROMPT_OPTIONS,
7571
+ autoValue: context.vectorDb
7572
+ } : {
7573
+ shouldPrompt: true,
7574
+ mode: "single",
7575
+ options: VECTOR_DB_PROMPT_OPTIONS,
7576
+ initialValue: "none"
7577
+ };
7578
+ }
7579
+ async function getVectorDbChoice(vectorDb, backend, ecosystem) {
7580
+ const resolution = resolveVectorDbPrompt({
7581
+ vectorDb,
7582
+ backend,
7583
+ ecosystem
7584
+ });
7585
+ if (!resolution.shouldPrompt) return resolution.autoValue ?? "none";
7586
+ const response = await navigableSelect({
7587
+ message: "Select vector database",
7588
+ options: resolution.options,
7589
+ initialValue: resolution.initialValue
7590
+ });
7591
+ if (isCancel$1(response)) return exitCancelled("Operation cancelled");
7592
+ return response;
7593
+ }
7594
+
7595
+ //#endregion
7596
+ //#region src/prompts/server-deploy.ts
7597
+ async function getServerDeploymentChoice(deployment, runtime, backend, _webDeploy) {
7598
+ if (deployment !== void 0) return deployment;
7599
+ if (backend === "none" || backend === "convex") return "none";
7600
+ if (backend !== "hono") return "none";
7601
+ if (runtime === "workers") return "cloudflare";
7602
+ const response = await navigableSelect({
7603
+ message: "Select server deployment",
7604
+ options: getServerDeploymentOptions(runtime),
7605
+ initialValue: DEFAULT_CONFIG.serverDeploy
7606
+ });
7607
+ if (isCancel$1(response)) return exitCancelled("Operation cancelled");
7608
+ return response;
7609
+ }
7610
+ function getServerDeploymentOptions(runtime) {
7611
+ return [
7612
+ {
7613
+ value: "none",
7614
+ label: "None",
7615
+ hint: "Skip server deployment setup"
7616
+ },
7617
+ {
7618
+ value: "railway",
7619
+ label: "Railway",
7620
+ hint: "Deploy with Railway cloud development platform"
7621
+ },
7622
+ {
7623
+ value: "fly",
7624
+ label: "Fly.io",
7625
+ hint: "Deploy globally with Fly.io edge platform"
7626
+ },
7627
+ {
7628
+ value: "render",
7629
+ label: "Render",
7630
+ hint: "Deploy with Render's Blueprint and Docker builds"
7631
+ },
7632
+ ...runtime === "node" ? [{
7633
+ value: "netlify",
7634
+ label: "Netlify",
7635
+ hint: "Deploy Hono APIs with Netlify Functions"
7636
+ }] : [],
7637
+ {
7638
+ value: "docker",
7639
+ label: "Docker",
7640
+ hint: "Container-based deployment with Dockerfile"
7641
+ },
7642
+ {
7643
+ value: "sst",
7644
+ label: "SST",
7645
+ hint: "Deploy to AWS with SST (Serverless Stack)"
7646
+ },
7647
+ {
7648
+ value: "vercel",
7649
+ label: "Vercel",
7650
+ hint: "Deploy to Vercel's edge network with zero config"
7651
+ }
7652
+ ];
7653
+ }
7654
+
6703
7655
  //#endregion
6704
7656
  //#region src/prompts/config-prompts.ts
7657
+ const CONFIG_SCOPE_META_KEYS = new Set([
7658
+ "ecosystem",
7659
+ "configScope",
7660
+ "configSections"
7661
+ ]);
7662
+ const SHADCN_FLAG_KEYS = new Set([
7663
+ "shadcnBase",
7664
+ "shadcnStyle",
7665
+ "shadcnIconLibrary",
7666
+ "shadcnColorTheme",
7667
+ "shadcnBaseColor",
7668
+ "shadcnFont",
7669
+ "shadcnRadius"
7670
+ ]);
7671
+ const CONFIG_PROMPT_ENTRY_KEY_MAP = {
7672
+ ecosystem: true,
7673
+ configScope: true,
7674
+ configSections: true,
7675
+ frontend: true,
7676
+ astroIntegration: true,
7677
+ uiLibrary: true,
7678
+ shadcnOptions: true,
7679
+ cssFramework: true,
7680
+ backend: true,
7681
+ runtime: true,
7682
+ database: true,
7683
+ orm: true,
7684
+ api: true,
7685
+ auth: true,
7686
+ payments: true,
7687
+ email: true,
7688
+ effect: true,
7689
+ addons: true,
7690
+ examples: true,
7691
+ dbSetup: true,
7692
+ webDeploy: true,
7693
+ serverDeploy: true,
7694
+ ai: true,
7695
+ validation: true,
7696
+ forms: true,
7697
+ stateManagement: true,
7698
+ animation: true,
7699
+ testing: true,
7700
+ realtime: true,
7701
+ jobQueue: true,
7702
+ fileUpload: true,
7703
+ logging: true,
7704
+ observability: true,
7705
+ featureFlags: true,
7706
+ analytics: true,
7707
+ cms: true,
7708
+ caching: true,
7709
+ rateLimit: true,
7710
+ i18n: true,
7711
+ search: true,
7712
+ vectorDb: true,
7713
+ fileStorage: true,
7714
+ mobileNavigation: true,
7715
+ mobileUI: true,
7716
+ mobileStorage: true,
7717
+ mobileTesting: true,
7718
+ mobilePush: true,
7719
+ mobileOTA: true,
7720
+ mobileDeepLinking: true,
7721
+ rustWebFramework: true,
7722
+ rustFrontend: true,
7723
+ rustOrm: true,
7724
+ rustApi: true,
7725
+ rustCli: true,
7726
+ rustLibraries: true,
7727
+ rustLogging: true,
7728
+ rustErrorHandling: true,
7729
+ rustCaching: true,
7730
+ rustAuth: true,
7731
+ rustRealtime: true,
7732
+ rustMessageQueue: true,
7733
+ rustObservability: true,
7734
+ rustTemplating: true,
7735
+ pythonWebFramework: true,
7736
+ pythonOrm: true,
7737
+ pythonValidation: true,
7738
+ pythonAi: true,
7739
+ pythonAuth: true,
7740
+ pythonApi: true,
7741
+ pythonTaskQueue: true,
7742
+ pythonGraphql: true,
7743
+ pythonQuality: true,
7744
+ pythonTesting: true,
7745
+ pythonCaching: true,
7746
+ pythonRealtime: true,
7747
+ pythonObservability: true,
7748
+ pythonCli: true,
7749
+ goWebFramework: true,
7750
+ goOrm: true,
7751
+ goApi: true,
7752
+ goCli: true,
7753
+ goLogging: true,
7754
+ goAuth: true,
7755
+ goTesting: true,
7756
+ goRealtime: true,
7757
+ goMessageQueue: true,
7758
+ goCaching: true,
7759
+ goConfig: true,
7760
+ goObservability: true,
7761
+ javaWebFramework: true,
7762
+ javaLanguage: true,
7763
+ javaBuildTool: true,
7764
+ javaOrm: true,
7765
+ javaAuth: true,
7766
+ javaApi: true,
7767
+ javaLogging: true,
7768
+ javaLibraries: true,
7769
+ javaTestingLibraries: true,
7770
+ dotnetWebFramework: true,
7771
+ dotnetOrm: true,
7772
+ dotnetAuth: true,
7773
+ dotnetApi: true,
7774
+ dotnetTesting: true,
7775
+ dotnetJobQueue: true,
7776
+ dotnetRealtime: true,
7777
+ dotnetObservability: true,
7778
+ dotnetValidation: true,
7779
+ dotnetCaching: true,
7780
+ dotnetDeploy: true,
7781
+ elixirWebFramework: true,
7782
+ elixirOrm: true,
7783
+ elixirAuth: true,
7784
+ elixirApi: true,
7785
+ elixirRealtime: true,
7786
+ elixirJobs: true,
7787
+ elixirValidation: true,
7788
+ elixirHttp: true,
7789
+ elixirJson: true,
7790
+ elixirEmail: true,
7791
+ elixirCaching: true,
7792
+ elixirObservability: true,
7793
+ elixirTesting: true,
7794
+ elixirQuality: true,
7795
+ elixirDeploy: true,
7796
+ elixirLibraries: true,
7797
+ aiDocs: true,
7798
+ git: true,
7799
+ workspaceShape: true,
7800
+ packageManager: true,
7801
+ install: true
7802
+ };
7803
+ const CONFIG_PROMPT_ENTRY_KEYS = Object.keys(CONFIG_PROMPT_ENTRY_KEY_MAP);
7804
+ function hasStackPromptFlags(flags) {
7805
+ return Object.keys(flags).some((key) => {
7806
+ if (key === "projectName" || key === "projectDir" || key === "relativePath") return false;
7807
+ if (SHADCN_FLAG_KEYS.has(key)) return true;
7808
+ return CONFIG_PROMPT_ENTRY_KEYS.includes(key);
7809
+ });
7810
+ }
7811
+ function getPromptResolutionValue(key, results, flags) {
7812
+ const resolver = PROMPT_RESOLVER_REGISTRY[key];
7813
+ if (!resolver) return void 0;
7814
+ const frontends = results.frontend ?? flags.frontend;
7815
+ const contextByKey = {
7816
+ frontend: {
7817
+ frontend: flags.frontend,
7818
+ backend: flags.backend,
7819
+ auth: flags.auth
7820
+ },
7821
+ backend: {
7822
+ backendFramework: flags.backend,
7823
+ frontends
7824
+ },
7825
+ runtime: {
7826
+ runtime: flags.runtime,
7827
+ backend: results.backend
7828
+ },
7829
+ database: {
7830
+ database: flags.database,
7831
+ backend: results.backend,
7832
+ runtime: results.runtime
7833
+ },
7834
+ orm: {
7835
+ orm: flags.orm,
7836
+ hasDatabase: results.database !== void 0 && results.database !== "none",
7837
+ database: results.database,
7838
+ backend: results.backend,
7839
+ runtime: results.runtime
7840
+ },
7841
+ api: {
7842
+ api: flags.api,
7843
+ frontend: frontends,
7844
+ backend: results.backend,
7845
+ astroIntegration: results.astroIntegration
7846
+ },
7847
+ auth: {
7848
+ auth: flags.auth,
7849
+ backend: results.backend,
7850
+ frontend: frontends,
7851
+ ecosystem: results.ecosystem
7852
+ },
7853
+ payments: {
7854
+ payments: flags.payments,
7855
+ auth: results.auth,
7856
+ backend: results.backend,
7857
+ frontends
7858
+ },
7859
+ email: {
7860
+ email: flags.email,
7861
+ backend: results.backend,
7862
+ ecosystem: results.ecosystem
7863
+ },
7864
+ uiLibrary: {
7865
+ uiLibrary: flags.uiLibrary,
7866
+ frontends,
7867
+ astroIntegration: results.astroIntegration
7868
+ },
7869
+ cssFramework: {
7870
+ cssFramework: flags.cssFramework,
7871
+ uiLibrary: results.uiLibrary
7872
+ },
7873
+ forms: {
7874
+ forms: flags.forms,
7875
+ frontends
7876
+ },
7877
+ stateManagement: {
7878
+ stateManagement: flags.stateManagement,
7879
+ frontends
7880
+ },
7881
+ animation: {
7882
+ animation: flags.animation,
7883
+ frontends
7884
+ },
7885
+ caching: {
7886
+ caching: flags.caching,
7887
+ backend: results.backend,
7888
+ ecosystem: results.ecosystem
7889
+ },
7890
+ search: {
7891
+ search: flags.search,
7892
+ backend: results.backend,
7893
+ ecosystem: results.ecosystem
7894
+ },
7895
+ observability: {
7896
+ observability: flags.observability,
7897
+ backend: results.backend,
7898
+ ecosystem: results.ecosystem
7899
+ },
7900
+ realtime: {
7901
+ realtime: flags.realtime,
7902
+ backend: results.backend
7903
+ },
7904
+ jobQueue: {
7905
+ jobQueue: flags.jobQueue,
7906
+ backend: results.backend
7907
+ },
7908
+ fileUpload: {
7909
+ fileUpload: flags.fileUpload,
7910
+ backend: results.backend
7911
+ },
7912
+ logging: {
7913
+ logging: flags.logging,
7914
+ backend: results.backend
7915
+ },
7916
+ rateLimit: {
7917
+ rateLimit: flags.rateLimit,
7918
+ backend: results.backend
7919
+ },
7920
+ cms: {
7921
+ cms: flags.cms,
7922
+ backend: results.backend
7923
+ },
7924
+ vectorDb: {
7925
+ vectorDb: flags.vectorDb,
7926
+ backend: results.backend,
7927
+ ecosystem: results.ecosystem
7928
+ },
7929
+ fileStorage: {
7930
+ fileStorage: flags.fileStorage,
7931
+ backend: results.backend
7932
+ }
7933
+ };
7934
+ const selectedValue = flags[key];
7935
+ const context = contextByKey[key] ?? { value: selectedValue };
7936
+ const resolution = resolver.resolve(context);
7937
+ return resolution.autoValue ?? resolution.initialValue;
7938
+ }
7939
+ async function getScopedDefaultPromptValue(key, results, flags) {
7940
+ if (key === "serverDeploy" && results.ecosystem === "typescript") {
7941
+ if (flags.serverDeploy !== void 0) return flags.serverDeploy;
7942
+ if (results.backend !== "hono") return "none";
7943
+ if (results.runtime === "workers") return "cloudflare";
7944
+ return "none";
7945
+ }
7946
+ if (key === "effect" && results.ecosystem === "typescript") return flags.effect ?? (results.backend === "effect" ? "effect-full" : "none");
7947
+ if (key === "validation" && results.ecosystem === "typescript" && results.backend === "effect") return flags.validation ?? "effect-schema";
7948
+ const resolvedValue = getPromptResolutionValue(key, results, flags);
7949
+ if (resolvedValue !== void 0) return resolvedValue;
7950
+ return getDefaultPromptValue(key);
7951
+ }
7952
+ function scopedPrompt(key, flags, prompt) {
7953
+ return (opts) => {
7954
+ if (!CONFIG_SCOPE_META_KEYS.has(key) && !shouldAskConfigPromptKey(opts.results.ecosystem, key, opts.results.configScope, opts.results.configSections)) return getScopedDefaultPromptValue(key, opts.results, flags);
7955
+ return prompt(opts);
7956
+ };
7957
+ }
6705
7958
  async function gatherConfig(flags, projectName, projectDir, relativePath) {
6706
7959
  if (flags.ecosystem === void 0 && flags.stackParts === void 0) {
6707
7960
  if (await getCompositionModeChoice() === "multi") return gatherMultiEcosystemConfig(flags, projectName, projectDir, relativePath);
6708
7961
  }
6709
- const result = await navigableGroup({
7962
+ const shouldPromptForScope = !hasStackPromptFlags(flags);
7963
+ const result = await navigableGroup(Object.fromEntries(Object.entries({
6710
7964
  ecosystem: () => getEcosystemChoice(flags.ecosystem),
7965
+ configScope: () => shouldPromptForScope ? getConfigScopeChoice() : Promise.resolve("full"),
7966
+ configSections: ({ results }) => {
7967
+ if (!shouldPromptForScope || results.configScope !== "custom") return Promise.resolve([]);
7968
+ return getConfigSectionsChoice(results.ecosystem ?? "typescript");
7969
+ },
6711
7970
  frontend: ({ results }) => {
6712
7971
  if (results.ecosystem === "react-native") return getNativeFrontendChoice(flags.frontend);
6713
7972
  if (results.ecosystem !== "typescript") return Promise.resolve([]);
@@ -7092,18 +8351,31 @@ async function gatherConfig(flags, projectName, projectDir, relativePath) {
7092
8351
  javaLanguage: ({ results }) => {
7093
8352
  if (results.ecosystem !== "java") return Promise.resolve("java");
7094
8353
  if (results.javaWebFramework !== "spring-boot") return Promise.resolve("java");
8354
+ const kotlinBlocker = (0, types_exports.getKotlinJavaIncompatibilityReason)({
8355
+ javaWebFramework: results.javaWebFramework,
8356
+ javaBuildTool: "maven",
8357
+ email: results.email,
8358
+ search: results.search,
8359
+ caching: results.caching,
8360
+ observability: results.observability
8361
+ });
8362
+ if (kotlinBlocker) {
8363
+ if (flags.javaLanguage === "kotlin") log.warn(`JVM language set to Java: ${kotlinBlocker}`);
8364
+ else if (flags.javaLanguage === void 0 && flags.javaWebFramework === void 0) log.info(`Kotlin not offered: ${kotlinBlocker}`);
8365
+ return Promise.resolve("java");
8366
+ }
7095
8367
  if (flags.javaLanguage !== void 0) return getJavaLanguageChoice(flags.javaLanguage);
7096
8368
  if (flags.javaWebFramework !== void 0) return Promise.resolve("java");
7097
8369
  return getJavaLanguageChoice(flags.javaLanguage);
7098
8370
  },
7099
8371
  javaBuildTool: ({ results }) => {
7100
8372
  if (results.ecosystem !== "java") return Promise.resolve("none");
7101
- return getJavaBuildToolChoice(flags.javaBuildTool);
8373
+ return getJavaBuildToolChoice(flags.javaBuildTool, results.javaLanguage);
7102
8374
  },
7103
8375
  javaOrm: ({ results }) => {
7104
8376
  if (results.ecosystem !== "java") return Promise.resolve("none");
7105
8377
  if (results.javaWebFramework !== "spring-boot" || results.javaBuildTool === "none") return Promise.resolve("none");
7106
- return getJavaOrmChoice(flags.javaOrm);
8378
+ return getJavaOrmChoice(flags.javaOrm, results.javaLanguage);
7107
8379
  },
7108
8380
  javaAuth: ({ results }) => {
7109
8381
  if (results.ecosystem !== "java") return Promise.resolve("none");
@@ -7113,7 +8385,7 @@ async function gatherConfig(flags, projectName, projectDir, relativePath) {
7113
8385
  javaApi: ({ results }) => {
7114
8386
  if (results.ecosystem !== "java") return Promise.resolve("none");
7115
8387
  if (results.javaWebFramework !== "spring-boot") return Promise.resolve("none");
7116
- return getJavaApiChoice(flags.javaApi);
8388
+ return getJavaApiChoice(flags.javaApi, results.javaLanguage);
7117
8389
  },
7118
8390
  javaLogging: ({ results }) => {
7119
8391
  if (results.ecosystem !== "java") return Promise.resolve("none");
@@ -7123,12 +8395,12 @@ async function gatherConfig(flags, projectName, projectDir, relativePath) {
7123
8395
  javaLibraries: ({ results }) => {
7124
8396
  if (results.ecosystem !== "java") return Promise.resolve([]);
7125
8397
  if (results.javaWebFramework !== "spring-boot" || results.javaBuildTool === "none") return Promise.resolve([]);
7126
- return getJavaLibrariesChoice(flags.javaLibraries);
8398
+ return getJavaLibrariesChoice(flags.javaLibraries, results.javaLanguage);
7127
8399
  },
7128
8400
  javaTestingLibraries: ({ results }) => {
7129
8401
  if (results.ecosystem !== "java") return Promise.resolve([]);
7130
8402
  if (results.javaBuildTool === "none") return Promise.resolve([]);
7131
- return getJavaTestingLibrariesChoice(flags.javaTestingLibraries);
8403
+ return getJavaTestingLibrariesChoice(flags.javaTestingLibraries, results.javaLanguage);
7132
8404
  },
7133
8405
  dotnetWebFramework: ({ results }) => {
7134
8406
  if (results.ecosystem !== "dotnet") return Promise.resolve("none");
@@ -7253,7 +8525,7 @@ async function gatherConfig(flags, projectName, projectDir, relativePath) {
7253
8525
  return getPackageManagerChoice(flags.packageManager);
7254
8526
  },
7255
8527
  install: ({ results }) => getinstallChoice(flags.install, results.ecosystem, results.javaBuildTool)
7256
- }, { onCancel: () => exitCancelled("Operation cancelled") });
8528
+ }).map(([key, prompt]) => [key, scopedPrompt(key, flags, prompt)])), { onCancel: () => exitCancelled("Operation cancelled") });
7257
8529
  return {
7258
8530
  projectName,
7259
8531
  projectDir,
@@ -7686,6 +8958,17 @@ function displayConfig(config) {
7686
8958
  return configDisplay.join("\n");
7687
8959
  }
7688
8960
 
8961
+ //#endregion
8962
+ //#region src/utils/open-url.ts
8963
+ async function openUrl(url) {
8964
+ const platform = process.platform;
8965
+ if (platform === "darwin") await $({ stdio: "ignore" })`open ${url}`;
8966
+ else if (platform === "win32") {
8967
+ const escapedUrl = url.replace(/&/g, "^&");
8968
+ await $({ stdio: "ignore" })`cmd /c start "" ${escapedUrl}`;
8969
+ } else await $({ stdio: "ignore" })`xdg-open ${url}`;
8970
+ }
8971
+
7689
8972
  //#endregion
7690
8973
  //#region src/utils/preflight-display.ts
7691
8974
  function displayPreflightWarnings({ warnings }) {
@@ -9830,11 +11113,10 @@ async function createProject(options, cliInput = {}) {
9830
11113
  await rollbackPartialProject(projectDir, dirHadContentBefore);
9831
11114
  if (error instanceof Error) {
9832
11115
  if (!isSilent()) console.error(error.stack);
9833
- exitWithError(`Error during project creation: ${error.message}`);
9834
- } else {
9835
- if (!isSilent()) console.error(error);
9836
- exitWithError(`An unexpected error occurred: ${String(error)}`);
11116
+ throw new CLIError(`Error during project creation: ${error.message}`);
9837
11117
  }
11118
+ if (!isSilent()) console.error(error);
11119
+ throw new CLIError(`An unexpected error occurred: ${String(error)}`);
9838
11120
  }
9839
11121
  }
9840
11122
  /**
@@ -9878,6 +11160,70 @@ async function ensurePackageManagerProjectFiles(projectDir, packageManager) {
9878
11160
 
9879
11161
  //#endregion
9880
11162
  //#region src/helpers/core/command-handlers.ts
11163
+ const NON_STACK_CREATE_OPTION_KEYS = new Set([
11164
+ "template",
11165
+ "fromHistory",
11166
+ "config",
11167
+ "yes",
11168
+ "yolo",
11169
+ "manualDb",
11170
+ "part",
11171
+ "verbose",
11172
+ "dryRun",
11173
+ "verify",
11174
+ "versionChannel",
11175
+ "directoryConflict",
11176
+ "renderTitle",
11177
+ "disableAnalytics"
11178
+ ]);
11179
+ const CREATE_STACK_FLAG_KEYS = new Set(Object.keys(CreateCommandOptionsSchema.shape).filter((key) => !NON_STACK_CREATE_OPTION_KEYS.has(key)));
11180
+ function hasCreateStackFlags(input) {
11181
+ return Object.entries(input).some(([key, value]) => {
11182
+ if (value === void 0) return false;
11183
+ if (key === "template" && value === "none") return false;
11184
+ return CREATE_STACK_FLAG_KEYS.has(key);
11185
+ });
11186
+ }
11187
+ function shouldShowBuilderRecommendationPrompt({ input, hasConfigBase, environment = {} }) {
11188
+ if (environment.skipBuilderPrompt === "1") return false;
11189
+ if (!canPromptInteractively({
11190
+ silent: environment.silent,
11191
+ stdinIsTTY: environment.stdinIsTTY,
11192
+ stdoutIsTTY: environment.stdoutIsTTY,
11193
+ ci: environment.ci
11194
+ })) return false;
11195
+ if (input.yes || input.yolo || input.manualDb || input.dryRun || input.part?.length || hasConfigBase || input.config || input.fromHistory || input.template && input.template !== "none") return false;
11196
+ if (hasCreateStackFlags(input)) return false;
11197
+ if (environment.forceBuilderPrompt === "1") return true;
11198
+ return Boolean(environment.npmConfigUserAgent);
11199
+ }
11200
+ async function showBuilderRecommendationPrompt() {
11201
+ note(`The Web Builder walks the full stack visually — every option, live compatibility checks — and hands you back a single command to run.\n\n${BUILDER_URL}`, "Prefer a visual builder?");
11202
+ const response = await navigableSelect({
11203
+ message: "How would you like to continue?",
11204
+ options: [{
11205
+ value: "open",
11206
+ label: "Open the Web Builder",
11207
+ hint: "recommended — opens in your browser"
11208
+ }, {
11209
+ value: "continue",
11210
+ label: "Continue in the CLI"
11211
+ }],
11212
+ initialValue: "open"
11213
+ });
11214
+ if (isCancel$1(response) || isGoBack(response)) return exitCancelled("Operation cancelled");
11215
+ if (response === "open") {
11216
+ try {
11217
+ await openUrl(BUILDER_URL);
11218
+ log.success(pc.blue("Opened Web Builder in your browser."));
11219
+ } catch {
11220
+ log.message(`Please visit ${BUILDER_URL}`);
11221
+ }
11222
+ outro(pc.magenta("Web Builder is ready when you are."));
11223
+ return "opened";
11224
+ }
11225
+ return "continue";
11226
+ }
9881
11227
  function getYesBaseConfig(flagConfig) {
9882
11228
  const baseConfig = getDefaultConfig();
9883
11229
  if (flagConfig.ecosystem !== "react-native") return baseConfig;
@@ -9929,11 +11275,20 @@ function shouldPromptForVersionChannel(input, hasConfigBase) {
9929
11275
  if (input.yes || input.part?.length || hasConfigBase || input.versionChannel !== void 0 || isSilent()) return false;
9930
11276
  return canPromptInteractively();
9931
11277
  }
11278
+ function normalizeKotlinJavaSelection(config) {
11279
+ if (!config.stackParts?.some((part) => part.role === "backend" && part.ecosystem === "java" && !part.ownerPartId && part.source !== "provided") && config.ecosystem !== "java" || config.javaLanguage !== "kotlin") return;
11280
+ const kotlinBlocker = (0, types_exports.getKotlinJavaIncompatibilityReason)(config);
11281
+ if (!kotlinBlocker) return;
11282
+ config.javaLanguage = "java";
11283
+ if (config.stackParts) config.stackParts = config.stackParts.filter((part) => !(part.role === "language" && part.ecosystem === "java" && part.toolId === "kotlin" && part.source !== "provided"));
11284
+ if (!isSilent()) log.warn(pc.yellow(`JVM language set to Java: ${kotlinBlocker}`));
11285
+ }
9932
11286
  async function createProjectHandler(input, options = {}) {
9933
11287
  const { silent = false } = options;
9934
11288
  return runWithContextAsync({ silent }, async () => {
9935
11289
  const startTime = Date.now();
9936
11290
  const timeScaffolded = (/* @__PURE__ */ new Date()).toISOString();
11291
+ let telemetrySource = silent ? "programmatic" : "cli-interactive";
9937
11292
  try {
9938
11293
  if (!isSilent() && input.renderTitle !== false) renderTitle();
9939
11294
  if (!isSilent()) intro(pc.magenta("Creating a new Better Fullstack project"));
@@ -9941,6 +11296,17 @@ async function createProjectHandler(input, options = {}) {
9941
11296
  if (!isSilent() && input.yolo) consola.fatal("YOLO mode enabled - skipping checks. Things may break!");
9942
11297
  const configBase = await resolveCreateConfigBase(input);
9943
11298
  const hasConfigBase = configBase !== void 0;
11299
+ if (shouldShowBuilderRecommendationPrompt({
11300
+ input,
11301
+ hasConfigBase,
11302
+ environment: {
11303
+ npmConfigUserAgent: process.env.npm_config_user_agent,
11304
+ forceBuilderPrompt: process.env.BFS_FORCE_BUILDER_PROMPT,
11305
+ skipBuilderPrompt: process.env.BFS_SKIP_BUILDER_PROMPT
11306
+ }
11307
+ })) {
11308
+ if (await showBuilderRecommendationPrompt() === "opened") return;
11309
+ }
9944
11310
  if (hasConfigBase && !isSilent()) log.info(pc.cyan(input.config ? `Using stack from config file: ${input.config}` : `Using stack from history entry #${input.fromHistory}`));
9945
11311
  const useDefaultsForName = Boolean(input.yes) || hasConfigBase;
9946
11312
  let currentPathInput;
@@ -10153,6 +11519,7 @@ async function createProjectHandler(input, options = {}) {
10153
11519
  const { validatePreflightConfig } = await import("@better-fullstack/template-generator");
10154
11520
  let config;
10155
11521
  if (cliInput.yes || cliInput.part?.length || hasConfigBase) {
11522
+ if (!silent) telemetrySource = "cli-flags";
10156
11523
  const flagConfig = processProvidedFlagsWithoutValidation(cliInput, finalBaseName);
10157
11524
  config = {
10158
11525
  ...getYesBaseConfig(flagConfig),
@@ -10183,6 +11550,7 @@ async function createProjectHandler(input, options = {}) {
10183
11550
  };
10184
11551
  validateConfigCompatibility(config, providedFlags, cliInput);
10185
11552
  }
11553
+ normalizeKotlinJavaSelection(config);
10186
11554
  const preflight = validatePreflightConfig(config);
10187
11555
  if (preflight.hasWarnings && !isSilent()) displayPreflightWarnings(preflight);
10188
11556
  if (input.dryRun) {
@@ -10232,7 +11600,12 @@ async function createProjectHandler(input, options = {}) {
10232
11600
  if (cliInput.verify ?? input.verify) await runGeneratedChecks(config);
10233
11601
  const reproducibleCommand = generateReproducibleCommand(config);
10234
11602
  if (!isSilent()) log.success(pc.blue(`You can reproduce this setup with the following command:\n${reproducibleCommand}`));
10235
- await trackProjectCreation(config, input.disableAnalytics);
11603
+ await trackProjectCreation(config, input.disableAnalytics, {
11604
+ source: telemetrySource,
11605
+ success: true,
11606
+ setupFailures: setupFailures.map((failure) => failure.step),
11607
+ durationMs: Date.now() - startTime
11608
+ });
10236
11609
  try {
10237
11610
  await addToHistory(config, reproducibleCommand);
10238
11611
  } catch (historyError) {
@@ -10272,6 +11645,12 @@ async function createProjectHandler(input, options = {}) {
10272
11645
  };
10273
11646
  return;
10274
11647
  }
11648
+ await trackEvent("project_created", {}, {
11649
+ source: telemetrySource,
11650
+ success: false,
11651
+ errorName: error instanceof Error ? error.name : "UnknownError",
11652
+ durationMs: Date.now() - startTime
11653
+ }, input.disableAnalytics);
10275
11654
  if (error instanceof CLIError) {
10276
11655
  if (isSilent()) return {
10277
11656
  success: false,
@@ -10326,21 +11705,6 @@ async function handleDirectoryConflictProgrammatically(currentPathInput, strateg
10326
11705
  }
10327
11706
  }
10328
11707
 
10329
- //#endregion
10330
- //#region src/utils/open-url.ts
10331
- async function openUrl(url) {
10332
- const platform = process.platform;
10333
- try {
10334
- if (platform === "darwin") await $({ stdio: "ignore" })`open ${url}`;
10335
- else if (platform === "win32") {
10336
- const escapedUrl = url.replace(/&/g, "^&");
10337
- await $({ stdio: "ignore" })`cmd /c start "" ${escapedUrl}`;
10338
- } else await $({ stdio: "ignore" })`xdg-open ${url}`;
10339
- } catch {
10340
- log.message(`Please open ${url} in your browser.`);
10341
- }
10342
- }
10343
-
10344
11708
  //#endregion
10345
11709
  //#region src/utils/sponsors.ts
10346
11710
  const SPONSORS_JSON_URL = "https://better-fullstack-web.vercel.app/sponsors.json";
@@ -10439,7 +11803,6 @@ const router = os.router({
10439
11803
  }
10440
11804
  }),
10441
11805
  builder: os.meta({ description: "Open the interactive web-based stack builder at better-fullstack.dev" }).handler(async () => {
10442
- const BUILDER_URL = "https://better-fullstack-web.vercel.app/new";
10443
11806
  try {
10444
11807
  await openUrl(BUILDER_URL);
10445
11808
  log.success(pc.blue("Opened builder in your default browser."));
@@ -10448,7 +11811,7 @@ const router = os.router({
10448
11811
  }
10449
11812
  }),
10450
11813
  add: os.meta({ description: "Add addons, deploy targets, or stack capabilities to an existing Better Fullstack project using its bts.jsonc config" }).input(AddCommandInputSchema).handler(async ({ input }) => {
10451
- const { addHandler } = await import("./add-handler-CuPmSJRM.mjs");
11814
+ const { addHandler } = await import("./add-handler-ztNjzoMN.mjs");
10452
11815
  await addHandler(input);
10453
11816
  }),
10454
11817
  history: os.meta({ description: "Show history of scaffolded projects with reproducible commands" }).input(z.object({
@@ -10476,7 +11839,7 @@ const router = os.router({
10476
11839
  ecosystem: z.string().optional().describe("Filter by ecosystem (effect, tanstack, prisma, etc.)"),
10477
11840
  "list-ecosystems": z.boolean().default(false).describe("List available ecosystems")
10478
11841
  })).handler(async ({ input }) => {
10479
- const { updateDepsHandler, showEcosystems } = await import("./update-deps-DLZAuT3V.mjs");
11842
+ const { updateDepsHandler, showEcosystems } = await import("./update-deps-aD-iQw4U.mjs");
10480
11843
  if (input["list-ecosystems"]) {
10481
11844
  showEcosystems();
10482
11845
  return;
@@ -10497,7 +11860,7 @@ const router = os.router({
10497
11860
  })
10498
11861
  ])).handler(async ({ input }) => {
10499
11862
  const [kind, name, options] = input;
10500
- const { genCommand } = await import("./gen-DWx3Xu_K.mjs");
11863
+ const { genCommand } = await import("./gen-CCClL7Ve.mjs");
10501
11864
  await genCommand({
10502
11865
  kind,
10503
11866
  name,
@@ -10515,7 +11878,7 @@ const router = os.router({
10515
11878
  })
10516
11879
  ])).handler(async ({ input }) => {
10517
11880
  const [action, source, options] = input;
10518
- const { registryHandler } = await import("./registry-CxeEOPot.mjs");
11881
+ const { registryHandler } = await import("./registry-DSf2CEaU.mjs");
10519
11882
  await registryHandler({
10520
11883
  action,
10521
11884
  source,
@@ -10532,7 +11895,7 @@ const router = os.router({
10532
11895
  recordBaseline: z.boolean().optional().default(false).describe("Adopt the current on-disk state as the scaffold baseline (for projects created before the update engine)")
10533
11896
  })])).handler(async ({ input }) => {
10534
11897
  const [projectDir, options] = input;
10535
- const { updateCommand } = await import("./update-C9_x2yBF.mjs");
11898
+ const { updateCommand } = await import("./update-DJ8CI5KW.mjs");
10536
11899
  await updateCommand({
10537
11900
  projectDir,
10538
11901
  ...options
@@ -10544,7 +11907,7 @@ const router = os.router({
10544
11907
  }),
10545
11908
  doctor: os.meta({ description: "Diagnose a scaffolded Better Fullstack project: verify its bts.jsonc, installed dependencies, required env vars, and run ecosystem build/type checks" }).input(ProjectCheckInputSchema).handler(async ({ input }) => {
10546
11909
  const [projectDir, options] = input;
10547
- const { doctorCommand } = await import("./doctor-DucDyWfl.mjs");
11910
+ const { doctorCommand } = await import("./doctor-a4ca3SMd.mjs");
10548
11911
  await doctorCommand({
10549
11912
  projectDir,
10550
11913
  ...options
@@ -10552,7 +11915,7 @@ const router = os.router({
10552
11915
  }),
10553
11916
  check: os.meta({ description: "Check a scaffolded Better Fullstack project for config, dependency, env, and generated build/type drift" }).input(ProjectCheckInputSchema).handler(async ({ input }) => {
10554
11917
  const [projectDir, options] = input;
10555
- const { doctorCommand } = await import("./doctor-DucDyWfl.mjs");
11918
+ const { doctorCommand } = await import("./doctor-a4ca3SMd.mjs");
10556
11919
  await doctorCommand({
10557
11920
  projectDir,
10558
11921
  ...options
@@ -10563,7 +11926,7 @@ const router = os.router({
10563
11926
  ecosystem: z.string().optional().describe("Force an ecosystem (typescript, react-native, rust, go, python, java, ...)"),
10564
11927
  json: z.boolean().default(false).describe("Output the recommendation as JSON")
10565
11928
  })).handler(async ({ input }) => {
10566
- const { recommendStackFromBrief } = await import("./mcp-D9O5zgAA.mjs");
11929
+ const { recommendStackFromBrief } = await import("./mcp-492OkjcS.mjs");
10567
11930
  const result = recommendStackFromBrief(input.brief, input.ecosystem);
10568
11931
  if (input.json) {
10569
11932
  log.message(JSON.stringify(result, null, 2));
@@ -10638,9 +12001,12 @@ async function docs() {
10638
12001
  async function builder() {
10639
12002
  return caller.builder();
10640
12003
  }
10641
- async function add(input) {
10642
- const { addHandler } = await import("./add-handler-CuPmSJRM.mjs");
10643
- return addHandler(input, { silent: true });
12004
+ async function add(input, options) {
12005
+ const { addHandler } = await import("./add-handler-ztNjzoMN.mjs");
12006
+ return addHandler(input, {
12007
+ silent: true,
12008
+ telemetrySource: options?.telemetrySource ?? "programmatic"
12009
+ });
10644
12010
  }
10645
12011
  async function history(options) {
10646
12012
  return caller.history({