create-better-fullstack 2.1.6 → 2.1.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (28) hide show
  1. package/dist/{add-handler-CuPmSJRM.mjs → add-handler-ztNjzoMN.mjs} +43 -5
  2. package/dist/addons-setup-DnLjAzTw.mjs +7 -0
  3. package/dist/{addons-setup-C_lxdJqU.mjs → addons-setup-LaAj43NP.mjs} +3 -24
  4. package/dist/analytics-DVltG11u.mjs +170 -0
  5. package/dist/{bts-config-BceXPcpI.mjs → bts-config-DQVWvPDs.mjs} +70 -66
  6. package/dist/cli.mjs +2 -2
  7. package/dist/{config-processing-B_1wTe3g.mjs → config-processing-D9-F2Us9.mjs} +1 -1
  8. package/dist/{doctor-DucDyWfl.mjs → doctor-a4ca3SMd.mjs} +2 -2
  9. package/dist/{file-formatter-XU6ti05V.mjs → file-formatter-gvmrpd-g.mjs} +13 -1
  10. package/dist/{gen-DWx3Xu_K.mjs → gen-CCClL7Ve.mjs} +1 -1
  11. package/dist/{generated-checks-Dt4Xqp1x.mjs → generated-checks-BV9jol5h.mjs} +1 -1
  12. package/dist/index.d.mts +27 -21
  13. package/dist/index.mjs +10 -8
  14. package/dist/{install-dependencies-DHoYa3P-.mjs → install-dependencies-RoUyaE8o.mjs} +7 -2
  15. package/dist/mcp-492OkjcS.mjs +11 -0
  16. package/dist/mcp-entry.mjs +56 -18
  17. package/dist/prompt-environment-BR0Kkw2W.mjs +26 -0
  18. package/dist/{registry-CxeEOPot.mjs → registry-DSf2CEaU.mjs} +27 -13
  19. package/dist/run-CD8f7PHh.mjs +15 -0
  20. package/dist/{run-D80ZtSO8.mjs → run-T6g1jkfy.mjs} +1810 -444
  21. package/dist/scaffold-manifest-DGRyepdb.mjs +4 -0
  22. package/dist/{scaffold-manifest-GV1fbhpD.mjs → scaffold-manifest-Dyi0voqE.mjs} +13 -1
  23. package/dist/{update-C9_x2yBF.mjs → update-DJ8CI5KW.mjs} +3 -3
  24. package/package.json +3 -3
  25. package/dist/addons-setup-DEPfsn6z.mjs +0 -6
  26. package/dist/mcp-D9O5zgAA.mjs +0 -8
  27. package/dist/run-3AkXloH1.mjs +0 -13
  28. /package/dist/{update-deps-DLZAuT3V.mjs → update-deps-aD-iQw4U.mjs} +0 -0
@@ -1,10 +1,13 @@
1
1
  #!/usr/bin/env node
2
- import { a as updateBtsConfig, r as readBtsConfig, u as getDefaultConfig } from "./bts-config-BceXPcpI.mjs";
2
+ import { a as updateBtsConfig, r as readBtsConfig, v as getDefaultConfig } from "./bts-config-DQVWvPDs.mjs";
3
3
  import { t as renderTitle } from "./render-title-zvyKC1ej.mjs";
4
4
  import { c as isSilent, l as runWithContextAsync, n as UserCancelledError, t as CLIError } from "./errors-ns_o2OKg.mjs";
5
- import { t as setupAddons } from "./addons-setup-C_lxdJqU.mjs";
6
- import "./file-formatter-XU6ti05V.mjs";
7
- import { c as applyDependencyVersionChannel, t as installDependencies, u as getAddonsToAdd } from "./install-dependencies-DHoYa3P-.mjs";
5
+ import "./prompt-environment-BR0Kkw2W.mjs";
6
+ import { i as trackEvent, r as maybeShowTelemetryNotice } from "./analytics-DVltG11u.mjs";
7
+ import "./file-formatter-gvmrpd-g.mjs";
8
+ import { c as applyDependencyVersionChannel, t as installDependencies, u as getAddonsToAdd } from "./install-dependencies-RoUyaE8o.mjs";
9
+ import "./scaffold-manifest-Dyi0voqE.mjs";
10
+ import { t as setupAddons } from "./addons-setup-LaAj43NP.mjs";
8
11
  import { o as applyStackUpdate, u as planStackUpdate } from "./mcp-entry.mjs";
