create-better-fullstack 2.1.5 → 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 (29) hide show
  1. package/dist/{add-handler-BNSL6HdM.mjs → add-handler-ztNjzoMN.mjs} +52 -6
  2. package/dist/addons-setup-DnLjAzTw.mjs +7 -0
  3. package/dist/{addons-setup-CyrP1IV-.mjs → addons-setup-LaAj43NP.mjs} +10 -24
  4. package/dist/analytics-DVltG11u.mjs +170 -0
  5. package/dist/{errors-Cyol8zbN.mjs → bts-config-DQVWvPDs.mjs} +72 -149
  6. package/dist/cli.mjs +2 -2
  7. package/dist/{templates-CnTOtKjm.mjs → config-processing-D9-F2Us9.mjs} +57 -2
  8. package/dist/{doctor-DBoq7bZ9.mjs → doctor-a4ca3SMd.mjs} +3 -2
  9. package/dist/errors-ns_o2OKg.mjs +86 -0
  10. package/dist/{file-formatter-B3dsev2l.mjs → file-formatter-gvmrpd-g.mjs} +78 -6
  11. package/dist/gen-CCClL7Ve.mjs +274 -0
  12. package/dist/{generated-checks-C8hn9w2i.mjs → generated-checks-BV9jol5h.mjs} +1 -1
  13. package/dist/index.d.mts +162 -64
  14. package/dist/index.mjs +17 -8
  15. package/dist/{install-dependencies-CgNh-aOy.mjs → install-dependencies-RoUyaE8o.mjs} +80 -21
  16. package/dist/mcp-492OkjcS.mjs +11 -0
  17. package/dist/mcp-entry.mjs +205 -30
  18. package/dist/prompt-environment-BR0Kkw2W.mjs +26 -0
  19. package/dist/registry-DSf2CEaU.mjs +408 -0
  20. package/dist/{run-BYse4yJy.mjs → run-D9I7NdES.mjs} +2081 -464
  21. package/dist/run-buK4aZS8.mjs +15 -0
  22. package/dist/scaffold-manifest-DGRyepdb.mjs +4 -0
  23. package/dist/scaffold-manifest-Dyi0voqE.mjs +135 -0
  24. package/dist/update-DJ8CI5KW.mjs +401 -0
  25. package/package.json +3 -3
  26. package/dist/addons-setup-DyMm42a5.mjs +0 -5
  27. package/dist/mcp-CsW3i66c.mjs +0 -6
  28. package/dist/run-_cf_sFwM.mjs +0 -10
  29. /package/dist/{update-deps-D5OG0KmJ.mjs → update-deps-aD-iQw4U.mjs} +0 -0
@@ -1,10 +1,14 @@
1
1
  #!/usr/bin/env node
2
- import { c as isSilent, g as updateBtsConfig, l as runWithContextAsync, m as readBtsConfig, n as UserCancelledError, t as CLIError, x as getDefaultConfig } from "./errors-Cyol8zbN.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
- import { t as setupAddons } from "./addons-setup-CyrP1IV-.mjs";
5
- import "./file-formatter-B3dsev2l.mjs";
6
- import { c as applyDependencyVersionChannel, t as installDependencies, u as getAddonsToAdd } from "./install-dependencies-CgNh-aOy.mjs";
7
- import { a as applyStackUpdate, o as planStackUpdate } from "./mcp-entry.mjs";
4
+ import { c as isSilent, l as runWithContextAsync, n as UserCancelledError, t as CLIError } from "./errors-ns_o2OKg.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";
11
+ import { o as applyStackUpdate, u as planStackUpdate } from "./mcp-entry.mjs";
8
12
  import { intro, log, outro } from "@clack/prompts";
9
13
  import pc from "picocolors";
10
14
  import fs from "fs-extra";
