create-better-t-stack 2.38.2 → 2.39.0-canary.bae99c30
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/dist/cli.js +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/{src-C2nUxBND.js → src-CHXGSisf.js} +22 -17
- package/package.json +3 -4
- package/templates/examples/ai/web/react/base/src/components/response.tsx.hbs +22 -0
- package/templates/examples/ai/web/react/next/src/app/ai/page.tsx.hbs +5 -8
- package/templates/examples/ai/web/react/react-router/src/routes/ai.tsx.hbs +2 -5
- package/templates/examples/ai/web/react/tanstack-router/src/routes/ai.tsx.hbs +2 -5
- package/templates/examples/ai/web/react/tanstack-start/src/routes/ai.tsx.hbs +2 -5
- package/templates/frontend/react/web-base/src/{index.css → index.css.hbs} +3 -0
package/dist/cli.js
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -261,7 +261,7 @@ declare const router: trpcServer.TRPCBuiltRouter<{
|
|
|
261
261
|
}>>;
|
|
262
262
|
declare function createBtsCli(): trpc_cli0.TrpcCli;
|
|
263
263
|
/**
|
|
264
|
-
* Initialize a new Better-T
|
|
264
|
+
* Initialize a new Better-T-Stack project
|
|
265
265
|
*
|
|
266
266
|
* @example CLI usage:
|
|
267
267
|
* ```bash
|
package/dist/index.js
CHANGED
|
@@ -107,6 +107,7 @@ const dependencyVersionMap = {
|
|
|
107
107
|
"@ai-sdk/vue": "^2.0.9",
|
|
108
108
|
"@ai-sdk/svelte": "^3.0.9",
|
|
109
109
|
"@ai-sdk/react": "^2.0.9",
|
|
110
|
+
streamdown: "^1.1.6",
|
|
110
111
|
"@orpc/server": "^1.8.4",
|
|
111
112
|
"@orpc/client": "^1.8.4",
|
|
112
113
|
"@orpc/tanstack-query": "^1.8.4",
|
|
@@ -1346,7 +1347,7 @@ const getLatestCLIVersion = () => {
|
|
|
1346
1347
|
*/
|
|
1347
1348
|
function isTelemetryEnabled() {
|
|
1348
1349
|
const BTS_TELEMETRY_DISABLED = process.env.BTS_TELEMETRY_DISABLED;
|
|
1349
|
-
const BTS_TELEMETRY = "
|
|
1350
|
+
const BTS_TELEMETRY = "0";
|
|
1350
1351
|
if (BTS_TELEMETRY_DISABLED !== void 0) return BTS_TELEMETRY_DISABLED !== "1";
|
|
1351
1352
|
if (BTS_TELEMETRY !== void 0) return BTS_TELEMETRY === "1";
|
|
1352
1353
|
return true;
|
|
@@ -1354,8 +1355,8 @@ function isTelemetryEnabled() {
|
|
|
1354
1355
|
|
|
1355
1356
|
//#endregion
|
|
1356
1357
|
//#region src/utils/analytics.ts
|
|
1357
|
-
const POSTHOG_API_KEY = "
|
|
1358
|
-
const POSTHOG_HOST = "
|
|
1358
|
+
const POSTHOG_API_KEY = "random";
|
|
1359
|
+
const POSTHOG_HOST = "random";
|
|
1359
1360
|
function generateSessionId() {
|
|
1360
1361
|
const rand = Math.random().toString(36).slice(2);
|
|
1361
1362
|
const now = Date.now().toString(36);
|
|
@@ -2345,6 +2346,10 @@ async function setupExamplesTemplate(projectDir, context) {
|
|
|
2345
2346
|
if (hasReactWeb) {
|
|
2346
2347
|
const exampleWebSrc = path.join(exampleBaseDir, "web/react");
|
|
2347
2348
|
if (await fs.pathExists(exampleWebSrc)) {
|
|
2349
|
+
if (example === "ai") {
|
|
2350
|
+
const exampleWebBaseSrc = path.join(exampleWebSrc, "base");
|
|
2351
|
+
if (await fs.pathExists(exampleWebBaseSrc)) await processAndCopyFiles("**/*", exampleWebBaseSrc, webAppDir, context, false);
|
|
2352
|
+
}
|
|
2348
2353
|
const reactFramework = context.frontend.find((f) => [
|
|
2349
2354
|
"next",
|
|
2350
2355
|
"react-router",
|
|
@@ -2948,9 +2953,9 @@ async function addAddonsToProject(input) {
|
|
|
2948
2953
|
try {
|
|
2949
2954
|
const projectDir = input.projectDir || process.cwd();
|
|
2950
2955
|
const isBetterTStack = await isBetterTStackProject(projectDir);
|
|
2951
|
-
if (!isBetterTStack) exitWithError("This doesn't appear to be a Better-T
|
|
2956
|
+
if (!isBetterTStack) exitWithError("This doesn't appear to be a Better-T-Stack project. Please run this command from the root of a Better-T-Stack project.");
|
|
2952
2957
|
const detectedConfig = await detectProjectConfig(projectDir);
|
|
2953
|
-
if (!detectedConfig) exitWithError("Could not detect the project configuration. Please ensure this is a valid Better-T
|
|
2958
|
+
if (!detectedConfig) exitWithError("Could not detect the project configuration. Please ensure this is a valid Better-T-Stack project.");
|
|
2954
2959
|
const config = {
|
|
2955
2960
|
projectName: detectedConfig.projectName || path.basename(projectDir),
|
|
2956
2961
|
projectDir,
|
|
@@ -3718,9 +3723,9 @@ async function addDeploymentToProject(input) {
|
|
|
3718
3723
|
try {
|
|
3719
3724
|
const projectDir = input.projectDir || process.cwd();
|
|
3720
3725
|
const isBetterTStack = await isBetterTStackProject(projectDir);
|
|
3721
|
-
if (!isBetterTStack) exitWithError("This doesn't appear to be a Better-T
|
|
3726
|
+
if (!isBetterTStack) exitWithError("This doesn't appear to be a Better-T-Stack project. Please run this command from the root of a Better-T-Stack project.");
|
|
3722
3727
|
const detectedConfig = await detectProjectConfig(projectDir);
|
|
3723
|
-
if (!detectedConfig) exitWithError("Could not detect the project configuration. Please ensure this is a valid Better-T
|
|
3728
|
+
if (!detectedConfig) exitWithError("Could not detect the project configuration. Please ensure this is a valid Better-T-Stack project.");
|
|
3724
3729
|
if (input.webDeploy && detectedConfig.webDeploy === input.webDeploy) exitWithError(`${input.webDeploy} web deployment is already configured for this project.`);
|
|
3725
3730
|
if (input.serverDeploy && detectedConfig.serverDeploy === input.serverDeploy) exitWithError(`${input.serverDeploy} server deployment is already configured for this project.`);
|
|
3726
3731
|
const config = {
|
|
@@ -3830,7 +3835,7 @@ async function setupExamples(config) {
|
|
|
3830
3835
|
const dependencies = ["ai"];
|
|
3831
3836
|
if (hasNuxt) dependencies.push("@ai-sdk/vue");
|
|
3832
3837
|
else if (hasSvelte) dependencies.push("@ai-sdk/svelte");
|
|
3833
|
-
else if (hasReactWeb) dependencies.push("@ai-sdk/react");
|
|
3838
|
+
else if (hasReactWeb) dependencies.push("@ai-sdk/react", "streamdown");
|
|
3834
3839
|
await addPackageDependency({
|
|
3835
3840
|
dependencies,
|
|
3836
3841
|
projectDir: webClientDir
|
|
@@ -5744,7 +5749,7 @@ async function displayPostInstallInstructions(config) {
|
|
|
5744
5749
|
if (noOrmWarning) output += `\n${noOrmWarning.trim()}\n`;
|
|
5745
5750
|
if (bunWebNativeWarning) output += `\n${bunWebNativeWarning.trim()}\n`;
|
|
5746
5751
|
output += `\n${pc.bold("Update all dependencies:\n")}${pc.cyan(tazeCommand)}\n\n`;
|
|
5747
|
-
output += `${pc.bold("Like Better-T
|
|
5752
|
+
output += `${pc.bold("Like Better-T-Stack?")} Please consider giving us a star\n on GitHub:\n`;
|
|
5748
5753
|
output += pc.cyan("https://github.com/AmanVarshney01/create-better-t-stack");
|
|
5749
5754
|
consola$1.box(output);
|
|
5750
5755
|
}
|
|
@@ -6072,7 +6077,7 @@ async function createProjectHandler(input) {
|
|
|
6072
6077
|
const startTime = Date.now();
|
|
6073
6078
|
const timeScaffolded = (/* @__PURE__ */ new Date()).toISOString();
|
|
6074
6079
|
if (input.renderTitle !== false) renderTitle();
|
|
6075
|
-
intro(pc.magenta("Creating a new Better-T
|
|
6080
|
+
intro(pc.magenta("Creating a new Better-T-Stack project"));
|
|
6076
6081
|
if (input.yolo) consola.fatal("YOLO mode enabled - skipping checks. Things may break!");
|
|
6077
6082
|
let currentPathInput;
|
|
6078
6083
|
if (input.yes && input.projectName) currentPathInput = input.projectName;
|
|
@@ -6219,7 +6224,7 @@ async function addAddonsHandler(input) {
|
|
|
6219
6224
|
try {
|
|
6220
6225
|
const projectDir = input.projectDir || process.cwd();
|
|
6221
6226
|
const detectedConfig = await detectProjectConfig(projectDir);
|
|
6222
|
-
if (!detectedConfig) exitWithError("Could not detect project configuration. Please ensure this is a valid Better-T
|
|
6227
|
+
if (!detectedConfig) exitWithError("Could not detect project configuration. Please ensure this is a valid Better-T-Stack project.");
|
|
6223
6228
|
if (!input.addons || input.addons.length === 0) {
|
|
6224
6229
|
const addonsPrompt = await getAddonsToAdd(detectedConfig.frontend || [], detectedConfig.addons || []);
|
|
6225
6230
|
if (addonsPrompt.length > 0) input.addons = addonsPrompt;
|
|
@@ -6343,7 +6348,7 @@ function displaySponsors(sponsors$1) {
|
|
|
6343
6348
|
const t = trpcServer.initTRPC.create();
|
|
6344
6349
|
const router = t.router({
|
|
6345
6350
|
init: t.procedure.meta({
|
|
6346
|
-
description: "Create a new Better-T
|
|
6351
|
+
description: "Create a new Better-T-Stack project",
|
|
6347
6352
|
default: true,
|
|
6348
6353
|
negateBooleans: true
|
|
6349
6354
|
}).input(z.tuple([ProjectNameSchema.optional(), z.object({
|
|
@@ -6377,7 +6382,7 @@ const router = t.router({
|
|
|
6377
6382
|
const result = await createProjectHandler(combinedInput);
|
|
6378
6383
|
if (options.verbose) return result;
|
|
6379
6384
|
}),
|
|
6380
|
-
add: t.procedure.meta({ description: "Add addons or deployment configurations to an existing Better-T
|
|
6385
|
+
add: t.procedure.meta({ description: "Add addons or deployment configurations to an existing Better-T-Stack project" }).input(z.tuple([z.object({
|
|
6381
6386
|
addons: z.array(AddonsSchema).optional().default([]),
|
|
6382
6387
|
webDeploy: WebDeploySchema.optional(),
|
|
6383
6388
|
serverDeploy: ServerDeploySchema.optional(),
|
|
@@ -6388,17 +6393,17 @@ const router = t.router({
|
|
|
6388
6393
|
const [options] = input;
|
|
6389
6394
|
await addAddonsHandler(options);
|
|
6390
6395
|
}),
|
|
6391
|
-
sponsors: t.procedure.meta({ description: "Show Better-T
|
|
6396
|
+
sponsors: t.procedure.meta({ description: "Show Better-T-Stack sponsors" }).mutation(async () => {
|
|
6392
6397
|
try {
|
|
6393
6398
|
renderTitle();
|
|
6394
|
-
intro(pc.magenta("Better-T
|
|
6399
|
+
intro(pc.magenta("Better-T-Stack Sponsors"));
|
|
6395
6400
|
const sponsors$1 = await fetchSponsors();
|
|
6396
6401
|
displaySponsors(sponsors$1);
|
|
6397
6402
|
} catch (error) {
|
|
6398
6403
|
handleError(error, "Failed to display sponsors");
|
|
6399
6404
|
}
|
|
6400
6405
|
}),
|
|
6401
|
-
docs: t.procedure.meta({ description: "Open Better-T
|
|
6406
|
+
docs: t.procedure.meta({ description: "Open Better-T-Stack documentation" }).mutation(async () => {
|
|
6402
6407
|
const DOCS_URL = "https://better-t-stack.dev/docs";
|
|
6403
6408
|
try {
|
|
6404
6409
|
await openUrl(DOCS_URL);
|
|
@@ -6426,7 +6431,7 @@ function createBtsCli() {
|
|
|
6426
6431
|
});
|
|
6427
6432
|
}
|
|
6428
6433
|
/**
|
|
6429
|
-
* Initialize a new Better-T
|
|
6434
|
+
* Initialize a new Better-T-Stack project
|
|
6430
6435
|
*
|
|
6431
6436
|
* @example CLI usage:
|
|
6432
6437
|
* ```bash
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-better-t-stack",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.39.0-canary.bae99c30",
|
|
4
4
|
"description": "A modern CLI tool for scaffolding end-to-end type-safe TypeScript projects with best practices and customizable configurations",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"author": "Aman Varshney",
|
|
8
8
|
"bin": {
|
|
9
|
-
"create-better-t-stack": "
|
|
9
|
+
"create-better-t-stack": "./src/cli.ts"
|
|
10
10
|
},
|
|
11
11
|
"files": [
|
|
12
12
|
"templates",
|
|
@@ -59,8 +59,7 @@
|
|
|
59
59
|
},
|
|
60
60
|
"exports": {
|
|
61
61
|
".": {
|
|
62
|
-
"
|
|
63
|
-
"import": "./dist/index.js"
|
|
62
|
+
"import": "./src/index.ts"
|
|
64
63
|
}
|
|
65
64
|
},
|
|
66
65
|
"dependencies": {
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { type ComponentProps, memo } from "react";
|
|
4
|
+
import { Streamdown } from "streamdown";
|
|
5
|
+
import { cn } from "@/lib/utils";
|
|
6
|
+
|
|
7
|
+
type ResponseProps = ComponentProps<typeof Streamdown>;
|
|
8
|
+
|
|
9
|
+
export const Response = memo(
|
|
10
|
+
({ className, ...props }: ResponseProps) => (
|
|
11
|
+
<Streamdown
|
|
12
|
+
className={cn(
|
|
13
|
+
"size-full [&>*:first-child]:mt-0 [&>*:last-child]:mb-0",
|
|
14
|
+
className,
|
|
15
|
+
)}
|
|
16
|
+
{...props}
|
|
17
|
+
/>
|
|
18
|
+
),
|
|
19
|
+
(prevProps, nextProps) => prevProps.children === nextProps.children,
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
Response.displayName = "Response";
|
|
@@ -2,10 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
import { useChat } from "@ai-sdk/react";
|
|
4
4
|
import { DefaultChatTransport } from "ai";
|
|
5
|
-
import { Input } from "@/components/ui/input";
|
|
6
|
-
import { Button } from "@/components/ui/button";
|
|
7
5
|
import { Send } from "lucide-react";
|
|
8
|
-
import {
|
|
6
|
+
import { useEffect, useRef, useState } from "react";
|
|
7
|
+
import { Response } from "@/components/response";
|
|
8
|
+
import { Button } from "@/components/ui/button";
|
|
9
|
+
import { Input } from "@/components/ui/input";
|
|
9
10
|
|
|
10
11
|
export default function AIPage() {
|
|
11
12
|
const [input, setInput] = useState("");
|
|
@@ -51,11 +52,7 @@ export default function AIPage() {
|
|
|
51
52
|
</p>
|
|
52
53
|
{message.parts?.map((part, index) => {
|
|
53
54
|
if (part.type === "text") {
|
|
54
|
-
return
|
|
55
|
-
<div key={index} className="whitespace-pre-wrap">
|
|
56
|
-
{part.text}
|
|
57
|
-
</div>
|
|
58
|
-
);
|
|
55
|
+
return <Response key={index}>{part.text}</Response>;
|
|
59
56
|
}
|
|
60
57
|
return null;
|
|
61
58
|
})}
|
|
@@ -4,6 +4,7 @@ import { DefaultChatTransport } from "ai";
|
|
|
4
4
|
import { Input } from "@/components/ui/input";
|
|
5
5
|
import { Button } from "@/components/ui/button";
|
|
6
6
|
import { Send } from "lucide-react";
|
|
7
|
+
import { Response } from "@/components/response";
|
|
7
8
|
|
|
8
9
|
const AI: React.FC = () => {
|
|
9
10
|
const [input, setInput] = useState("");
|
|
@@ -49,11 +50,7 @@ const AI: React.FC = () => {
|
|
|
49
50
|
</p>
|
|
50
51
|
{message.parts?.map((part, index) => {
|
|
51
52
|
if (part.type === "text") {
|
|
52
|
-
return
|
|
53
|
-
<div key={index} className="whitespace-pre-wrap">
|
|
54
|
-
{part.text}
|
|
55
|
-
</div>
|
|
56
|
-
);
|
|
53
|
+
return <Response key={index}>{part.text}</Response>;
|
|
57
54
|
}
|
|
58
55
|
return null;
|
|
59
56
|
})}
|
|
@@ -5,6 +5,7 @@ import { Input } from "@/components/ui/input";
|
|
|
5
5
|
import { Button } from "@/components/ui/button";
|
|
6
6
|
import { Send } from "lucide-react";
|
|
7
7
|
import { useRef, useEffect, useState } from "react";
|
|
8
|
+
import { Response } from "@/components/response";
|
|
8
9
|
|
|
9
10
|
export const Route = createFileRoute("/ai")({
|
|
10
11
|
component: RouteComponent,
|
|
@@ -54,11 +55,7 @@ function RouteComponent() {
|
|
|
54
55
|
</p>
|
|
55
56
|
{message.parts?.map((part, index) => {
|
|
56
57
|
if (part.type === "text") {
|
|
57
|
-
return
|
|
58
|
-
<div key={index} className="whitespace-pre-wrap">
|
|
59
|
-
{part.text}
|
|
60
|
-
</div>
|
|
61
|
-
);
|
|
58
|
+
return <Response key={index}>{part.text}</Response>;
|
|
62
59
|
}
|
|
63
60
|
return null;
|
|
64
61
|
})}
|
|
@@ -5,6 +5,7 @@ import { Input } from "@/components/ui/input";
|
|
|
5
5
|
import { Button } from "@/components/ui/button";
|
|
6
6
|
import { Send } from "lucide-react";
|
|
7
7
|
import { useRef, useEffect, useState } from "react";
|
|
8
|
+
import { Response } from "@/components/response";
|
|
8
9
|
|
|
9
10
|
export const Route = createFileRoute("/ai")({
|
|
10
11
|
component: RouteComponent,
|
|
@@ -54,11 +55,7 @@ function RouteComponent() {
|
|
|
54
55
|
</p>
|
|
55
56
|
{message.parts?.map((part, index) => {
|
|
56
57
|
if (part.type === "text") {
|
|
57
|
-
return
|
|
58
|
-
<div key={index} className="whitespace-pre-wrap">
|
|
59
|
-
{part.text}
|
|
60
|
-
</div>
|
|
61
|
-
);
|
|
58
|
+
return <Response key={index}>{part.text}</Response>;
|
|
62
59
|
}
|
|
63
60
|
return null;
|
|
64
61
|
})}
|