9
12
  import { intro, log, outro } from "@clack/prompts";
10
13
  import pc from "picocolors";
@@ -124,12 +127,47 @@ async function runStackUpdateAdd(input, projectDir, projectName, currentConfig,
124
127
  setupWarnings: setupWarnings.length > 0 ? setupWarnings : void 0
125
128
  };
126
129
  }
130
+ const ADD_FEATURE_KEYS = new Set([
131
+ "addons",
132
+ "webDeploy",
133
+ "serverDeploy",
134
+ "packageManager"
135
+ ]);
136
+ async function trackAddEvent(input, options, outcome) {
137
+ if (input.dryRun) return;
138
+ const request = buildStackUpdateRequest(input);
139
+ const stackPayload = { ...request };
140
+ if (outcome.addedAddons !== void 0) if (outcome.addedAddons.length > 0) stackPayload.addons = outcome.addedAddons;
141
+ else delete stackPayload.addons;
142
+ await trackEvent(Object.keys(request).some((key) => !ADD_FEATURE_KEYS.has(key)) ? "stack_updated" : "feature_added", stackPayload, {
143
+ source: options.telemetrySource ?? (options.silent ? "programmatic" : Object.keys(request).length > 0 ? "cli-flags" : "cli-interactive"),
144
+ success: outcome.success,
145
+ errorName: outcome.errorName,
146
+ durationMs: outcome.durationMs
147
+ });
148
+ }
127
149
  async function addHandler(input, options = {}) {
128
150
  const { silent = false } = options;
151
+ const startTime = Date.now();
129
152
  return runWithContextAsync({ silent }, async () => {
130
153
  try {
131
- return await addHandlerInternal(input);
154
+ const result = await addHandlerInternal(input);
155
+ await maybeShowTelemetryNotice();
156
+ await trackAddEvent(input, options, {
157
+ success: result.success,
158
+ durationMs: Date.now() - startTime,
159
+ addedAddons: result.addedAddons
160
+ });
161
+ return result;
132
162
  } catch (error) {
163
+ if (!(error instanceof UserCancelledError)) {
164
+ await maybeShowTelemetryNotice();
165
+ await trackAddEvent(input, options, {
166
+ success: false,
167
+ errorName: error instanceof Error ? error.name : "UnknownError",
168
+ durationMs: Date.now() - startTime
169
+ });
170
+ }
133
171
  if (error instanceof UserCancelledError) {
134
172
  if (isSilent()) return {
135
173
  success: false,
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env node
2
+ import "./bts-config-DQVWvPDs.mjs";
3
+ import "./errors-ns_o2OKg.mjs";
4
+ import "./prompt-environment-BR0Kkw2W.mjs";
5
+ import { t as setupAddons } from "./addons-setup-LaAj43NP.mjs";
6
+
7
+ export { setupAddons };
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env node
2
- import { r as readBtsConfig } from "./bts-config-BceXPcpI.mjs";
2
+ import { r as readBtsConfig } from "./bts-config-DQVWvPDs.mjs";
3
3
  import { c as isSilent, r as exitCancelled } from "./errors-ns_o2OKg.mjs";
4
+ import { t as canPromptInteractively } from "./prompt-environment-BR0Kkw2W.mjs";
4
5
  import { autocompleteMultiselect, group, isCancel, log, multiselect, select, spinner } from "@clack/prompts";
5
6
  import pc from "picocolors";
6
7
  import fs from "fs-extra";
@@ -8,28 +9,6 @@ import path from "node:path";
8
9
  import consola from "consola";
9
10
  import { $ } from "execa";
10
11
 
11
- //#region src/utils/prompt-environment.ts
12
- function hasOwnProperty(value, property) {
13
- return Object.prototype.hasOwnProperty.call(value, property);
14
- }
15
- function resolveCiValue(environment) {
16
- if (environment && hasOwnProperty(environment, "ci")) return environment.ci;
17
- return process.env.CI;
18
- }
19
- function isCiEnvironment(value) {
20
- if (!value) return false;
21
- const normalizedValue = value.trim().toLowerCase();
22
- return normalizedValue !== "" && normalizedValue !== "0" && normalizedValue !== "false";
23
- }
24
- function canPromptInteractively(environment = {}) {
25
- const silent = environment.silent ?? isSilent();
26
- const stdinIsTTY = environment.stdinIsTTY ?? process.stdin.isTTY === true;
27
- const stdoutIsTTY = environment.stdoutIsTTY ?? process.stdout.isTTY === true;
28
- const ci = resolveCiValue(environment);
29
- return !silent && stdinIsTTY && stdoutIsTTY && !isCiEnvironment(ci);
30
- }
31
-
32
- //#endregion
33
12
  //#region src/utils/add-package-deps.ts
34
13
  const addPackageDependency = async (opts) => {
35
14
  const { dependencies = [], devDependencies = [], customDependencies = {}, customDevDependencies = {}, projectDir } = opts;
@@ -1339,4 +1318,4 @@ async function setupLefthook(projectDir) {
1339
1318
  }
1340
1319
 
1341
1320
  //#endregion
1342
- export { canPromptInteractively as i, getPackageExecutionArgs as n, addPackageDependency as r, setupAddons as t };
1321
+ export { getPackageExecutionArgs as n, addPackageDependency as r, setupAddons as t };
@@ -0,0 +1,170 @@
1
+ #!/usr/bin/env node
2
+ import { m as getLatestCLIVersion } from "./bts-config-DQVWvPDs.mjs";
3
+ import { t as canPromptInteractively } from "./prompt-environment-BR0Kkw2W.mjs";
4
+ import { log } from "@clack/prompts";
5
+ import pc from "picocolors";
6
+ import envPaths from "env-paths";
7
+ import fs from "fs-extra";
8
+ import path from "node:path";
9
+ import { randomUUID } from "node:crypto";
10
+
11
+ //#region src/utils/telemetry-settings.ts
12
+ const paths = envPaths("better-fullstack", { suffix: "" });
13
+ const SETTINGS_FILE = "telemetry.json";
14
+ function getSettingsPath() {
15
+ return path.join(paths.data, SETTINGS_FILE);
16
+ }
17
+ function emptySettings() {
18
+ return {
19
+ version: 1,
20
+ noticeShown: false
21
+ };
22
+ }
23
+ async function readTelemetrySettings() {
24
+ const settingsPath = getSettingsPath();
25
+ if (!await fs.pathExists(settingsPath)) return emptySettings();
26
+ try {
27
+ const data = await fs.readJson(settingsPath);
28
+ if (!data || typeof data !== "object") return emptySettings();
29
+ return {
30
+ version: typeof data.version === "number" ? data.version : 1,
31
+ enabled: typeof data.enabled === "boolean" ? data.enabled : void 0,
32
+ noticeShown: data.noticeShown === true,
33
+ machineId: typeof data.machineId === "string" ? data.machineId : void 0
34
+ };
35
+ } catch {
36
+ return emptySettings();
37
+ }
38
+ }
39
+ async function writeTelemetrySettings(settings) {
40
+ await fs.ensureDir(paths.data);
41
+ await fs.writeJson(getSettingsPath(), settings, { spaces: 2 });
42
+ }
43
+ /**
44
+ * The user's explicit persisted preference, or `undefined` when they never chose.
45
+ */
46
+ async function getPersistedTelemetryPreference() {
47
+ return (await readTelemetrySettings()).enabled;
48
+ }
49
+ /**
50
+ * Persist an explicit opt-in/opt-out. Choosing a preference also marks the
51
+ * first-run notice as shown so it never appears afterwards.
52
+ */
53
+ async function setTelemetryPreference(enabled) {
54
+ const settings = await readTelemetrySettings();
55
+ settings.enabled = enabled;
56
+ settings.noticeShown = true;
57
+ await writeTelemetrySettings(settings);
58
+ }
59
+ async function hasTelemetryNoticeBeenShown() {
60
+ return (await readTelemetrySettings()).noticeShown;
61
+ }
62
+ async function markTelemetryNoticeShown() {
63
+ const settings = await readTelemetrySettings();
64
+ settings.noticeShown = true;
65
+ await writeTelemetrySettings(settings);
66
+ }
67
+ /**
68
+ * The persisted anonymous machine ID, created on first use. Returns
69
+ * `undefined` if it cannot be persisted (telemetry then simply omits it).
70
+ */
71
+ async function getOrCreateMachineId() {
72
+ try {
73
+ const settings = await readTelemetrySettings();
74
+ if (settings.machineId) return settings.machineId;
75
+ settings.machineId = randomUUID();
76
+ await writeTelemetrySettings(settings);
77
+ return settings.machineId;
78
+ } catch {
79
+ return;
80
+ }
81
+ }
82
+
83
+ //#endregion
84
+ //#region src/utils/analytics.ts
85
+ const CONVEX_INGEST_URL = "https://curious-elephant-653.convex.site/api/analytics/ingest";
86
+ /**
87
+ * Whether telemetry is explicitly overridden at runtime.
88
+ *
89
+ * Only `BTS_TELEMETRY_DISABLED` is a runtime override: `BTS_TELEMETRY` is inlined
90
+ * by the bundler at build time (see tsdown.config.ts) and therefore acts as a
91
+ * build-time default, not a runtime switch.
92
+ */
93
+ function hasTelemetryEnvOverride() {
94
+ return process.env.BTS_TELEMETRY_DISABLED !== void 0;
95
+ }
96
+ /**
97
+ * Resolve whether telemetry is enabled.
98
+ *
99
+ * Precedence: runtime env override (`BTS_TELEMETRY_DISABLED`) > persisted
100
+ * preference > default. The default honors the build-time `BTS_TELEMETRY` flag
101
+ * (inlined by the bundler, "0" by default) and falls back to enabled when the
102
+ * flag is unset (e.g. running from source).
103
+ *
104
+ * `BTS_TELEMETRY` is intentionally evaluated last: the bundler replaces it with
105
+ * a literal, so an early `!== undefined` check would always short-circuit and
106
+ * make the persisted preference unreachable in the shipped CLI.
107
+ */
108
+ async function isTelemetryEnabled() {
109
+ const disabled = process.env.BTS_TELEMETRY_DISABLED;
110
+ if (disabled !== void 0) return disabled !== "1";
111
+ const persisted = await getPersistedTelemetryPreference();
112
+ if (persisted !== void 0) return persisted;
113
+ const buildDefault = "1";
114
+ return buildDefault === void 0 ? true : buildDefault === "1";
115
+ }
116
+ /**
117
+ * Print a one-time notice describing the anonymous telemetry the CLI collects
118
+ * and how to opt out, then remember that it was shown so it never repeats.
119
+ *
120
+ * No-ops when telemetry is explicitly configured via env var, when a persisted
121
+ * preference already exists, when the notice was already shown, when telemetry
122
+ * is disabled by the build default, or when the CLI is not running interactively
123
+ * (CI / silent / non-TTY).
124
+ */
125
+ async function maybeShowTelemetryNotice() {
126
+ if (hasTelemetryEnvOverride()) return;
127
+ if (!canPromptInteractively()) return;
128
+ if (await getPersistedTelemetryPreference() !== void 0) return;
129
+ if (await hasTelemetryNoticeBeenShown()) return;
130
+ if (!await isTelemetryEnabled()) return;
131
+ 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("scaffold outcome (success, duration), CLI version, Node.js version, OS")}\n${pc.dim("platform, and a random anonymous install ID — never project names, file")}\n${pc.dim("paths, or any personal data.")}\nOpt out anytime with ${pc.cyan("create-better-fullstack telemetry disable")} or ${pc.cyan("BTS_TELEMETRY_DISABLED=1")}.`);
132
+ try {
133
+ await markTelemetryNoticeShown();
134
+ } catch {}
135
+ }
136
+ async function sendConvexEvent(payload) {
137
+ try {
138
+ await fetch(CONVEX_INGEST_URL, {
139
+ method: "POST",
140
+ headers: { "Content-Type": "application/json" },
141
+ body: JSON.stringify(payload)
142
+ });
143
+ } catch {}
144
+ }
145
+ /**
146
+ * Send one telemetry event. `config` may be a full ProjectConfig or any
147
+ * partial stack snapshot (e.g. the parts added by `add`); PII-ish fields
148
+ * are always stripped before sending.
149
+ */
150
+ async function trackEvent(eventType, config, outcome = {}, disableAnalytics = false) {
151
+ if (disableAnalytics || !await isTelemetryEnabled()) return;
152
+ const { projectName: _projectName, projectDir: _projectDir, relativePath: _relativePath, ...safeConfig } = config;
153
+ try {
154
+ await sendConvexEvent({
155
+ ...safeConfig,
156
+ eventType,
157
+ ...outcome,
158
+ machineId: await getOrCreateMachineId(),
159
+ cli_version: getLatestCLIVersion(),
160
+ node_version: typeof process !== "undefined" ? process.version : "",
161
+ platform: typeof process !== "undefined" ? process.platform : ""
162
+ });
163
+ } catch {}
164
+ }
165
+ async function trackProjectCreation(config, disableAnalytics = false, outcome = {}) {
166
+ await trackEvent("project_created", config, outcome, disableAnalytics);
167
+ }
168
+
169
+ //#endregion
170
+ export { trackProjectCreation as a, trackEvent as i, isTelemetryEnabled as n, getPersistedTelemetryPreference as o, maybeShowTelemetryNotice as r, setTelemetryPreference as s, hasTelemetryEnvOverride as t };
@@ -11,6 +11,72 @@ var types_exports = {};
11
11
  import * as import__better_fullstack_types from "@better-fullstack/types";
12
12
  __reExport(types_exports, import__better_fullstack_types);
13
13
 
14
+ //#endregion
15
+ //#region src/utils/get-package-manager.ts
16
+ const getUserPkgManager = () => {
17
+ const userAgent = process.env.npm_config_user_agent;
18
+ if (userAgent?.startsWith("pnpm")) return "pnpm";
19
+ if (userAgent?.startsWith("bun")) return "bun";
20
+ if (userAgent?.startsWith("yarn")) return "yarn";
21
+ return "npm";
22
+ };
23
+
24
+ //#endregion
25
+ //#region src/constants.ts
26
+ const __filename = fileURLToPath(import.meta.url);
27
+ const distPath = path.dirname(__filename);
28
+ const PKG_ROOT = path.join(distPath, "../");
29
+ const BUILDER_URL = "https://better-fullstack-web.vercel.app/new";
30
+ const DEFAULT_CONFIG_BASE = createCliDefaultProjectConfigBase(getUserPkgManager());
31
+ function getDefaultConfig() {
32
+ return {
33
+ ...DEFAULT_CONFIG_BASE,
34
+ projectDir: path.resolve(process.cwd(), DEFAULT_CONFIG_BASE.projectName),
35
+ packageManager: getUserPkgManager(),
36
+ frontend: [...DEFAULT_CONFIG_BASE.frontend],
37
+ addons: [...DEFAULT_CONFIG_BASE.addons],
38
+ examples: [...DEFAULT_CONFIG_BASE.examples],
39
+ rustLibraries: [...DEFAULT_CONFIG_BASE.rustLibraries],
40
+ pythonAi: [...DEFAULT_CONFIG_BASE.pythonAi],
41
+ javaLibraries: [...DEFAULT_CONFIG_BASE.javaLibraries],
42
+ javaTestingLibraries: [...DEFAULT_CONFIG_BASE.javaTestingLibraries],
43
+ aiDocs: [...DEFAULT_CONFIG_BASE.aiDocs]
44
+ };
45
+ }
46
+ const DEFAULT_CONFIG = getDefaultConfig();
47
+ /**
48
+ * Default UI library for each frontend framework
49
+ * Falls back based on what's compatible
50
+ */
51
+ const DEFAULT_UI_LIBRARY_BY_FRONTEND = {
52
+ "tanstack-router": "shadcn-ui",
53
+ "react-router": "shadcn-ui",
54
+ "react-vite": "shadcn-ui",
55
+ "tanstack-start": "shadcn-ui",
56
+ next: "shadcn-ui",
57
+ vinext: "shadcn-ui",
58
+ nuxt: "daisyui",
59
+ svelte: "daisyui",
60
+ solid: "daisyui",
61
+ "solid-start": "daisyui",
62
+ astro: "daisyui",
63
+ qwik: "daisyui",
64
+ angular: "daisyui",
65
+ redwood: "daisyui",
66
+ fresh: "daisyui",
67
+ "native-bare": "none",
68
+ "native-uniwind": "none",
69
+ "native-unistyles": "none",
70
+ none: "none"
71
+ };
72
+
73
+ //#endregion
74
+ //#region src/utils/get-latest-cli-version.ts
75
+ const getLatestCLIVersion = () => {
76
+ const packageJsonPath = path.join(PKG_ROOT, "package.json");
77
+ return fs.readJSONSync(packageJsonPath).version ?? "1.0.0";
78
+ };
79
+
14
80
  //#endregion
15
81
  //#region src/utils/graph-summary.ts
16
82
  const FRONTEND_LABELS = {
@@ -163,71 +229,6 @@ function getGraphBackendDeployInstructions(config) {
163
229
  }
164
230
  }
165
231
 
166
- //#endregion
167
- //#region src/utils/get-package-manager.ts
168
- const getUserPkgManager = () => {
169
- const userAgent = process.env.npm_config_user_agent;
170
- if (userAgent?.startsWith("pnpm")) return "pnpm";
171
- if (userAgent?.startsWith("bun")) return "bun";
172
- if (userAgent?.startsWith("yarn")) return "yarn";
173
- return "npm";
174
- };
175
-
176
- //#endregion
177
- //#region src/constants.ts
178
- const __filename = fileURLToPath(import.meta.url);
179
- const distPath = path.dirname(__filename);
180
- const PKG_ROOT = path.join(distPath, "../");
181
- const DEFAULT_CONFIG_BASE = createCliDefaultProjectConfigBase(getUserPkgManager());
182
- function getDefaultConfig() {
183
- return {
184
- ...DEFAULT_CONFIG_BASE,
185
- projectDir: path.resolve(process.cwd(), DEFAULT_CONFIG_BASE.projectName),
186
- packageManager: getUserPkgManager(),
187
- frontend: [...DEFAULT_CONFIG_BASE.frontend],
188
- addons: [...DEFAULT_CONFIG_BASE.addons],
189
- examples: [...DEFAULT_CONFIG_BASE.examples],
190
- rustLibraries: [...DEFAULT_CONFIG_BASE.rustLibraries],
191
- pythonAi: [...DEFAULT_CONFIG_BASE.pythonAi],
192
- javaLibraries: [...DEFAULT_CONFIG_BASE.javaLibraries],
193
- javaTestingLibraries: [...DEFAULT_CONFIG_BASE.javaTestingLibraries],
194
- aiDocs: [...DEFAULT_CONFIG_BASE.aiDocs]
195
- };
196
- }
197
- const DEFAULT_CONFIG = getDefaultConfig();
198
- /**
199
- * Default UI library for each frontend framework
200
- * Falls back based on what's compatible
201
- */
202
- const DEFAULT_UI_LIBRARY_BY_FRONTEND = {
203
- "tanstack-router": "shadcn-ui",
204
- "react-router": "shadcn-ui",
205
- "react-vite": "shadcn-ui",
206
- "tanstack-start": "shadcn-ui",
207
- next: "shadcn-ui",
208
- vinext: "shadcn-ui",
209
- nuxt: "daisyui",
210
- svelte: "daisyui",
211
- solid: "daisyui",
212
- "solid-start": "daisyui",
213
- astro: "daisyui",
214
- qwik: "daisyui",
215
- angular: "daisyui",
216
- redwood: "daisyui",
217
- fresh: "daisyui",
218
- "native-bare": "none",
219
- "native-uniwind": "none",
220
- "native-unistyles": "none",
221
- none: "none"
222
- };
223
-
224
- //#endregion
225
- //#region src/utils/get-latest-cli-version.ts
226
- const getLatestCLIVersion = () => {
227
- const packageJsonPath = path.join(PKG_ROOT, "package.json");
228
- return fs.readJSONSync(packageJsonPath).version ?? "1.0.0";
229
- };
230
-
231
232
  //#endregion
232
233
  //#region src/utils/bts-config.ts
233
234
  const BTS_CONFIG_FILE = "bts.jsonc";
@@ -315,6 +316,7 @@ function normalizeGraphConfigForPersistence(projectConfig, stackParts) {
315
316
  }
316
317
  if (selectedEcosystems.has("go") && projectConfig.auth === "go-better-auth" && legacyConfig.auth === "none") normalized.auth = projectConfig.auth;
317
318
  if (!selectedEcosystems.has("java")) {
319
+ normalized.javaLanguage = "java";
318
320
  normalized.javaWebFramework = "none";
319
321
  normalized.javaBuildTool = "none";
320
322
  normalized.javaOrm = "none";
@@ -534,6 +536,7 @@ function buildBtsConfigForPersistence(projectConfig, metadata = {}) {
534
536
  goCaching: persistedConfig.goCaching,
535
537
  goConfig: persistedConfig.goConfig,
536
538
  goObservability: persistedConfig.goObservability,
539
+ javaLanguage: persistedConfig.javaLanguage,
537
540
  javaWebFramework: persistedConfig.javaWebFramework,
538
541
  javaBuildTool: persistedConfig.javaBuildTool,
539
542
  javaOrm: persistedConfig.javaOrm,
@@ -690,6 +693,7 @@ async function writeBtsConfig(projectConfig, metadata = {}) {
690
693
  goCaching: btsConfig.goCaching,
691
694
  goConfig: btsConfig.goConfig,
692
695
  goObservability: btsConfig.goObservability,
696
+ javaLanguage: btsConfig.javaLanguage,
693
697
  javaWebFramework: btsConfig.javaWebFramework,
694
698
  javaBuildTool: btsConfig.javaBuildTool,
695
699
  javaOrm: btsConfig.javaOrm,
@@ -812,4 +816,4 @@ async function updateBtsConfig(projectDir, updates) {
812
816
  }
813
817
 
814
818
  //#endregion
815
- export { getPrimaryGraphPart as _, updateBtsConfig as a, DEFAULT_CONFIG as c, getUserPkgManager as d, getEffectiveStack as f, getGraphSummary as g, getGraphPart as h, readBtsConfigFromFile as i, DEFAULT_UI_LIBRARY_BY_FRONTEND as l, getGraphBackendUrl as m, previewBtsConfigUpdate as n, writeBtsConfig as o, getGraphBackendDeployInstructions as p, readBtsConfig as r, getLatestCLIVersion as s, buildBtsConfigForPersistence as t, getDefaultConfig as u, hasGraphPart as v, types_exports as y };
819
+ export { DEFAULT_UI_LIBRARY_BY_FRONTEND as _, updateBtsConfig as a, types_exports as b, getGraphBackendDeployInstructions as c, getGraphSummary as d, getPrimaryGraphPart as f, DEFAULT_CONFIG as g, BUILDER_URL as h, readBtsConfigFromFile as i, getGraphBackendUrl as l, getLatestCLIVersion as m, previewBtsConfigUpdate as n, writeBtsConfig as o, hasGraphPart as p, readBtsConfig as r, getEffectiveStack as s, buildBtsConfigForPersistence as t, getGraphPart as u, getDefaultConfig as v, getUserPkgManager as y };
package/dist/cli.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  //#region src/cli.ts
3
- if (process.argv[2] === "mcp" && process.argv.length === 3) import("./mcp-D9O5zgAA.mjs").then((m) => m.startMcpServer());
4
- else import("./run-3AkXloH1.mjs").then((m) => m.createBtsCli().run());
3
+ if (process.argv[2] === "mcp" && process.argv.length === 3) import("./mcp-492OkjcS.mjs").then((m) => m.startMcpServer());
4
+ else import("./run-CD8f7PHh.mjs").then((m) => m.createBtsCli().run());
5
5
 
6
6
  //#endregion
7
7
  export { };
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { y as types_exports } from "./bts-config-BceXPcpI.mjs";
2
+ import { b as types_exports } from "./bts-config-DQVWvPDs.mjs";
3
3
  import path from "node:path";
4
4
  import { cliInputToProjectConfigPartial } from "@better-fullstack/types/stack-translation";
5
5
 
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
- import { r as readBtsConfig } from "./bts-config-BceXPcpI.mjs";
2
+ import { r as readBtsConfig } from "./bts-config-DQVWvPDs.mjs";
3
3
  import { t as renderTitle } from "./render-title-zvyKC1ej.mjs";
4
4
  import { a as handleError } from "./errors-ns_o2OKg.mjs";
5
- import { t as runGeneratedChecks } from "./generated-checks-Dt4Xqp1x.mjs";
5
+ import { t as runGeneratedChecks } from "./generated-checks-BV9jol5h.mjs";
6
6
  import { intro, log, spinner } from "@clack/prompts";
7
7
  import pc from "picocolors";
8
8
  import fs from "fs-extra";
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { y as types_exports } from "./bts-config-BceXPcpI.mjs";
2
+ import { b as types_exports } from "./bts-config-DQVWvPDs.mjs";
3
3
  import { c as isSilent, i as exitWithError, t as CLIError } from "./errors-ns_o2OKg.mjs";
4
4
  import pc from "picocolors";
5
5
  import z from "zod";
@@ -1280,6 +1280,18 @@ function validateRateLimitConstraints(config) {
1280
1280
  function validateSearchConstraints(config) {
1281
1281
  if (!config.search || config.search === "none") return;
1282
1282
  const ecosystem = config.ecosystem ?? "typescript";
1283
+ if (config.search === "bleve" && ecosystem !== "go") incompatibilityError({
1284
+ message: "Bleve search is available for Go projects only.",
1285
+ provided: {
1286
+ ecosystem,
1287
+ search: config.search
1288
+ },
1289
+ suggestions: [
1290
+ "Use --ecosystem go",
1291
+ "Use --search meilisearch",
1292
+ "Use --search none"
1293
+ ]
1294
+ });
1283
1295
  const allowedSearch = {
1284
1296
  go: ["meilisearch", "bleve"],
1285
1297
  python: ["meilisearch", "elasticsearch"]
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { r as readBtsConfig } from "./bts-config-BceXPcpI.mjs";
2
+ import { r as readBtsConfig } from "./bts-config-DQVWvPDs.mjs";
3
3
  import { log } from "@clack/prompts";
4
4
  import pc from "picocolors";
5
5
  import fs from "fs-extra";
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { _ as getPrimaryGraphPart } from "./bts-config-BceXPcpI.mjs";
2
+ import { f as getPrimaryGraphPart } from "./bts-config-DQVWvPDs.mjs";
3
3
  import { log, spinner } from "@clack/prompts";
4
4
  import pc from "picocolors";
5
5
  import path from "node:path";