@@ -55,6 +59,13 @@ function logStackUpdateSummary(plan, dryRun) {
55
59
  const envCount = countEnvChanges(plan);
56
60
  if (envCount > 0) log.info(pc.dim(`Env vars: ${formatCount(envCount, "addition")}`));
57
61
  for (const adjustment of plan.compatibilityAdjustments) log.info(pc.dim(`Adjusted: ${adjustment}`));
62
+ if (plan.architectureChanges.length > 0) {
63
+ const swaps = plan.architectureChanges.map((change) => `${change.key}: ${change.from} -> ${change.to}`).join(", ");
64
+ log.warn(pc.yellow(`Architecture change: ${swaps}`));
65
+ log.info(pc.dim("Data and schema are NOT migrated automatically. Migration checklist:"));
66
+ for (const step of plan.migrationSteps) log.info(pc.dim(` - ${step}`));
67
+ if (dryRun && plan.requiresArchitectureAck) log.warn(pc.yellow("Re-run with --acknowledge-architecture-change to apply this architecture change."));
68
+ }
58
69
  for (const blocker of plan.manualReviewBlockers) log.warn(pc.yellow(`Manual review: ${blocker}`));
59
70
  }
60
71
  function buildAddonSetupConfig(projectDir, projectName, currentConfig, plan, addonsToSetup) {
@@ -116,12 +127,47 @@ async function runStackUpdateAdd(input, projectDir, projectName, currentConfig,
116
127
  setupWarnings: setupWarnings.length > 0 ? setupWarnings : void 0
117
128
  };
118
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
+ }
119
149
  async function addHandler(input, options = {}) {
120
150
  const { silent = false } = options;
151
+ const startTime = Date.now();
121
152
  return runWithContextAsync({ silent }, async () => {
122
153
  try {
123
- 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;
124
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
+ }
125
171
  if (error instanceof UserCancelledError) {
126
172
  if (isSilent()) return {
127
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,5 +1,7 @@
1
1
  #!/usr/bin/env node
2
- import { c as isSilent, m as readBtsConfig, r as exitCancelled } from "./errors-Cyol8zbN.mjs";
2
+ import { r as readBtsConfig } from "./bts-config-DQVWvPDs.mjs";
3
+ import { c as isSilent, r as exitCancelled } from "./errors-ns_o2OKg.mjs";
4
+ import { t as canPromptInteractively } from "./prompt-environment-BR0Kkw2W.mjs";
3
5
  import { autocompleteMultiselect, group, isCancel, log, multiselect, select, spinner } from "@clack/prompts";
4
6
  import pc from "picocolors";
5
7
  import fs from "fs-extra";
@@ -7,28 +9,6 @@ import path from "node:path";
7
9
  import consola from "consola";
8
10
  import { $ } from "execa";
9
11
 
10
- //#region src/utils/prompt-environment.ts
11
- function hasOwnProperty(value, property) {
12
- return Object.prototype.hasOwnProperty.call(value, property);
13
- }
14
- function resolveCiValue(environment) {
15
- if (environment && hasOwnProperty(environment, "ci")) return environment.ci;
16
- return process.env.CI;
17
- }
18
- function isCiEnvironment(value) {
19
- if (!value) return false;
20
- const normalizedValue = value.trim().toLowerCase();
21
- return normalizedValue !== "" && normalizedValue !== "0" && normalizedValue !== "false";
22
- }
23
- function canPromptInteractively(environment = {}) {
24
- const silent = environment.silent ?? isSilent();
25
- const stdinIsTTY = environment.stdinIsTTY ?? process.stdin.isTTY === true;
26
- const stdoutIsTTY = environment.stdoutIsTTY ?? process.stdout.isTTY === true;
27
- const ci = resolveCiValue(environment);
28
- return !silent && stdinIsTTY && stdoutIsTTY && !isCiEnvironment(ci);
29
- }
30
-
31
- //#endregion
32
12
  //#region src/utils/add-package-deps.ts
33
13
  const addPackageDependency = async (opts) => {
34
14
  const { dependencies = [], devDependencies = [], customDependencies = {}, customDevDependencies = {}, projectDir } = opts;
@@ -396,6 +376,12 @@ function getRecommendedMcpServers(config) {
396
376
  name: "polar",
397
377
  target: "https://mcp.polar.sh/mcp/polar-mcp"
398
378
  });
379
+ if (config.payments === "revenuecat") servers.push({
380
+ key: "revenuecat",
381
+ label: "RevenueCat",
382
+ name: "revenuecat",
383
+ target: "https://mcp.revenuecat.ai/mcp"
384
+ });
399
385
  return servers;
400
386
  }
401
387
  function filterAgentsForScope(scope) {
@@ -1332,4 +1318,4 @@ async function setupLefthook(projectDir) {
1332
1318
  }
1333
1319
 
1334
1320
  //#endregion
1335
- 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 };
@@ -1,20 +1,82 @@
1
1
  #!/usr/bin/env node
2
2
  import { t as __reExport } from "./chunk-CCII7kTE.mjs";
3
- import { cancel } from "@clack/prompts";
4
- import pc from "picocolors";
5
3
  import fs from "fs-extra";
6
4
  import path from "node:path";
7
5
  import * as JSONC from "jsonc-parser";
8
6
  import { createCliDefaultProjectConfigBase } from "@better-fullstack/types";
9
7
  import { fileURLToPath } from "node:url";
10
- import { AsyncLocalStorage } from "node:async_hooks";
11
- import consola from "consola";
12
8
 
13
9
  //#region src/types.ts
14
10
  var types_exports = {};
15
11
  import * as import__better_fullstack_types from "@better-fullstack/types";
16
12
  __reExport(types_exports, import__better_fullstack_types);
17
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
+
18
80
  //#endregion
19
81
  //#region src/utils/graph-summary.ts
20
82
  const FRONTEND_LABELS = {
@@ -167,71 +229,6 @@ function getGraphBackendDeployInstructions(config) {
167
229
  }
168
230
  }
169
231
 
170
- //#endregion
171
- //#region src/utils/get-package-manager.ts
172
- const getUserPkgManager = () => {
173
- const userAgent = process.env.npm_config_user_agent;
174
- if (userAgent?.startsWith("pnpm")) return "pnpm";
175
- if (userAgent?.startsWith("bun")) return "bun";
176
- if (userAgent?.startsWith("yarn")) return "yarn";
177
- return "npm";
178
- };
179
-
180
- //#endregion
181
- //#region src/constants.ts
182
- const __filename = fileURLToPath(import.meta.url);
183
- const distPath = path.dirname(__filename);
184
- const PKG_ROOT = path.join(distPath, "../");
185
- const DEFAULT_CONFIG_BASE = createCliDefaultProjectConfigBase(getUserPkgManager());
186
- function getDefaultConfig() {
187
- return {
188
- ...DEFAULT_CONFIG_BASE,
189
- projectDir: path.resolve(process.cwd(), DEFAULT_CONFIG_BASE.projectName),
190
- packageManager: getUserPkgManager(),
191
- frontend: [...DEFAULT_CONFIG_BASE.frontend],
192
- addons: [...DEFAULT_CONFIG_BASE.addons],
193
- examples: [...DEFAULT_CONFIG_BASE.examples],
194
- rustLibraries: [...DEFAULT_CONFIG_BASE.rustLibraries],
195
- pythonAi: [...DEFAULT_CONFIG_BASE.pythonAi],
196
- javaLibraries: [...DEFAULT_CONFIG_BASE.javaLibraries],
197
- javaTestingLibraries: [...DEFAULT_CONFIG_BASE.javaTestingLibraries],
198
- aiDocs: [...DEFAULT_CONFIG_BASE.aiDocs]
199
- };
200
- }
201
- const DEFAULT_CONFIG = getDefaultConfig();
202
- /**
203
- * Default UI library for each frontend framework
204
- * Falls back based on what's compatible
205
- */
206
- const DEFAULT_UI_LIBRARY_BY_FRONTEND = {
207
- "tanstack-router": "shadcn-ui",
208
- "react-router": "shadcn-ui",
209
- "react-vite": "shadcn-ui",
210
- "tanstack-start": "shadcn-ui",
211
- next: "shadcn-ui",
212
- vinext: "shadcn-ui",
213
- nuxt: "daisyui",
214
- svelte: "daisyui",
215
- solid: "daisyui",
216
- "solid-start": "daisyui",
217
- astro: "daisyui",
218
- qwik: "daisyui",
219
- angular: "daisyui",
220
- redwood: "daisyui",
221
- fresh: "daisyui",
222
- "native-bare": "none",
223
- "native-uniwind": "none",
224
- "native-unistyles": "none",
225
- none: "none"
226
- };
227
-
228
- //#endregion
229
- //#region src/utils/get-latest-cli-version.ts
230
- const getLatestCLIVersion = () => {
231
- const packageJsonPath = path.join(PKG_ROOT, "package.json");
232
- return fs.readJSONSync(packageJsonPath).version ?? "1.0.0";
233
- };
234
-
235
232
  //#endregion
236
233
  //#region src/utils/bts-config.ts
237
234
  const BTS_CONFIG_FILE = "bts.jsonc";
@@ -319,6 +316,7 @@ function normalizeGraphConfigForPersistence(projectConfig, stackParts) {
319
316
  }
320
317
  if (selectedEcosystems.has("go") && projectConfig.auth === "go-better-auth" && legacyConfig.auth === "none") normalized.auth = projectConfig.auth;
321
318
  if (!selectedEcosystems.has("java")) {
319
+ normalized.javaLanguage = "java";
322
320
  normalized.javaWebFramework = "none";
323
321
  normalized.javaBuildTool = "none";
324
322
  normalized.javaOrm = "none";
@@ -462,6 +460,7 @@ function buildBtsConfigForPersistence(projectConfig, metadata = {}) {
462
460
  testing: persistedConfig.testing,
463
461
  packageManager: persistedConfig.packageManager,
464
462
  versionChannel: persistedConfig.versionChannel,
463
+ workspaceShape: persistedConfig.workspaceShape === "single-app" ? "single-app" : void 0,
465
464
  dbSetup: persistedConfig.dbSetup,
466
465
  api: persistedConfig.api,
467
466
  webDeploy: persistedConfig.webDeploy,
@@ -537,6 +536,7 @@ function buildBtsConfigForPersistence(projectConfig, metadata = {}) {
537
536
  goCaching: persistedConfig.goCaching,
538
537
  goConfig: persistedConfig.goConfig,
539
538
  goObservability: persistedConfig.goObservability,
539
+ javaLanguage: persistedConfig.javaLanguage,
540
540
  javaWebFramework: persistedConfig.javaWebFramework,
541
541
  javaBuildTool: persistedConfig.javaBuildTool,
542
542
  javaOrm: persistedConfig.javaOrm,
@@ -617,6 +617,7 @@ async function writeBtsConfig(projectConfig, metadata = {}) {
617
617
  testing: btsConfig.testing,
618
618
  packageManager: btsConfig.packageManager,
619
619
  versionChannel: btsConfig.versionChannel,
620
+ workspaceShape: btsConfig.workspaceShape,
620
621
  dbSetup: btsConfig.dbSetup,
621
622
  api: btsConfig.api,
622
623
  webDeploy: btsConfig.webDeploy,
@@ -692,6 +693,7 @@ async function writeBtsConfig(projectConfig, metadata = {}) {
692
693
  goCaching: btsConfig.goCaching,
693
694
  goConfig: btsConfig.goConfig,
694
695
  goObservability: btsConfig.goObservability,
696
+ javaLanguage: btsConfig.javaLanguage,
695
697
  javaWebFramework: btsConfig.javaWebFramework,
696
698
  javaBuildTool: btsConfig.javaBuildTool,
697
699
  javaOrm: btsConfig.javaOrm,
@@ -814,83 +816,4 @@ async function updateBtsConfig(projectDir, updates) {
814
816
  }
815
817
 
816
818
  //#endregion
817
- //#region src/utils/context.ts
818
- const cliStorage = new AsyncLocalStorage();
819
- function defaultContext() {
820
- return {
821
- navigation: {
822
- isFirstPrompt: false,
823
- lastPromptShownUI: false
824
- },
825
- silent: false
826
- };
827
- }
828
- function getContext() {
829
- const ctx = cliStorage.getStore();
830
- if (!ctx) return defaultContext();
831
- return ctx;
832
- }
833
- function tryGetContext() {
834
- return cliStorage.getStore();
835
- }
836
- function isSilent() {
837
- return getContext().silent;
838
- }
839
- function isFirstPrompt() {
840
- return getContext().navigation.isFirstPrompt;
841
- }
842
- function didLastPromptShowUI() {
843
- return getContext().navigation.lastPromptShownUI;
844
- }
845
- function setIsFirstPrompt(value) {
846
- const ctx = tryGetContext();
847
- if (ctx) ctx.navigation.isFirstPrompt = value;
848
- }
849
- function setLastPromptShownUI(value) {
850
- const ctx = tryGetContext();
851
- if (ctx) ctx.navigation.lastPromptShownUI = value;
852
- }
853
- async function runWithContextAsync(options, fn) {
854
- const ctx = {
855
- navigation: {
856
- isFirstPrompt: false,
857
- lastPromptShownUI: false
858
- },
859
- silent: options.silent ?? false
860
- };
861
- return cliStorage.run(ctx, fn);
862
- }
863
-
864
- //#endregion
865
- //#region src/utils/errors.ts
866
- var UserCancelledError = class extends Error {
867
- constructor(message = "Operation cancelled") {
868
- super(message);
869
- this.name = "UserCancelledError";
870
- }
871
- };
872
- var CLIError = class extends Error {
873
- constructor(message) {
874
- super(message);
875
- this.name = "CLIError";
876
- }
877
- };
878
- function exitWithError(message) {
879
- if (isSilent()) throw new CLIError(message);
880
- consola.error(pc.red(message));
881
- process.exit(1);
882
- }
883
- function exitCancelled(message = "Operation cancelled") {
884
- if (isSilent()) throw new UserCancelledError(message);
885
- cancel(pc.red(message));
886
- process.exit(1);
887
- }
888
- function handleError(error, fallbackMessage) {
889
- const message = error instanceof Error ? error.message : fallbackMessage || String(error);
890
- if (isSilent()) throw error instanceof Error ? error : new Error(message);
891
- consola.error(pc.red(message));
892
- process.exit(1);
893
- }
894
-
895
- //#endregion
896
- export { types_exports as A, getEffectiveStack as C, getGraphSummary as D, getGraphPart as E, getPrimaryGraphPart as O, getUserPkgManager as S, getGraphBackendUrl as T, writeBtsConfig as _, handleError as a, DEFAULT_UI_LIBRARY_BY_FRONTEND as b, isSilent as c, setLastPromptShownUI as d, buildBtsConfigForPersistence as f, updateBtsConfig as g, readBtsConfigFromFile as h, exitWithError as i, hasGraphPart as k, runWithContextAsync as l, readBtsConfig as m, UserCancelledError as n, didLastPromptShowUI as o, previewBtsConfigUpdate as p, exitCancelled as r, isFirstPrompt as s, CLIError as t, setIsFirstPrompt as u, getLatestCLIVersion as v, getGraphBackendDeployInstructions as w, getDefaultConfig as x, DEFAULT_CONFIG 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-CsW3i66c.mjs").then((m) => m.startMcpServer());
4
- else import("./run-_cf_sFwM.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-buK4aZS8.mjs").then((m) => m.createBtsCli().run());
5
5
 
6
6
  //#endregion
7
7
  export { };