create-better-t-stack 3.41.1 → 3.41.3
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.
- package/README.md +1 -1
- package/dist/cli.mjs +13 -51
- package/dist/index.d.mts +3 -4
- package/dist/index.mjs +1 -1
- package/dist/{src-pRksmzD7.mjs → src-BhgA6H5Y.mjs} +30 -125
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -130,7 +130,7 @@ This CLI collects anonymous usage data to help improve the tool. The data collec
|
|
|
130
130
|
- Platform (OS)
|
|
131
131
|
- How the CLI was driven (prompts, flags, `--yes`, JSON, the programmatic API, or the MCP server)
|
|
132
132
|
|
|
133
|
-
Separately,
|
|
133
|
+
Separately, one anonymous failure event is sent when a scaffold breaks (stage and error class, never full messages or paths). See the [analytics documentation](https://better-t-stack.dev/docs/analytics) for details.
|
|
134
134
|
|
|
135
135
|
**Telemetry is enabled by default in published versions** to help us understand usage patterns and improve the tool.
|
|
136
136
|
|
package/dist/cli.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
2
|
+
import { D as setProcessMode, i as SchemaNameSchema, l as create, m as getSchemaResult, s as add, u as createBtsCli, v as types_exports, y as getLatestCLIVersion } from "./src-BhgA6H5Y.mjs";
|
|
3
3
|
import z from "zod";
|
|
4
4
|
import { McpServer } from "@modelcontextprotocol/server";
|
|
5
5
|
import { serveStdio } from "@modelcontextprotocol/server/stdio";
|
|
@@ -58,44 +58,6 @@ function formatToolError(cause) {
|
|
|
58
58
|
isError: true
|
|
59
59
|
};
|
|
60
60
|
}
|
|
61
|
-
const reportedSessions = /* @__PURE__ */ new WeakSet();
|
|
62
|
-
/** One session event per connection, sent when the client identity is first known. */
|
|
63
|
-
function reportMcpSession(server) {
|
|
64
|
-
if (reportedSessions.has(server)) return;
|
|
65
|
-
reportedSessions.add(server);
|
|
66
|
-
const client = server.server.getClientVersion();
|
|
67
|
-
reportDiagnostic("mcp_session", {
|
|
68
|
-
client: client?.name ?? "unknown",
|
|
69
|
-
clientVersion: client?.version ?? "unknown"
|
|
70
|
-
});
|
|
71
|
-
}
|
|
72
|
-
/**
|
|
73
|
-
* Times every tool call and reports the outcome. Diagnostics are fire-and-forget here
|
|
74
|
-
* because the server process is long-lived and must not add latency to tool results.
|
|
75
|
-
*/
|
|
76
|
-
function instrumentTool(server, tool, handler, isOptedOut) {
|
|
77
|
-
return async (...args) => {
|
|
78
|
-
if (isOptedOut?.(...args)) return handler(...args);
|
|
79
|
-
reportMcpSession(server);
|
|
80
|
-
const startTime = Date.now();
|
|
81
|
-
const result = await handler(...args);
|
|
82
|
-
const ok = !("isError" in result);
|
|
83
|
-
reportDiagnostic("mcp_tool", {
|
|
84
|
-
tool,
|
|
85
|
-
ok,
|
|
86
|
-
duration: durationBucket(Date.now() - startTime)
|
|
87
|
-
});
|
|
88
|
-
if (!ok) reportDiagnostic("mcp_tool_error", {
|
|
89
|
-
tool,
|
|
90
|
-
error: "ToolError",
|
|
91
|
-
reason: scrubReason(result.structuredContent.error)
|
|
92
|
-
});
|
|
93
|
-
return result;
|
|
94
|
-
};
|
|
95
|
-
}
|
|
96
|
-
function isCreateOptedOut(input) {
|
|
97
|
-
return input.disableAnalytics === true;
|
|
98
|
-
}
|
|
99
61
|
function getProjectToolAnnotations() {
|
|
100
62
|
return {
|
|
101
63
|
destructiveHint: true,
|
|
@@ -185,13 +147,13 @@ function createBtsMcpServer() {
|
|
|
185
147
|
idempotentHint: true,
|
|
186
148
|
openWorldHint: false
|
|
187
149
|
}
|
|
188
|
-
},
|
|
150
|
+
}, async () => {
|
|
189
151
|
try {
|
|
190
152
|
return formatToolSuccess(getStackGuidance());
|
|
191
153
|
} catch (error) {
|
|
192
154
|
return formatToolError(error);
|
|
193
155
|
}
|
|
194
|
-
})
|
|
156
|
+
});
|
|
195
157
|
server.registerTool("bts_get_schema", {
|
|
196
158
|
title: "Get Better T Stack Schemas",
|
|
197
159
|
description: "Inspect Better T Stack CLI and input schemas so agents can plan valid create/add requests. Use this together with bts_get_stack_guidance before creating a project if any part of the request is ambiguous.",
|
|
@@ -204,13 +166,13 @@ function createBtsMcpServer() {
|
|
|
204
166
|
idempotentHint: true,
|
|
205
167
|
openWorldHint: false
|
|
206
168
|
}
|
|
207
|
-
},
|
|
169
|
+
}, async ({ name }) => {
|
|
208
170
|
try {
|
|
209
171
|
return formatToolSuccess(getSchemaResult(name ?? "all"));
|
|
210
172
|
} catch (error) {
|
|
211
173
|
return formatToolError(error);
|
|
212
174
|
}
|
|
213
|
-
})
|
|
175
|
+
});
|
|
214
176
|
server.registerTool("bts_plan_project", {
|
|
215
177
|
title: "Plan Better T Stack Project",
|
|
216
178
|
description: "Validate and preview a Better T Stack project creation without writing files or provisioning resources. Always use this before bts_create_project. This tool requires an explicit full stack config rather than a partial payload with inferred defaults.",
|
|
@@ -223,7 +185,7 @@ function createBtsMcpServer() {
|
|
|
223
185
|
idempotentHint: true,
|
|
224
186
|
openWorldHint: false
|
|
225
187
|
}
|
|
226
|
-
},
|
|
188
|
+
}, async (input) => {
|
|
227
189
|
try {
|
|
228
190
|
const result = await create(input.projectName, {
|
|
229
191
|
...input,
|
|
@@ -242,7 +204,7 @@ function createBtsMcpServer() {
|
|
|
242
204
|
} catch (error) {
|
|
243
205
|
return formatToolError(error);
|
|
244
206
|
}
|
|
245
|
-
}
|
|
207
|
+
});
|
|
246
208
|
server.registerTool("bts_create_project", {
|
|
247
209
|
title: "Create Better T Stack Project",
|
|
248
210
|
description: "Create a Better T Stack project on disk using the same silent programmatic flow as the CLI JSON API. Call this only after bts_plan_project succeeds and the plan clearly matches the user's intent. This tool requires an explicit full stack config.",
|
|
@@ -252,7 +214,7 @@ function createBtsMcpServer() {
|
|
|
252
214
|
title: "Create Better T Stack Project",
|
|
253
215
|
...getProjectToolAnnotations()
|
|
254
216
|
}
|
|
255
|
-
},
|
|
217
|
+
}, async (input) => {
|
|
256
218
|
try {
|
|
257
219
|
if (input.install) return formatToolError(getMcpInstallTimeoutMessage(input.packageManager));
|
|
258
220
|
const result = await create(input.projectName, {
|
|
@@ -264,7 +226,7 @@ function createBtsMcpServer() {
|
|
|
264
226
|
} catch (error) {
|
|
265
227
|
return formatToolError(error);
|
|
266
228
|
}
|
|
267
|
-
}
|
|
229
|
+
});
|
|
268
230
|
server.registerTool("bts_plan_addons", {
|
|
269
231
|
title: "Plan Better T Stack Project Additions",
|
|
270
232
|
description: "Validate and preview addon installation or workspace package scaffolding for an existing Better T Stack project without writing files. Always use this before bts_add_addons.",
|
|
@@ -277,7 +239,7 @@ function createBtsMcpServer() {
|
|
|
277
239
|
idempotentHint: true,
|
|
278
240
|
openWorldHint: false
|
|
279
241
|
}
|
|
280
|
-
},
|
|
242
|
+
}, async (input) => {
|
|
281
243
|
try {
|
|
282
244
|
const result = await add({
|
|
283
245
|
...input,
|
|
@@ -288,7 +250,7 @@ function createBtsMcpServer() {
|
|
|
288
250
|
} catch (error) {
|
|
289
251
|
return formatToolError(error);
|
|
290
252
|
}
|
|
291
|
-
})
|
|
253
|
+
});
|
|
292
254
|
server.registerTool("bts_add_addons", {
|
|
293
255
|
title: "Apply Better T Stack Project Additions",
|
|
294
256
|
description: "Install addons or scaffold a workspace package in an existing Better T Stack project using the same silent flow as add-json. Call this only after bts_plan_addons succeeds and the planned changes match the user's intent.",
|
|
@@ -300,7 +262,7 @@ function createBtsMcpServer() {
|
|
|
300
262
|
idempotentHint: false,
|
|
301
263
|
openWorldHint: true
|
|
302
264
|
}
|
|
303
|
-
},
|
|
265
|
+
}, async (input) => {
|
|
304
266
|
try {
|
|
305
267
|
const result = await add(input);
|
|
306
268
|
if (!result?.success) return formatToolError(result?.error ?? "Failed to update project");
|
|
@@ -308,7 +270,7 @@ function createBtsMcpServer() {
|
|
|
308
270
|
} catch (error) {
|
|
309
271
|
return formatToolError(error);
|
|
310
272
|
}
|
|
311
|
-
})
|
|
273
|
+
});
|
|
312
274
|
return server;
|
|
313
275
|
}
|
|
314
276
|
function startBtsMcpServer() {
|
package/dist/index.d.mts
CHANGED
|
@@ -12,12 +12,9 @@ declare const UserCancelledError_base: import("better-result").TaggedErrorClass<
|
|
|
12
12
|
*/
|
|
13
13
|
declare class UserCancelledError extends UserCancelledError_base<{
|
|
14
14
|
message: string;
|
|
15
|
-
/** Name of the prompt that was open when the user cancelled, when known. */
|
|
16
|
-
prompt?: string;
|
|
17
15
|
}> {
|
|
18
16
|
constructor(args?: {
|
|
19
17
|
message?: string;
|
|
20
|
-
prompt?: string;
|
|
21
18
|
});
|
|
22
19
|
}
|
|
23
20
|
declare const CLIError_base: import("better-result").TaggedErrorClass<"CLIError">;
|
|
@@ -358,6 +355,7 @@ declare const router: import("@trpc/server").TRPCBuiltRouter<{
|
|
|
358
355
|
packageManager?: "bun" | "npm" | "pnpm" | undefined;
|
|
359
356
|
projectDir?: string | undefined;
|
|
360
357
|
dryRun?: boolean | undefined;
|
|
358
|
+
disableAnalytics?: boolean | undefined;
|
|
361
359
|
};
|
|
362
360
|
output: void;
|
|
363
361
|
meta: TrpcCliMeta;
|
|
@@ -407,6 +405,7 @@ declare const router: import("@trpc/server").TRPCBuiltRouter<{
|
|
|
407
405
|
install?: boolean | undefined;
|
|
408
406
|
packageManager?: "bun" | "npm" | "pnpm" | undefined;
|
|
409
407
|
dryRun?: boolean | undefined;
|
|
408
|
+
disableAnalytics?: boolean | undefined;
|
|
410
409
|
};
|
|
411
410
|
output: AddResult;
|
|
412
411
|
meta: TrpcCliMeta;
|
|
@@ -479,7 +478,7 @@ declare function builder(): Promise<void>;
|
|
|
479
478
|
* ```
|
|
480
479
|
*/
|
|
481
480
|
declare function createVirtual(options: Partial<Omit<types_d_exports.ProjectConfig, "projectDir" | "relativePath">>): Promise<Result$1<VirtualFileTree$1, GeneratorError$1>>;
|
|
482
|
-
type AddOptions = Pick<types_d_exports.AddInput, "addons" | "addonOptions" | "package" | "install" | "packageManager" | "projectDir" | "dryRun">;
|
|
481
|
+
type AddOptions = Pick<types_d_exports.AddInput, "addons" | "addonOptions" | "package" | "install" | "packageManager" | "projectDir" | "dryRun" | "disableAnalytics">;
|
|
483
482
|
/**
|
|
484
483
|
* Programmatic API to add addons or a workspace package to an existing Better-T-Stack project.
|
|
485
484
|
*
|
package/dist/index.mjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { C as
|
|
2
|
+
import { C as DirectoryConflictError, E as ValidationError, S as DatabaseSetupError, T as UserCancelledError, _ as ProjectLauncherSchema, a as TEMPLATE_COUNT, b as CLIError, c as builder, d as createVirtual, f as docs, g as sponsors, h as router, i as SchemaNameSchema, l as create, m as getSchemaResult, n as GeneratorError, o as VirtualFileSystem, p as generate, r as Result, s as add, t as EMBEDDED_TEMPLATES, u as createBtsCli, w as ProjectCreationError, x as CompatibilityError } from "./src-BhgA6H5Y.mjs";
|
|
3
3
|
export { CLIError, CompatibilityError, DatabaseSetupError, DirectoryConflictError, EMBEDDED_TEMPLATES, GeneratorError, ProjectCreationError, ProjectLauncherSchema, Result, SchemaNameSchema, TEMPLATE_COUNT, UserCancelledError, ValidationError, VirtualFileSystem, add, builder, create, createBtsCli, createVirtual, docs, generate, getSchemaResult, router, sponsors };
|
|
@@ -377,10 +377,7 @@ const cliConsola = {
|
|
|
377
377
|
*/
|
|
378
378
|
var UserCancelledError = class extends TaggedError("UserCancelledError") {
|
|
379
379
|
constructor(args) {
|
|
380
|
-
super({
|
|
381
|
-
message: args?.message ?? "Operation cancelled",
|
|
382
|
-
prompt: args?.prompt
|
|
383
|
-
});
|
|
380
|
+
super({ message: args?.message ?? "Operation cancelled" });
|
|
384
381
|
}
|
|
385
382
|
};
|
|
386
383
|
/**
|
|
@@ -1756,9 +1753,8 @@ function isTelemetryEnabled() {
|
|
|
1756
1753
|
//#endregion
|
|
1757
1754
|
//#region src/utils/diagnostics.ts
|
|
1758
1755
|
/**
|
|
1759
|
-
*
|
|
1760
|
-
* not to the Convex project dataset
|
|
1761
|
-
* cannot: failures, cancellations, non-create commands, slow stages, and MCP usage.
|
|
1756
|
+
* Failure diagnostics go to the self-hosted Umami instance (a separate "CLI" website),
|
|
1757
|
+
* not to the Convex project dataset, which only records successful creations.
|
|
1762
1758
|
* Everything is a no-op until UMAMI_CLI_WEBSITE_ID is baked in at build time.
|
|
1763
1759
|
*/
|
|
1764
1760
|
const UMAMI_HOST_URL = "https://umami.amanv.cloud";
|
|
@@ -1766,17 +1762,6 @@ const UMAMI_CLI_WEBSITE_ID = "e658611d-dbcc-4d3a-bc4e-182b9f5b0d5d";
|
|
|
1766
1762
|
const SEND_TIMEOUT_MS$1 = 3e3;
|
|
1767
1763
|
const MAX_STRING_LENGTH = 500;
|
|
1768
1764
|
const MAX_REASON_LENGTH = 160;
|
|
1769
|
-
const DURATION_BUCKETS = [
|
|
1770
|
-
[1e3, "<1s"],
|
|
1771
|
-
[5e3, "1-5s"],
|
|
1772
|
-
[15e3, "5-15s"],
|
|
1773
|
-
[6e4, "15-60s"],
|
|
1774
|
-
[3e5, "1-5m"]
|
|
1775
|
-
];
|
|
1776
|
-
function durationBucket(elapsedMs) {
|
|
1777
|
-
for (const [limit, label] of DURATION_BUCKETS) if (elapsedMs < limit) return label;
|
|
1778
|
-
return ">5m";
|
|
1779
|
-
}
|
|
1780
1765
|
/** Class name of the failure, which is stable and never carries user content. */
|
|
1781
1766
|
function errorClass(cause) {
|
|
1782
1767
|
if (cause instanceof Error) return cause.name || cause.constructor.name || "Error";
|
|
@@ -1794,7 +1779,7 @@ function failureStage(cause) {
|
|
|
1794
1779
|
}
|
|
1795
1780
|
/**
|
|
1796
1781
|
* First line of an error message with anything that could identify a machine or
|
|
1797
|
-
* project replaced by placeholders:
|
|
1782
|
+
* project replaced by placeholders: quoted names, URLs, emails, and paths.
|
|
1798
1783
|
*/
|
|
1799
1784
|
function scrubReason(cause) {
|
|
1800
1785
|
const scrubbed = ((cause instanceof Error ? cause.message : String(cause)).split(/\r?\n/, 1)[0] ?? "").replaceAll(/(["'`])(?:(?!\1).)*\1/g, "<name>").replaceAll(/https?:\/\/[^\s)\]"'>]+/gi, "<url>").replaceAll(/[\w.+-]+@[\w-]+\.[\w.-]+/g, "<email>").replaceAll(/(?:[a-zA-Z]:)?(?:[\\/][\w.@+ -]+)+[\\/][\w.@+-]+(?:[ \w.@+-]*\.\w+)?/g, "<path>").replaceAll(/\S*[\\/]\S*/g, "<path>").replaceAll(/\s+/g, " ").trim();
|
|
@@ -1807,11 +1792,6 @@ function clampValue(value) {
|
|
|
1807
1792
|
function isDiagnosticsEnabled() {
|
|
1808
1793
|
return Boolean(UMAMI_HOST_URL) && Boolean(UMAMI_CLI_WEBSITE_ID) && isTelemetryEnabled() && !getContext().analyticsDisabled;
|
|
1809
1794
|
}
|
|
1810
|
-
function eventUrl(name, data) {
|
|
1811
|
-
if (name.startsWith("mcp_")) return "/mcp";
|
|
1812
|
-
const command = data.command;
|
|
1813
|
-
return command === void 0 ? `/${name}` : `/${String(command)}`;
|
|
1814
|
-
}
|
|
1815
1795
|
function buildDiagnosticPayload(name, data) {
|
|
1816
1796
|
const eventData = {};
|
|
1817
1797
|
for (const [key, value] of Object.entries(data)) if (value !== void 0) eventData[key] = clampValue(value);
|
|
@@ -1820,7 +1800,7 @@ function buildDiagnosticPayload(name, data) {
|
|
|
1820
1800
|
payload: {
|
|
1821
1801
|
website: UMAMI_CLI_WEBSITE_ID,
|
|
1822
1802
|
hostname: "cli",
|
|
1823
|
-
url:
|
|
1803
|
+
url: `/${data.command}`,
|
|
1824
1804
|
title: name,
|
|
1825
1805
|
name,
|
|
1826
1806
|
data: eventData
|
|
@@ -1846,16 +1826,6 @@ async function reportDiagnostic(name, data) {
|
|
|
1846
1826
|
catch: () => void 0
|
|
1847
1827
|
});
|
|
1848
1828
|
}
|
|
1849
|
-
/** Reports a stage only when it crossed the slow threshold, so the event is a signal. */
|
|
1850
|
-
async function reportSlowStage(command, stage, elapsedMs, packageManager) {
|
|
1851
|
-
if (elapsedMs < 6e4) return;
|
|
1852
|
-
await reportDiagnostic("cli_slow", {
|
|
1853
|
-
command,
|
|
1854
|
-
stage,
|
|
1855
|
-
duration: durationBucket(elapsedMs),
|
|
1856
|
-
packageManager
|
|
1857
|
-
});
|
|
1858
|
-
}
|
|
1859
1829
|
//#endregion
|
|
1860
1830
|
//#region src/utils/input-hardening.ts
|
|
1861
1831
|
function hasControlCharacters(value) {
|
|
@@ -2731,10 +2701,7 @@ async function navigableGroup(prompts, opts) {
|
|
|
2731
2701
|
if (isCancel$1(result)) {
|
|
2732
2702
|
if (opts?.onCancel) {
|
|
2733
2703
|
results[name] = "canceled";
|
|
2734
|
-
opts.onCancel({
|
|
2735
|
-
results,
|
|
2736
|
-
prompt: String(name)
|
|
2737
|
-
});
|
|
2704
|
+
opts.onCancel({ results });
|
|
2738
2705
|
}
|
|
2739
2706
|
return results;
|
|
2740
2707
|
}
|
|
@@ -4919,11 +4886,11 @@ async function addHandler(input, options = {}) {
|
|
|
4919
4886
|
const { silent = false, mode } = options;
|
|
4920
4887
|
return runWithContextAsync({
|
|
4921
4888
|
silent,
|
|
4922
|
-
mode
|
|
4889
|
+
mode,
|
|
4890
|
+
analyticsDisabled: input.disableAnalytics
|
|
4923
4891
|
}, async () => {
|
|
4924
|
-
const startTime = Date.now();
|
|
4925
4892
|
const result = await addHandlerInternal(input);
|
|
4926
|
-
await reportAddOutcome(input, result
|
|
4893
|
+
await reportAddOutcome(input, result);
|
|
4927
4894
|
if (result.isOk()) return result.value;
|
|
4928
4895
|
const error = result.error;
|
|
4929
4896
|
if (UserCancelledError.is(error)) {
|
|
@@ -4945,36 +4912,13 @@ async function addHandler(input, options = {}) {
|
|
|
4945
4912
|
process.exit(1);
|
|
4946
4913
|
});
|
|
4947
4914
|
}
|
|
4948
|
-
async function reportAddOutcome(input, result
|
|
4949
|
-
|
|
4950
|
-
const duration = durationBucket(elapsedMs);
|
|
4951
|
-
if (result.isOk()) {
|
|
4952
|
-
await reportDiagnostic("cli_command", {
|
|
4953
|
-
command: "add",
|
|
4954
|
-
mode,
|
|
4955
|
-
ok: true,
|
|
4956
|
-
duration
|
|
4957
|
-
});
|
|
4958
|
-
return;
|
|
4959
|
-
}
|
|
4915
|
+
async function reportAddOutcome(input, result) {
|
|
4916
|
+
if (result.isOk()) return;
|
|
4960
4917
|
const error = result.error;
|
|
4961
|
-
if (UserCancelledError.is(error))
|
|
4962
|
-
await reportDiagnostic("cli_cancelled", {
|
|
4963
|
-
command: "add",
|
|
4964
|
-
mode,
|
|
4965
|
-
prompt: error.prompt ?? "unknown"
|
|
4966
|
-
});
|
|
4967
|
-
return;
|
|
4968
|
-
}
|
|
4969
|
-
await reportDiagnostic("cli_command", {
|
|
4970
|
-
command: "add",
|
|
4971
|
-
mode,
|
|
4972
|
-
ok: false,
|
|
4973
|
-
duration
|
|
4974
|
-
});
|
|
4918
|
+
if (UserCancelledError.is(error)) return;
|
|
4975
4919
|
await reportDiagnostic("cli_failed", {
|
|
4976
4920
|
command: "add",
|
|
4977
|
-
mode,
|
|
4921
|
+
mode: resolveInvocationMode(false),
|
|
4978
4922
|
stage: failureStage(error),
|
|
4979
4923
|
error: errorClass(error),
|
|
4980
4924
|
reason: scrubReason(error),
|
|
@@ -6278,11 +6222,8 @@ async function gatherConfig(flags, projectName, projectDir, relativePath, option
|
|
|
6278
6222
|
]
|
|
6279
6223
|
}
|
|
6280
6224
|
],
|
|
6281
|
-
onCancel: (
|
|
6282
|
-
throw new UserCancelledError({
|
|
6283
|
-
message: "Operation cancelled",
|
|
6284
|
-
prompt
|
|
6285
|
-
});
|
|
6225
|
+
onCancel: () => {
|
|
6226
|
+
throw new UserCancelledError({ message: "Operation cancelled" });
|
|
6286
6227
|
}
|
|
6287
6228
|
});
|
|
6288
6229
|
return {
|
|
@@ -6367,10 +6308,7 @@ async function getProjectName(initialName) {
|
|
|
6367
6308
|
}
|
|
6368
6309
|
}
|
|
6369
6310
|
});
|
|
6370
|
-
if (isCancel(response)) throw new UserCancelledError({
|
|
6371
|
-
message: "Operation cancelled.",
|
|
6372
|
-
prompt: "projectName"
|
|
6373
|
-
});
|
|
6311
|
+
if (isCancel(response)) throw new UserCancelledError({ message: "Operation cancelled." });
|
|
6374
6312
|
projectPath = response || defaultName;
|
|
6375
6313
|
isValid = true;
|
|
6376
6314
|
}
|
|
@@ -8964,7 +8902,6 @@ async function createProject(options, cliInput) {
|
|
|
8964
8902
|
return Result.gen(async function* () {
|
|
8965
8903
|
const projectDir = options.projectDir;
|
|
8966
8904
|
const isConvex = options.backend === "convex";
|
|
8967
|
-
const scaffoldStartTime = Date.now();
|
|
8968
8905
|
yield* Result.await(Result.tryPromise({
|
|
8969
8906
|
try: () => fs.ensureDir(projectDir),
|
|
8970
8907
|
catch: (e) => new ProjectCreationError({
|
|
@@ -9006,15 +8943,10 @@ async function createProject(options, cliInput) {
|
|
|
9006
8943
|
}));
|
|
9007
8944
|
yield* Result.await(formatProject(projectDir));
|
|
9008
8945
|
if (!isSilent()) log.success("Project scaffolded");
|
|
9009
|
-
|
|
9010
|
-
|
|
9011
|
-
|
|
9012
|
-
|
|
9013
|
-
projectDir,
|
|
9014
|
-
packageManager: options.packageManager
|
|
9015
|
-
}));
|
|
9016
|
-
await reportSlowStage("create", "install", Date.now() - installStartTime, options.packageManager);
|
|
9017
|
-
}
|
|
8946
|
+
if (options.install) yield* Result.await(installDependencies({
|
|
8947
|
+
projectDir,
|
|
8948
|
+
packageManager: options.packageManager
|
|
8949
|
+
}));
|
|
9018
8950
|
yield* Result.await(initializeGit(projectDir, options.git));
|
|
9019
8951
|
if (!isSilent()) await displayPostInstallInstructions({
|
|
9020
8952
|
...options,
|
|
@@ -9094,22 +9026,14 @@ async function executeCreateProjectHandler(input, options) {
|
|
|
9094
9026
|
};
|
|
9095
9027
|
});
|
|
9096
9028
|
}
|
|
9097
|
-
/**
|
|
9029
|
+
/** Failure diagnostics, which the success-only project event cannot show; awaited so it beats process.exit. */
|
|
9098
9030
|
async function reportCreateOutcome(input, result) {
|
|
9099
|
-
const mode = resolveInvocationMode(input.yes);
|
|
9100
9031
|
if (result.isOk()) return;
|
|
9101
9032
|
const error = result.error;
|
|
9102
|
-
if (UserCancelledError.is(error))
|
|
9103
|
-
await reportDiagnostic("cli_cancelled", {
|
|
9104
|
-
command: "create",
|
|
9105
|
-
mode,
|
|
9106
|
-
prompt: error.prompt ?? "unknown"
|
|
9107
|
-
});
|
|
9108
|
-
return;
|
|
9109
|
-
}
|
|
9033
|
+
if (UserCancelledError.is(error)) return;
|
|
9110
9034
|
await reportDiagnostic("cli_failed", {
|
|
9111
9035
|
command: "create",
|
|
9112
|
-
mode,
|
|
9036
|
+
mode: resolveInvocationMode(input.yes),
|
|
9113
9037
|
stage: failureStage(error),
|
|
9114
9038
|
error: errorClass(error),
|
|
9115
9039
|
reason: scrubReason(error),
|
|
@@ -9499,16 +9423,17 @@ const router = t.router({
|
|
|
9499
9423
|
return result;
|
|
9500
9424
|
}),
|
|
9501
9425
|
schema: t.procedure.meta({ description: "Show runtime CLI and input schemas as JSON" }).input(z.object({ name: SchemaNameSchema.describe("Schema name to inspect") })).query(({ input }) => getSchemaResult(input.name)),
|
|
9502
|
-
sponsors: t.procedure.meta({ description: "Show Better-T-Stack sponsors" }).mutation(() =>
|
|
9503
|
-
docs: t.procedure.meta({ description: "Open Better-T-Stack documentation" }).mutation(() =>
|
|
9504
|
-
builder: t.procedure.meta({ description: "Open the web-based stack builder" }).mutation(() =>
|
|
9426
|
+
sponsors: t.procedure.meta({ description: "Show Better-T-Stack sponsors" }).mutation(() => showSponsorsCommand()),
|
|
9427
|
+
docs: t.procedure.meta({ description: "Open Better-T-Stack documentation" }).mutation(() => openDocsCommand()),
|
|
9428
|
+
builder: t.procedure.meta({ description: "Open the web-based stack builder" }).mutation(() => openBuilderCommand()),
|
|
9505
9429
|
add: t.procedure.meta({ description: "Add addons or a workspace package to an existing Better-T-Stack project" }).input(z.object({
|
|
9506
9430
|
addons: z.array(types_exports.AddonsSchema).optional().describe("Addons to add"),
|
|
9507
9431
|
package: types_exports.WorkspacePackageNameSchema.optional(),
|
|
9508
9432
|
install: z.boolean().optional().default(false).describe("Install dependencies after adding"),
|
|
9509
9433
|
packageManager: types_exports.PackageManagerSchema.optional().describe("Package manager to use"),
|
|
9510
9434
|
projectDir: z.string().optional().describe("Project directory (defaults to current)"),
|
|
9511
|
-
dryRun: z.boolean().optional().default(false).describe("Preview addon changes without writing files")
|
|
9435
|
+
dryRun: z.boolean().optional().default(false).describe("Preview addon changes without writing files"),
|
|
9436
|
+
disableAnalytics: z.boolean().optional().default(false).describe("Disable analytics")
|
|
9512
9437
|
})).mutation(async ({ input }) => {
|
|
9513
9438
|
await addHandler(input);
|
|
9514
9439
|
}),
|
|
@@ -9529,29 +9454,9 @@ const router = t.router({
|
|
|
9529
9454
|
clear: z.boolean().optional().default(false).describe("Clear all history"),
|
|
9530
9455
|
json: z.boolean().optional().default(false).describe("Output as JSON")
|
|
9531
9456
|
})).mutation(async ({ input }) => {
|
|
9532
|
-
await
|
|
9457
|
+
await historyHandler(input);
|
|
9533
9458
|
})
|
|
9534
9459
|
});
|
|
9535
|
-
/** Usage diagnostics for commands that have no project event of their own. */
|
|
9536
|
-
async function trackCommand(command, run, isOk = () => true) {
|
|
9537
|
-
const startTime = Date.now();
|
|
9538
|
-
try {
|
|
9539
|
-
const value = await run();
|
|
9540
|
-
await reportDiagnostic("cli_command", {
|
|
9541
|
-
command,
|
|
9542
|
-
ok: isOk(value),
|
|
9543
|
-
duration: durationBucket(Date.now() - startTime)
|
|
9544
|
-
});
|
|
9545
|
-
return value;
|
|
9546
|
-
} catch (cause) {
|
|
9547
|
-
await reportDiagnostic("cli_command", {
|
|
9548
|
-
command,
|
|
9549
|
-
ok: false,
|
|
9550
|
-
duration: durationBucket(Date.now() - startTime)
|
|
9551
|
-
});
|
|
9552
|
-
throw cause;
|
|
9553
|
-
}
|
|
9554
|
-
}
|
|
9555
9460
|
function createBtsCli() {
|
|
9556
9461
|
return createCli({
|
|
9557
9462
|
router,
|
|
@@ -9738,4 +9643,4 @@ async function add(options = {}) {
|
|
|
9738
9643
|
};
|
|
9739
9644
|
}
|
|
9740
9645
|
//#endregion
|
|
9741
|
-
export {
|
|
9646
|
+
export { DirectoryConflictError as C, setProcessMode as D, ValidationError as E, DatabaseSetupError as S, UserCancelledError as T, ProjectLauncherSchema as _, TEMPLATE_COUNT as a, CLIError as b, builder as c, createVirtual as d, docs as f, sponsors as g, router as h, SchemaNameSchema as i, create as l, getSchemaResult as m, GeneratorError$1 as n, VirtualFileSystem$1 as o, generate$1 as p, Result$1 as r, add as s, EMBEDDED_TEMPLATES$1 as t, createBtsCli as u, types_exports as v, ProjectCreationError as w, CompatibilityError as x, getLatestCLIVersion as y };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-better-t-stack",
|
|
3
|
-
"version": "3.41.
|
|
3
|
+
"version": "3.41.3",
|
|
4
4
|
"description": "A modern CLI tool for scaffolding end-to-end type-safe TypeScript projects with best practices and customizable configurations",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"better-auth",
|
|
@@ -69,8 +69,8 @@
|
|
|
69
69
|
"prepublishOnly": "npm run build"
|
|
70
70
|
},
|
|
71
71
|
"dependencies": {
|
|
72
|
-
"@better-t-stack/template-generator": "^3.41.
|
|
73
|
-
"@better-t-stack/types": "^3.41.
|
|
72
|
+
"@better-t-stack/template-generator": "^3.41.3",
|
|
73
|
+
"@better-t-stack/types": "^3.41.3",
|
|
74
74
|
"@clack/core": "^1.4.3",
|
|
75
75
|
"@clack/prompts": "^1.7.0",
|
|
76
76
|
"@modelcontextprotocol/server": "2.0.0",
|