create-better-fullstack 2.1.6 → 2.1.7

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-D80ZtSO8.mjs → run-D9I7NdES.mjs} +1760 -416
  20. package/dist/run-buK4aZS8.mjs +15 -0
  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);
@@ -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,6 +6015,7 @@ async function gatherMultiEcosystemConfig(flags, projectName, projectDir, relati
5612
6015
  }
5613
6016
  if (backendEcosystem === "java") {
5614
6017
  const javaWebFramework = promptValue(await getJavaWebFrameworkChoice(flags.javaWebFramework));
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));
5615
6019
  const javaBuildTool = promptValue(await getJavaBuildToolChoice(flags.javaBuildTool));
5616
6020
  if (javaWebFramework !== "none" && javaBuildTool !== "none") {
5617
6021
  const databaseConfig = await selectDatabaseConfig(flags);
@@ -5620,11 +6024,12 @@ async function gatherMultiEcosystemConfig(flags, projectName, projectDir, relati
5620
6024
  }
5621
6025
  const javaOrm = database === "none" || javaWebFramework !== "spring-boot" || javaBuildTool === "none" ? "none" : promptValue(await getJavaOrmChoice(flags.javaOrm));
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));
6027
+ const javaLibraries = javaWebFramework !== "spring-boot" || javaBuildTool === "none" ? [] : await scopedPromptValue("java", "javaLibraries", configScope, backendSections, () => getJavaLibrariesChoice(flags.javaLibraries));
6028
+ const javaTestingLibraries = await scopedPromptValue("java", "javaTestingLibraries", configScope, backendSections, () => getJavaTestingLibrariesChoice(flags.javaTestingLibraries));
5625
6029
  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));
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([]);
@@ -7253,7 +8512,7 @@ async function gatherConfig(flags, projectName, projectDir, relativePath) {
7253
8512
  return getPackageManagerChoice(flags.packageManager);
7254
8513
  },
7255
8514
  install: ({ results }) => getinstallChoice(flags.install, results.ecosystem, results.javaBuildTool)
7256
- }, { onCancel: () => exitCancelled("Operation cancelled") });
8515
+ }).map(([key, prompt]) => [key, scopedPrompt(key, flags, prompt)])), { onCancel: () => exitCancelled("Operation cancelled") });
7257
8516
  return {
7258
8517
  projectName,
7259
8518
  projectDir,
@@ -7789,6 +9048,17 @@ async function setupProjectDirectory(finalPathInput, shouldClearDirectory) {
7789
9048
  };
7790
9049
  }
7791
9050
 
9051
+ //#endregion
9052
+ //#region src/utils/open-url.ts
9053
+ async function openUrl(url) {
9054
+ const platform = process.platform;
9055
+ if (platform === "darwin") await $({ stdio: "ignore" })`open ${url}`;
9056
+ else if (platform === "win32") {
9057
+ const escapedUrl = url.replace(/&/g, "^&");
9058
+ await $({ stdio: "ignore" })`cmd /c start "" ${escapedUrl}`;
9059
+ } else await $({ stdio: "ignore" })`xdg-open ${url}`;
9060
+ }
9061
+
7792
9062
  //#endregion
7793
9063
  //#region src/validation.ts
