create-better-t-stack 3.34.0 → 3.35.1

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.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { _ as types_exports, i as SchemaNameSchema, l as create, m as getSchemaResult, s as add, u as createBtsCli, v as getLatestCLIVersion } from "./src-_FzI_58B.mjs";
2
+ import { _ as types_exports, i as SchemaNameSchema, l as create, m as getSchemaResult, s as add, u as createBtsCli, v as getLatestCLIVersion } from "./src-CTOHjSfr.mjs";
3
3
  import z from "zod";
4
4
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
5
5
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
package/dist/index.mjs CHANGED
@@ -1,3 +1,3 @@
1
1
  #!/usr/bin/env node
2
- import { C as ProjectCreationError, S as DirectoryConflictError, T as ValidationError, a as TEMPLATE_COUNT, b as CompatibilityError, 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 UserCancelledError, x as DatabaseSetupError, y as CLIError } from "./src-_FzI_58B.mjs";
2
+ import { C as ProjectCreationError, S as DirectoryConflictError, T as ValidationError, a as TEMPLATE_COUNT, b as CompatibilityError, 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 UserCancelledError, x as DatabaseSetupError, y as CLIError } from "./src-CTOHjSfr.mjs";
3
3
  export { CLIError, CompatibilityError, DatabaseSetupError, DirectoryConflictError, EMBEDDED_TEMPLATES, GeneratorError, ProjectCreationError, Result, SchemaNameSchema, TEMPLATE_COUNT, UserCancelledError, ValidationError, VirtualFileSystem, add, builder, create, createBtsCli, createVirtual, docs, generate, getSchemaResult, router, sponsors };
@@ -735,6 +735,8 @@ const TASK_RUNNER_ADDONS$1 = [
735
735
  "nx",
736
736
  "vite-plus"
737
737
  ];