7794
9064
  const CORE_STACK_FLAGS = new Set([
@@ -9830,11 +11100,10 @@ async function createProject(options, cliInput = {}) {
9830
11100
  await rollbackPartialProject(projectDir, dirHadContentBefore);
9831
11101
  if (error instanceof Error) {
9832
11102
  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)}`);
11103
+ throw new CLIError(`Error during project creation: ${error.message}`);
9837
11104
  }
11105
+ if (!isSilent()) console.error(error);
11106
+ throw new CLIError(`An unexpected error occurred: ${String(error)}`);
9838
11107
  }
9839
11108
  }
9840
11109
  /**
@@ -9878,6 +11147,70 @@ async function ensurePackageManagerProjectFiles(projectDir, packageManager) {
9878
11147
 
9879
11148
  //#endregion
9880
11149
  //#region src/helpers/core/command-handlers.ts
11150
+ const NON_STACK_CREATE_OPTION_KEYS = new Set([
11151
+ "template",
11152
+ "fromHistory",
11153
+ "config",
11154
+ "yes",
11155
+ "yolo",
11156
+ "manualDb",
11157
+ "part",
11158
+ "verbose",
11159
+ "dryRun",
11160
+ "verify",
11161
+ "versionChannel",
11162
+ "directoryConflict",
11163
+ "renderTitle",
11164
+ "disableAnalytics"
11165
+ ]);
11166
+ const CREATE_STACK_FLAG_KEYS = new Set(Object.keys(CreateCommandOptionsSchema.shape).filter((key) => !NON_STACK_CREATE_OPTION_KEYS.has(key)));
11167
+ function hasCreateStackFlags(input) {
11168
+ return Object.entries(input).some(([key, value]) => {
11169
+ if (value === void 0) return false;
11170
+ if (key === "template" && value === "none") return false;
11171
+ return CREATE_STACK_FLAG_KEYS.has(key);
11172
+ });
11173
+ }
11174
+ function shouldShowBuilderRecommendationPrompt({ input, hasConfigBase, environment = {} }) {
11175
+ if (environment.skipBuilderPrompt === "1") return false;
11176
+ if (!canPromptInteractively({
11177
+ silent: environment.silent,
11178
+ stdinIsTTY: environment.stdinIsTTY,
11179
+ stdoutIsTTY: environment.stdoutIsTTY,
11180
+ ci: environment.ci
11181
+ })) return false;
11182
+ if (input.yes || input.yolo || input.manualDb || input.dryRun || input.part?.length || hasConfigBase || input.config || input.fromHistory || input.template && input.template !== "none") return false;
11183
+ if (hasCreateStackFlags(input)) return false;
11184
+ if (environment.forceBuilderPrompt === "1") return true;
11185
+ return Boolean(environment.npmConfigUserAgent);
11186
+ }
11187
+ async function showBuilderRecommendationPrompt() {
11188
+ 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?");
11189
+ const response = await navigableSelect({
11190
+ message: "How would you like to continue?",
11191
+ options: [{
11192
+ value: "open",
11193
+ label: "Open the Web Builder",
11194
+ hint: "recommended — opens in your browser"
11195
+ }, {
11196
+ value: "continue",
11197
+ label: "Continue in the CLI"
11198
+ }],
11199
+ initialValue: "open"
11200
+ });
11201
+ if (isCancel$1(response) || isGoBack(response)) return exitCancelled("Operation cancelled");
11202
+ if (response === "open") {
11203
+ try {
11204
+ await openUrl(BUILDER_URL);
11205
+ log.success(pc.blue("Opened Web Builder in your browser."));
11206
+ } catch {
11207
+ log.message(`Please visit ${BUILDER_URL}`);
11208
+ }
11209
+ outro(pc.magenta("Web Builder is ready when you are."));
11210
+ return "opened";
11211
+ }
11212
+ return "continue";
11213
+ }
9881
11214
  function getYesBaseConfig(flagConfig) {
9882
11215
  const baseConfig = getDefaultConfig();
9883
11216
  if (flagConfig.ecosystem !== "react-native") return baseConfig;
@@ -9934,6 +11267,7 @@ async function createProjectHandler(input, options = {}) {
9934
11267
  return runWithContextAsync({ silent }, async () => {
9935
11268
  const startTime = Date.now();
9936
11269
  const timeScaffolded = (/* @__PURE__ */ new Date()).toISOString();
11270
+ let telemetrySource = silent ? "programmatic" : "cli-interactive";
9937
11271
  try {
9938
11272
  if (!isSilent() && input.renderTitle !== false) renderTitle();
9939
11273
  if (!isSilent()) intro(pc.magenta("Creating a new Better Fullstack project"));
@@ -9941,6 +11275,17 @@ async function createProjectHandler(input, options = {}) {
9941
11275
  if (!isSilent() && input.yolo) consola.fatal("YOLO mode enabled - skipping checks. Things may break!");
9942
11276
  const configBase = await resolveCreateConfigBase(input);
9943
11277
  const hasConfigBase = configBase !== void 0;
11278
+ if (shouldShowBuilderRecommendationPrompt({
11279
+ input,
11280
+ hasConfigBase,
11281
+ environment: {
11282
+ npmConfigUserAgent: process.env.npm_config_user_agent,
11283
+ forceBuilderPrompt: process.env.BFS_FORCE_BUILDER_PROMPT,
11284
+ skipBuilderPrompt: process.env.BFS_SKIP_BUILDER_PROMPT
11285
+ }
11286
+ })) {
11287
+ if (await showBuilderRecommendationPrompt() === "opened") return;
11288
+ }
9944
11289
  if (hasConfigBase && !isSilent()) log.info(pc.cyan(input.config ? `Using stack from config file: ${input.config}` : `Using stack from history entry #${input.fromHistory}`));
9945
11290
  const useDefaultsForName = Boolean(input.yes) || hasConfigBase;
9946
11291
  let currentPathInput;
@@ -10153,6 +11498,7 @@ async function createProjectHandler(input, options = {}) {
10153
11498
  const { validatePreflightConfig } = await import("@better-fullstack/template-generator");
10154
11499
  let config;
10155
11500
  if (cliInput.yes || cliInput.part?.length || hasConfigBase) {
11501
+ if (!silent) telemetrySource = "cli-flags";
10156
11502
  const flagConfig = processProvidedFlagsWithoutValidation(cliInput, finalBaseName);
10157
11503
  config = {
10158
11504
  ...getYesBaseConfig(flagConfig),
@@ -10232,7 +11578,12 @@ async function createProjectHandler(input, options = {}) {
10232
11578
  if (cliInput.verify ?? input.verify) await runGeneratedChecks(config);
10233
11579
  const reproducibleCommand = generateReproducibleCommand(config);
10234
11580
  if (!isSilent()) log.success(pc.blue(`You can reproduce this setup with the following command:\n${reproducibleCommand}`));
10235
- await trackProjectCreation(config, input.disableAnalytics);
11581
+ await trackProjectCreation(config, input.disableAnalytics, {
11582
+ source: telemetrySource,
11583
+ success: true,
11584
+ setupFailures: setupFailures.map((failure) => failure.step),
11585
+ durationMs: Date.now() - startTime
11586
+ });
10236
11587
  try {
10237
11588
  await addToHistory(config, reproducibleCommand);
10238
11589
  } catch (historyError) {
@@ -10272,6 +11623,12 @@ async function createProjectHandler(input, options = {}) {
10272
11623
  };
10273
11624
  return;
10274
11625
  }
11626
+ await trackEvent("project_created", {}, {
11627
+ source: telemetrySource,
11628
+ success: false,
11629
+ errorName: error instanceof Error ? error.name : "UnknownError",
11630
+ durationMs: Date.now() - startTime
11631
+ }, input.disableAnalytics);
10275
11632
  if (error instanceof CLIError) {
10276
11633
  if (isSilent()) return {
10277
11634
  success: false,
@@ -10326,21 +11683,6 @@ async function handleDirectoryConflictProgrammatically(currentPathInput, strateg
10326
11683
  }
10327
11684
  }
10328
11685
 
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
11686
  //#endregion
10345
11687
  //#region src/utils/sponsors.ts
10346
11688
  const SPONSORS_JSON_URL = "https://better-fullstack-web.vercel.app/sponsors.json";
@@ -10439,7 +11781,6 @@ const router = os.router({
10439
11781
  }
10440
11782
  }),
10441
11783
  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
11784
  try {
10444
11785
  await openUrl(BUILDER_URL);
10445
11786
  log.success(pc.blue("Opened builder in your default browser."));
@@ -10448,7 +11789,7 @@ const router = os.router({
10448
11789
  }
10449
11790
  }),
10450
11791
  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");
11792
+ const { addHandler } = await import("./add-handler-ztNjzoMN.mjs");
10452
11793
  await addHandler(input);
10453
11794
  }),
10454
11795
  history: os.meta({ description: "Show history of scaffolded projects with reproducible commands" }).input(z.object({
@@ -10476,7 +11817,7 @@ const router = os.router({
10476
11817
  ecosystem: z.string().optional().describe("Filter by ecosystem (effect, tanstack, prisma, etc.)"),
10477
11818
  "list-ecosystems": z.boolean().default(false).describe("List available ecosystems")
10478
11819
  })).handler(async ({ input }) => {
10479
- const { updateDepsHandler, showEcosystems } = await import("./update-deps-DLZAuT3V.mjs");
11820
+ const { updateDepsHandler, showEcosystems } = await import("./update-deps-aD-iQw4U.mjs");
10480
11821
  if (input["list-ecosystems"]) {
10481
11822
  showEcosystems();
10482
11823
  return;
@@ -10497,7 +11838,7 @@ const router = os.router({
10497
11838
  })
10498
11839
  ])).handler(async ({ input }) => {
10499
11840
  const [kind, name, options] = input;
10500
- const { genCommand } = await import("./gen-DWx3Xu_K.mjs");
11841
+ const { genCommand } = await import("./gen-CCClL7Ve.mjs");
10501
11842
  await genCommand({
10502
11843
  kind,
10503
11844
  name,
@@ -10515,7 +11856,7 @@ const router = os.router({
10515
11856
  })
10516
11857
  ])).handler(async ({ input }) => {
10517
11858
  const [action, source, options] = input;
10518
- const { registryHandler } = await import("./registry-CxeEOPot.mjs");
11859
+ const { registryHandler } = await import("./registry-DSf2CEaU.mjs");
10519
11860
  await registryHandler({
10520
11861
  action,
10521
11862
  source,
@@ -10532,7 +11873,7 @@ const router = os.router({
10532
11873
  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
11874
  })])).handler(async ({ input }) => {
10534
11875
  const [projectDir, options] = input;
10535
- const { updateCommand } = await import("./update-C9_x2yBF.mjs");
11876
+ const { updateCommand } = await import("./update-DJ8CI5KW.mjs");
10536
11877
  await updateCommand({
10537
11878
  projectDir,
10538
11879
  ...options
@@ -10544,7 +11885,7 @@ const router = os.router({
10544
11885
  }),
10545
11886
  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
11887
  const [projectDir, options] = input;
10547
- const { doctorCommand } = await import("./doctor-DucDyWfl.mjs");
11888
+ const { doctorCommand } = await import("./doctor-a4ca3SMd.mjs");
10548
11889
  await doctorCommand({
10549
11890
  projectDir,
10550
11891
  ...options
@@ -10552,7 +11893,7 @@ const router = os.router({
10552
11893
  }),
10553
11894
  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
11895
  const [projectDir, options] = input;
10555
- const { doctorCommand } = await import("./doctor-DucDyWfl.mjs");
11896
+ const { doctorCommand } = await import("./doctor-a4ca3SMd.mjs");
10556
11897
  await doctorCommand({
10557
11898
  projectDir,
10558
11899
  ...options
@@ -10563,7 +11904,7 @@ const router = os.router({
10563
11904
  ecosystem: z.string().optional().describe("Force an ecosystem (typescript, react-native, rust, go, python, java, ...)"),
10564
11905
  json: z.boolean().default(false).describe("Output the recommendation as JSON")
10565
11906
  })).handler(async ({ input }) => {
10566
- const { recommendStackFromBrief } = await import("./mcp-D9O5zgAA.mjs");
11907
+ const { recommendStackFromBrief } = await import("./mcp-492OkjcS.mjs");
10567
11908
  const result = recommendStackFromBrief(input.brief, input.ecosystem);
10568
11909
  if (input.json) {
10569
11910
  log.message(JSON.stringify(result, null, 2));
@@ -10638,9 +11979,12 @@ async function docs() {
10638
11979
  async function builder() {
10639
11980
  return caller.builder();
10640
11981
  }
10641
- async function add(input) {
10642
- const { addHandler } = await import("./add-handler-CuPmSJRM.mjs");
10643
- return addHandler(input, { silent: true });
11982
+ async function add(input, options) {
11983
+ const { addHandler } = await import("./add-handler-ztNjzoMN.mjs");
11984
+ return addHandler(input, {
11985
+ silent: true,
11986
+ telemetrySource: options?.telemetrySource ?? "programmatic"
11987
+ });
10644
11988
  }
10645
11989
  async function history(options) {
10646
11990
  return caller.history({