738
+ const STATIC_DESKTOP_ADDONS = ["tauri", "electrobun"];
739
+ const TAURI_STATIC_EXPORT_FRONTENDS = ["next", "tanstack-start"];
738
740
  const CONVEX_BETTER_AUTH_INCOMPATIBLE_FRONTENDS = [
739
741
  "nuxt",
740
742
  "svelte",
@@ -881,11 +883,19 @@ function validateDockerServerDeploy(serverDeploy, backend, runtime) {
881
883
  if (runtime === "workers") return validationErr$1("'--server-deploy docker' is not compatible with '--runtime workers'. Use '--runtime bun' or '--runtime node', or choose '--server-deploy cloudflare'.");
882
884
  return Result.ok(void 0);
883
885
  }
884
- function validateAddonCompatibility(addon, frontend, _auth, backend, runtime) {
886
+ function validateAddonCompatibility(addon, frontend, auth, backend, runtime) {
885
887
  if (addon === "evlog" && !supportsEvlogAddon(frontend, backend, runtime)) return {
886
888
  isCompatible: false,
887
889
  reason: evlogCompatibilityMessage
888
890
  };
891
+ if (backend === "self" && STATIC_DESKTOP_ADDONS.includes(addon)) return {
892
+ isCompatible: false,
893
+ reason: `${addon} addon requires a separate backend or no backend because backend 'self' emits server routes that cannot be bundled as static desktop assets.`
894
+ };
895
+ if (addon === "tauri" && backend === "convex" && auth === "better-auth" && frontend.some((f) => TAURI_STATIC_EXPORT_FRONTENDS.includes(f))) return {
896
+ isCompatible: false,
897
+ reason: "tauri addon is not compatible with Convex Better Auth on Next.js or TanStack Start because those templates use server auth bootstrap and cannot be exported as static desktop assets."
898
+ };
889
899
  const compatibleFrontends = ADDON_COMPATIBILITY[addon];
890
900
  if (compatibleFrontends.length > 0) {
891
901
  if (!frontend.some((f) => compatibleFrontends.includes(f))) return {
@@ -1511,13 +1521,6 @@ function getAuthImportLine(config) {
1511
1521
  function getAuthExpression(config) {
1512
1522
  return usesCreateAuthFactory(config) ? "createAuth()" : "auth";
1513
1523
  }
1514
- function addAiSdkEvlogTelemetry(content, loggerExpression) {
1515
- let nextContent = addNamedImport(content, "evlog/ai", ["createAILogger", "createEvlogIntegration"]);
1516
- if (!nextContent.includes("const ai = createAILogger(")) nextContent = nextContent.replace(/^(\s*)const model = wrapLanguageModel\({/m, (_match, indent) => `${indent}const ai = createAILogger(${loggerExpression});\n${indent}const model = wrapLanguageModel({`);
1517
- if (!nextContent.includes("model: ai.wrap(model)")) nextContent = nextContent.replace(/(const result = streamText\({\n\s*)model,/, "$1model: ai.wrap(model),");
1518
- if (!nextContent.includes("createEvlogIntegration(ai)")) nextContent = nextContent.replace(/(messages:\s*await convertToModelMessages\([^)]+\),?)/, (match) => `${match.endsWith(",") ? match : `${match},`}\n\t\texperimental_telemetry: {\n\t\t\tisEnabled: true,\n\t\t\tintegrations: [createEvlogIntegration(ai)],\n\t\t},`);
1519
- return nextContent;
1520
- }
1521
1524
  function addEvlogBetterAuthServerSetup(content, backend, authExpression) {
1522
1525
  let nextContent = addNamedImport(content, "evlog/better-auth", ["createAuthMiddleware", "type BetterAuthInstance"]);
1523
1526
  const usesAuthFactory = authExpression.endsWith("()");
@@ -1650,21 +1653,6 @@ function addNextAiEvlogSetup(content) {
1650
1653
  }
1651
1654
  return nextContent;
1652
1655
  }
1653
- function addNuxtAiEvlogSetup(content) {
1654
- return addAiSdkEvlogTelemetry(content, "useLogger(event)");
1655
- }
1656
- function addSvelteAiEvlogSetup(content) {
1657
- return addAiSdkEvlogTelemetry(content.replace("export const POST: RequestHandler = async ({ request }) => {", "export const POST: RequestHandler = async ({ request, locals }) => {"), "locals.log");
1658
- }
1659
- function addTanstackStartAiEvlogSetup(content) {
1660
- return addAiSdkEvlogTelemetry(prependMissingImports(content, ["import type { RequestLogger } from \"evlog\";", "import { useRequest } from \"nitro/context\";"]), "useRequest().context.log as RequestLogger");
1661
- }
1662
- function addBackendAiEvlogSetup(content, backend) {
1663
- if (backend === "hono") return addAiSdkEvlogTelemetry(content, "c.get(\"log\")");
1664
- if (backend === "express") return addAiSdkEvlogTelemetry(content, "req.log");
1665
- if (backend === "fastify") return addAiSdkEvlogTelemetry(addNamedImport(content, "evlog/fastify", ["useLogger"]), "useLogger()");
1666
- return addAiSdkEvlogTelemetry(content, "context.log");
1667
- }
1668
1656
  function addNextBetterAuthToRoute(content) {
1669
1657
  let nextContent = addNamedImport(content, "@/lib/evlog-auth", ["identifyEvlogUser"]);
1670
1658
  nextContent = nextContent.replace("function handler(req:", "async function handler(req:");
@@ -1704,7 +1692,7 @@ function addAstroBetterAuthEvlogSetup(content, config) {
1704
1692
  }
1705
1693
  function getNextEvlogFile(serviceName) {
1706
1694
  return `import { createEvlog } from "evlog/next";
1707
- import { createInstrumentation } from "evlog/next/instrumentation";
1695
+ import { createInstrumentation } from "evlog/next/instrumentation/create";
1708
1696
 
1709
1697
  export const { withEvlog, useLogger, log, createError } = createEvlog({
1710
1698
  service: "${serviceName}",
@@ -1908,7 +1896,6 @@ async function setupNuxtEvlog(config, serviceName) {
1908
1896
  const authMiddlewarePath = path.join(webDir, "server/middleware/evlog-auth.ts");
1909
1897
  if (!await fs.pathExists(authMiddlewarePath)) await writeFileIfChanged(authMiddlewarePath, getNuxtEvlogAuthMiddlewareFile(config));
1910
1898
  }
1911
- if (config.examples.includes("ai")) await updateFileIfExists(path.join(webDir, "server/api/ai.post.ts"), addNuxtAiEvlogSetup);
1912
1899
  }
1913
1900
  async function setupSvelteEvlog(config, serviceName) {
1914
1901
  const webDir = path.join(config.projectDir, "apps/web");
@@ -1921,7 +1908,6 @@ export const { handle, handleError } = createEvlogHooks();
1921
1908
  `);
1922
1909
  await updateFileIfExists(path.join(webDir, "src/app.d.ts"), addSvelteLocalsType);
1923
1910
  if (shouldIdentifyWebAuth(config)) await updateFileIfExists(path.join(webDir, "src/hooks.server.ts"), (content) => addSvelteBetterAuthEvlogSetup(content, config));
1924
- if (config.examples.includes("ai")) await updateFileIfExists(path.join(webDir, "src/routes/api/ai/+server.ts"), addSvelteAiEvlogSetup);
1925
1911
  }
1926
1912
  async function setupTanstackStartEvlog(config, serviceName) {
1927
1913
  const webDir = path.join(config.projectDir, "apps/web");
@@ -1932,7 +1918,6 @@ async function setupTanstackStartEvlog(config, serviceName) {
1932
1918
  const authPluginPath = path.join(webDir, "server/plugins/evlog-auth.ts");
1933
1919
  if (!await fs.pathExists(authPluginPath)) await writeFileIfChanged(authPluginPath, getNitroEvlogAuthPluginFile(config));
1934
1920
  }
1935
- if (config.examples.includes("ai")) await updateFileIfExists(path.join(webDir, "src/routes/api/ai/$.ts"), addTanstackStartAiEvlogSetup);
1936
1921
  }
1937
1922
  async function setupAstroEvlog(config, serviceName) {
1938
1923
  const webDir = path.join(config.projectDir, "apps/web");
@@ -1963,7 +1948,6 @@ async function setupEvlog(config) {
1963
1948
  const content = await fs.readFile(serverIndexPath, "utf-8");
1964
1949
  let nextContent = addEvlogServerSetup(content, config.backend, `${config.projectName}-server`);
1965
1950
  if (config.auth === "better-auth") nextContent = addEvlogBetterAuthServerSetup(nextContent, config.backend, getAuthExpression(config));
1966
- if (config.examples.includes("ai")) nextContent = addBackendAiEvlogSetup(nextContent, config.backend);
1967
1951
  if (nextContent !== content) await fs.writeFile(serverIndexPath, nextContent);
1968
1952
  }
1969
1953
  }
@@ -6915,11 +6899,10 @@ async function displayPostInstallInstructions(config) {
6915
6899
  const hasWeb = frontend?.some((f) => types_exports.desktopWebFrontends.includes(f));
6916
6900
  const hasNative = frontend?.includes("native-bare") || frontend?.includes("native-uniwind") || frontend?.includes("native-unistyles");
6917
6901
  const hasReactRouter = frontend?.includes("react-router");
6918
- const hasTanStackRouter = frontend?.includes("tanstack-router");
6919
6902
  const hasSvelte = frontend?.includes("svelte");
6920
6903
  const hasAstro = frontend?.includes("astro");
6921
- const webPort = hasReactRouter || hasTanStackRouter || hasSvelte ? "5173" : hasAstro ? "4321" : "3001";
6922
- const betterAuthConvexInstructions = isConvex && config.auth === "better-auth" ? getBetterAuthConvexInstructions(hasWeb ?? false, webPort, packageManager) : "";
6904
+ const webPort = hasReactRouter || hasSvelte ? "5173" : hasAstro ? "4321" : "3001";
6905
+ const betterAuthConvexInstructions = isConvex && config.auth === "better-auth" ? getBetterAuthConvexInstructions(hasWeb ?? false, webPort, packageManager, runCmd) : "";
6923
6906
  const polarInstructions = config.payments === "polar" && config.auth === "better-auth" ? getPolarInstructions(backend, packageManager) : "";
6924
6907
  const bunWebNativeWarning = packageManager === "bun" && hasNative && hasWeb ? getBunWebNativeWarning() : "";
6925
6908
  const noOrmWarning = !isConvex && database !== "none" && orm === "none" ? getNoOrmWarning() : "";
@@ -6981,7 +6964,7 @@ async function displayPostInstallInstructions(config) {
6981
6964
  function getNativeInstructions(isConvex, isBackendSelf, frontend, runCmd) {
6982
6965
  const envVar = isConvex ? "EXPO_PUBLIC_CONVEX_URL" : "EXPO_PUBLIC_SERVER_URL";
6983
6966
  const selfBackendPort = frontend.includes("svelte") ? "5173" : frontend.includes("astro") ? "4321" : "3001";
6984
- const exampleUrl = isConvex ? "https://<YOUR_CONVEX_URL>" : isBackendSelf ? `http://<YOUR_LOCAL_IP>:${selfBackendPort}` : "http://<YOUR_LOCAL_IP>:3000";
6967
+ const exampleUrl = isConvex ? "https://example.convex.cloud" : isBackendSelf ? `http://<YOUR_LOCAL_IP>:${selfBackendPort}` : "http://<YOUR_LOCAL_IP>:3000";
6985
6968
  const envFileName = ".env";
6986
6969
  const ipNote = isConvex ? "your Convex deployment URL (find after running 'dev:setup')" : "your local IP address";
6987
6970
  let instructions = `${pc.yellow("NOTE:")} For Expo connectivity issues, update\n apps/native/${envFileName} with ${ipNote}:\n ${`${envVar}=${exampleUrl}`}\n`;
@@ -7047,7 +7030,7 @@ function getTauriInstructions(runCmd, frontend) {
7047
7030
  }
7048
7031
  function getElectrobunInstructions(runCmd, frontend) {
7049
7032
  const staticBuildNote = getDesktopStaticBuildNote(frontend);
7050
- return `\n${pc.bold("Desktop app with Electrobun:")}\n${pc.cyan("•")} Start desktop app with HMR: ${`${runCmd} dev:desktop`}\n${pc.cyan("•")} Build stable desktop app (DMG/App): ${`${runCmd} build:desktop`}\n${pc.cyan("•")} Build canary desktop app: ${`${runCmd} build:desktop:canary`}\n${pc.yellow("NOTE:")} Electrobun wraps your web frontend in a desktop shell.\n See: https://blackboard.sh/electrobun/docs/${staticBuildNote ? `\n${staticBuildNote}` : ""}`;
7033
+ return `\n${pc.bold("Desktop app with Electrobun:")}\n${pc.cyan("•")} Start desktop app with HMR: ${`${runCmd} dev:desktop`}\n${pc.cyan("•")} Build stable desktop app (DMG/App): ${`${runCmd} build:desktop`}\n${pc.cyan("•")} Build canary desktop app: ${`${runCmd} build:desktop:canary`}\n${pc.yellow("NOTE:")} Electrobun wraps your web frontend in a desktop shell.\n See: https://framework.blackboard.sh/electrobun/${staticBuildNote ? `\n${staticBuildNote}` : ""}`;
7051
7034
  }
7052
7035
  function getPwaInstructions() {
7053
7036
  return `\n${pc.bold("PWA with React Router v7:")}\n${pc.yellow("NOTE:")} There is a known compatibility issue between VitePWA\n and React Router v7. See:\n https://github.com/vite-pwa/vite-plugin-pwa/issues/809`;
@@ -7120,9 +7103,9 @@ function getClerkInstructions(frontend, backend, api) {
7120
7103
  ...getClerkInstructionLines(frontend, backend, api).map((line) => `${pc.cyan("•")} ${line}`)
7121
7104
  ].join("\n");
7122
7105
  }
7123
- function getBetterAuthConvexInstructions(hasWeb, webPort, packageManager) {
7106
+ function getBetterAuthConvexInstructions(hasWeb, webPort, packageManager, runCmd) {
7124
7107
  const cmd = packageManager === "npm" ? "npx" : packageManager;
7125
- return `${pc.bold("Better Auth + Convex Setup:")}\n${pc.cyan("•")} Set environment variables from ${pc.white("packages/backend")}:\n${pc.white(" cd packages/backend")}\n${pc.white(` ${cmd} convex env set BETTER_AUTH_SECRET=$(openssl rand -base64 32)`)}\n` + (hasWeb ? `${pc.white(` ${cmd} convex env set SITE_URL http://localhost:${webPort}`)}\n` : "");
7108
+ return `${pc.bold("Better Auth + Convex Setup:")}\n${pc.cyan("•")} Configure the Convex deployment before setting env vars:\n${pc.white(` ${runCmd} dev:setup`)}\n${pc.cyan("•")} Set environment variables from ${pc.white("packages/backend")}:\n${pc.white(" cd packages/backend")}\n${pc.white(` ${cmd} convex env set BETTER_AUTH_SECRET=$(openssl rand -base64 32)`)}\n` + (hasWeb ? `${pc.white(` ${cmd} convex env set SITE_URL http://localhost:${webPort}`)}\n` : "");
7126
7109
  }
7127
7110
  function getPolarInstructions(backend, packageManager) {
7128
7111
  if (backend === "convex") {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-better-t-stack",
3
- "version": "3.34.0",
3
+ "version": "3.35.1",
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.34.0",
73
- "@better-t-stack/types": "^3.34.0",
72
+ "@better-t-stack/template-generator": "^3.35.1",
73
+ "@better-t-stack/types": "^3.35.1",
74
74
  "@clack/core": "^1.4.1",
75
75
  "@clack/prompts": "^1.5.1",
76
76
  "@modelcontextprotocol/sdk": "1.29.0",