create-better-t-stack 3.25.5 → 3.26.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/README.md +3 -3
- package/dist/cli.mjs +1 -1
- package/dist/index.mjs +1 -1
- package/dist/{src-p8a66ui5.mjs → src-Kus6HC8q.mjs} +179 -96
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -32,14 +32,14 @@ Follow the prompts to configure your project or use the `--yes` flag for default
|
|
|
32
32
|
| Category | Options |
|
|
33
33
|
| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
34
34
|
| **TypeScript** | End-to-end type safety across all parts of your application |
|
|
35
|
-
| **Frontend** | • React with TanStack Router<br>• React with React Router<br>• React with TanStack Start (SSR)<br>• Next.js<br>• SvelteKit<br>• Nuxt (Vue)<br>• SolidJS<br>• React Native with NativeWind (via Expo)<br>• React Native with Unistyles (via Expo)<br>• None
|
|
36
|
-
| **Backend** | • Hono<br>• Express<br>• Elysia<br>•
|
|
35
|
+
| **Frontend** | • React with TanStack Router<br>• React with React Router<br>• React with TanStack Start (SSR)<br>• Next.js<br>• SvelteKit<br>• Nuxt (Vue)<br>• SolidJS<br>• Astro<br>• React Native bare Expo<br>• React Native with NativeWind (via Expo)<br>• React Native with Unistyles (via Expo)<br>• None |
|
|
36
|
+
| **Backend** | • Hono<br>• Express<br>• Elysia<br>• Fastify<br>• Self (fullstack inside the web app)<br>• Convex<br>• None |
|
|
37
37
|
| **API Layer** | • tRPC (type-safe APIs)<br>• oRPC (OpenAPI-compatible type-safe APIs)<br>• None |
|
|
38
38
|
| **Runtime** | • Bun<br>• Node.js<br>• Cloudflare Workers<br>• None |
|
|
39
39
|
| **Database** | • SQLite<br>• PostgreSQL<br>• MySQL<br>• MongoDB<br>• None |
|
|
40
40
|
| **ORM** | • Drizzle (TypeScript-first)<br>• Prisma (feature-rich)<br>• Mongoose (for MongoDB)<br>• None |
|
|
41
41
|
| **Database Setup** | • Turso (SQLite)<br>• Cloudflare D1 (SQLite)<br>• Neon (PostgreSQL)<br>• Supabase (PostgreSQL)<br>• Prisma Postgres<br>• MongoDB Atlas<br>• None (manual setup) |
|
|
42
|
-
| **Authentication** | Better
|
|
42
|
+
| **Authentication** | • Better Auth<br>• Clerk |
|
|
43
43
|
| **Styling** | Tailwind CSS with a shared shadcn/ui package for React web apps |
|
|
44
44
|
| **Addons** | • PWA support<br>• Tauri (desktop applications)<br>• Electrobun (lightweight desktop shell)<br>• Starlight and Fumadocs (documentation sites)<br>• Biome, Oxlint, Ultracite (linting and formatting)<br>• Lefthook, Husky (Git hooks)<br>• MCP, Skills (agent tooling)<br>• OpenTUI, WXT (platform extensions)<br>• Turborepo or Nx (monorepo orchestration) |
|
|
45
45
|
| **Examples** | • Todo app<br>• AI Chat interface (using Vercel AI SDK) |
|
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-
|
|
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-Kus6HC8q.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-
|
|
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-Kus6HC8q.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 };
|
|
@@ -12,7 +12,7 @@ import envPaths from "env-paths";
|
|
|
12
12
|
import fs from "fs-extra";
|
|
13
13
|
import { fileURLToPath } from "node:url";
|
|
14
14
|
import { desktopWebFrontends as desktopWebFrontends$3 } from "@better-t-stack/types";
|
|
15
|
-
import { EMBEDDED_TEMPLATES, EMBEDDED_TEMPLATES as EMBEDDED_TEMPLATES$1, GeneratorError as GeneratorError$1, TEMPLATE_COUNT, VirtualFileSystem, VirtualFileSystem as VirtualFileSystem$1, dependencyVersionMap, generate, generate as generate$1, generateReproducibleCommand, processAddonTemplates, processAddonsDeps } from "@better-t-stack/template-generator";
|
|
15
|
+
import { EMBEDDED_TEMPLATES, EMBEDDED_TEMPLATES as EMBEDDED_TEMPLATES$1, GeneratorError, GeneratorError as GeneratorError$1, TEMPLATE_COUNT, VirtualFileSystem, VirtualFileSystem as VirtualFileSystem$1, dependencyVersionMap, generate, generate as generate$1, generateReproducibleCommand, processAddonTemplates, processAddonsDeps } from "@better-t-stack/template-generator";
|
|
16
16
|
import { consola, createConsola } from "consola";
|
|
17
17
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
18
18
|
import gradient from "gradient-string";
|
|
@@ -728,6 +728,21 @@ const WEB_FRAMEWORKS = [
|
|
|
728
728
|
];
|
|
729
729
|
//#endregion
|
|
730
730
|
//#region src/utils/compatibility-rules.ts
|
|
731
|
+
const CONVEX_BETTER_AUTH_INCOMPATIBLE_FRONTENDS = [
|
|
732
|
+
"nuxt",
|
|
733
|
+
"svelte",
|
|
734
|
+
"solid",
|
|
735
|
+
"astro"
|
|
736
|
+
];
|
|
737
|
+
const CONVEX_BETTER_AUTH_SUPPORTED_FRONTENDS = [
|
|
738
|
+
"tanstack-router",
|
|
739
|
+
"react-router",
|
|
740
|
+
"tanstack-start",
|
|
741
|
+
"next",
|
|
742
|
+
"native-bare",
|
|
743
|
+
"native-uniwind",
|
|
744
|
+
"native-unistyles"
|
|
745
|
+
];
|
|
731
746
|
function validationErr$1(message) {
|
|
732
747
|
return Result.err(new ValidationError({ message }));
|
|
733
748
|
}
|
|
@@ -781,8 +796,11 @@ function validateApiFrontendCompatibility(api, frontends = []) {
|
|
|
781
796
|
return Result.ok(void 0);
|
|
782
797
|
}
|
|
783
798
|
function isFrontendAllowedWithBackend(frontend, backend, auth) {
|
|
784
|
-
if (backend === "convex"
|
|
785
|
-
|
|
799
|
+
if (backend === "convex") {
|
|
800
|
+
if (auth === "better-auth" && CONVEX_BETTER_AUTH_INCOMPATIBLE_FRONTENDS.includes(frontend)) return false;
|
|
801
|
+
if (frontend === "solid" || frontend === "astro") return false;
|
|
802
|
+
}
|
|
803
|
+
if (auth === "clerk") {
|
|
786
804
|
if ([
|
|
787
805
|
"nuxt",
|
|
788
806
|
"svelte",
|
|
@@ -792,6 +810,9 @@ function isFrontendAllowedWithBackend(frontend, backend, auth) {
|
|
|
792
810
|
}
|
|
793
811
|
return true;
|
|
794
812
|
}
|
|
813
|
+
function supportsConvexBetterAuth(frontends = []) {
|
|
814
|
+
return frontends.some((frontend) => CONVEX_BETTER_AUTH_SUPPORTED_FRONTENDS.includes(frontend));
|
|
815
|
+
}
|
|
795
816
|
function allowedApisForFrontends(frontends = []) {
|
|
796
817
|
const includesNuxt = frontends.includes("nuxt");
|
|
797
818
|
const includesSvelte = frontends.includes("svelte");
|
|
@@ -3215,63 +3236,52 @@ async function getApiChoice(Api, frontend, backend) {
|
|
|
3215
3236
|
}
|
|
3216
3237
|
//#endregion
|
|
3217
3238
|
//#region src/prompts/auth.ts
|
|
3218
|
-
|
|
3219
|
-
if (
|
|
3220
|
-
|
|
3239
|
+
function getAvailableAuthProviders(backend, frontend = []) {
|
|
3240
|
+
if (backend === "none") return ["none"];
|
|
3241
|
+
const hasClerkCompatibleFrontends = frontend.some((f) => [
|
|
3242
|
+
"react-router",
|
|
3243
|
+
"tanstack-router",
|
|
3244
|
+
"tanstack-start",
|
|
3245
|
+
"next",
|
|
3246
|
+
"native-bare",
|
|
3247
|
+
"native-uniwind",
|
|
3248
|
+
"native-unistyles"
|
|
3249
|
+
].includes(f));
|
|
3250
|
+
const options = [];
|
|
3221
3251
|
if (backend === "convex") {
|
|
3222
|
-
|
|
3223
|
-
|
|
3224
|
-
|
|
3225
|
-
|
|
3226
|
-
|
|
3227
|
-
|
|
3228
|
-
|
|
3229
|
-
|
|
3230
|
-
|
|
3231
|
-
|
|
3232
|
-
|
|
3233
|
-
|
|
3234
|
-
"
|
|
3235
|
-
|
|
3236
|
-
|
|
3237
|
-
|
|
3238
|
-
|
|
3239
|
-
|
|
3240
|
-
|
|
3241
|
-
|
|
3242
|
-
|
|
3243
|
-
|
|
3244
|
-
|
|
3245
|
-
|
|
3246
|
-
|
|
3247
|
-
|
|
3248
|
-
|
|
3249
|
-
}
|
|
3250
|
-
|
|
3251
|
-
options.push({
|
|
3252
|
-
value: "none",
|
|
3253
|
-
label: "None",
|
|
3254
|
-
hint: "No auth"
|
|
3255
|
-
});
|
|
3256
|
-
const response = await navigableSelect({
|
|
3257
|
-
message: "Select authentication provider",
|
|
3258
|
-
options,
|
|
3259
|
-
initialValue: "none"
|
|
3260
|
-
});
|
|
3261
|
-
if (isCancel$1(response)) throw new UserCancelledError({ message: "Operation cancelled" });
|
|
3262
|
-
return response;
|
|
3263
|
-
}
|
|
3252
|
+
if (supportsConvexBetterAuth(frontend)) options.push("better-auth");
|
|
3253
|
+
} else options.push("better-auth");
|
|
3254
|
+
if (hasClerkCompatibleFrontends) options.push("clerk");
|
|
3255
|
+
if (options.length === 0) return ["none"];
|
|
3256
|
+
return [...options, "none"];
|
|
3257
|
+
}
|
|
3258
|
+
async function getAuthChoice(auth, backend, frontend = []) {
|
|
3259
|
+
if (auth !== void 0) return auth;
|
|
3260
|
+
const availableProviders = getAvailableAuthProviders(backend, frontend);
|
|
3261
|
+
if (availableProviders.length === 1 && availableProviders[0] === "none") return "none";
|
|
3262
|
+
const options = availableProviders.map((provider) => {
|
|
3263
|
+
switch (provider) {
|
|
3264
|
+
case "better-auth": return {
|
|
3265
|
+
value: "better-auth",
|
|
3266
|
+
label: "Better-Auth",
|
|
3267
|
+
hint: "comprehensive auth framework for TypeScript"
|
|
3268
|
+
};
|
|
3269
|
+
case "clerk": return {
|
|
3270
|
+
value: "clerk",
|
|
3271
|
+
label: "Clerk",
|
|
3272
|
+
hint: "More than auth, Complete User Management"
|
|
3273
|
+
};
|
|
3274
|
+
default: return {
|
|
3275
|
+
value: "none",
|
|
3276
|
+
label: "None",
|
|
3277
|
+
hint: "No auth"
|
|
3278
|
+
};
|
|
3279
|
+
}
|
|
3280
|
+
});
|
|
3264
3281
|
const response = await navigableSelect({
|
|
3265
3282
|
message: "Select authentication provider",
|
|
3266
|
-
options
|
|
3267
|
-
|
|
3268
|
-
label: "Better-Auth",
|
|
3269
|
-
hint: "comprehensive auth framework for TypeScript"
|
|
3270
|
-
}, {
|
|
3271
|
-
value: "none",
|
|
3272
|
-
label: "None"
|
|
3273
|
-
}],
|
|
3274
|
-
initialValue: DEFAULT_CONFIG.auth
|
|
3283
|
+
options,
|
|
3284
|
+
initialValue: options.some((option) => option.value === DEFAULT_CONFIG.auth) ? DEFAULT_CONFIG.auth : "none"
|
|
3275
3285
|
});
|
|
3276
3286
|
if (isCancel$1(response)) throw new UserCancelledError({ message: "Operation cancelled" });
|
|
3277
3287
|
return response;
|
|
@@ -4363,15 +4373,10 @@ function validateConvexConstraints(config, providedFlags) {
|
|
|
4363
4373
|
if (has("dbSetup") && config.dbSetup !== "none") return validationErr("Convex backend requires '--db-setup none'. Please remove the --db-setup flag or set it to 'none'.");
|
|
4364
4374
|
if (has("serverDeploy") && config.serverDeploy !== "none") return validationErr("Convex backend requires '--server-deploy none'. Please remove the --server-deploy flag or set it to 'none'.");
|
|
4365
4375
|
if (has("auth") && config.auth === "better-auth") {
|
|
4366
|
-
const
|
|
4367
|
-
|
|
4368
|
-
|
|
4369
|
-
|
|
4370
|
-
"native-bare",
|
|
4371
|
-
"native-uniwind",
|
|
4372
|
-
"native-unistyles"
|
|
4373
|
-
];
|
|
4374
|
-
if (!config.frontend?.some((f) => supportedFrontends.includes(f))) return validationErr("Better-Auth with Convex backend requires a supported frontend (TanStack Router, TanStack Start, Next.js, or Native).");
|
|
4376
|
+
const incompatibleFrontends = config.frontend?.filter((f) => CONVEX_BETTER_AUTH_INCOMPATIBLE_FRONTENDS.includes(f)) ?? [];
|
|
4377
|
+
const hasSupportedFrontend = supportsConvexBetterAuth(config.frontend);
|
|
4378
|
+
if (incompatibleFrontends.length > 0) return validationErr(`Better Auth with '--backend convex' is not compatible with the following frontends: ${incompatibleFrontends.join(", ")}. Please use a React-based web frontend (next, tanstack-start, tanstack-router, react-router), a supported native frontend, or choose a different auth provider.`);
|
|
4379
|
+
if (!hasSupportedFrontend) return validationErr(`Better Auth with '--backend convex' requires a supported frontend (${CONVEX_BETTER_AUTH_SUPPORTED_FRONTENDS.join(", ")}).`);
|
|
4375
4380
|
}
|
|
4376
4381
|
return Result.ok(void 0);
|
|
4377
4382
|
}
|
|
@@ -4398,12 +4403,12 @@ function validateSelfBackendConstraints(config, providedFlags) {
|
|
|
4398
4403
|
}
|
|
4399
4404
|
function validateBackendConstraints(config, providedFlags, options) {
|
|
4400
4405
|
const { backend } = config;
|
|
4401
|
-
if (config.auth === "clerk" &&
|
|
4402
|
-
if (backend === "convex" && config.auth === "clerk" && config.frontend) {
|
|
4406
|
+
if (config.auth === "clerk" && config.frontend) {
|
|
4403
4407
|
const incompatibleFrontends = config.frontend.filter((f) => [
|
|
4404
4408
|
"nuxt",
|
|
4405
4409
|
"svelte",
|
|
4406
|
-
"solid"
|
|
4410
|
+
"solid",
|
|
4411
|
+
"astro"
|
|
4407
4412
|
].includes(f));
|
|
4408
4413
|
if (incompatibleFrontends.length > 0) return validationErr(`Clerk authentication is not compatible with the following frontends: ${incompatibleFrontends.join(", ")}. Please choose a different frontend or auth provider.`);
|
|
4409
4414
|
}
|
|
@@ -5999,15 +6004,16 @@ async function displayPostInstallInstructions(config) {
|
|
|
5999
6004
|
const nativeInstructions = (frontend?.includes("native-bare") || frontend?.includes("native-uniwind") || frontend?.includes("native-unistyles")) && backend !== "none" ? getNativeInstructions(isConvex, isBackendSelf, frontend || [], runCmd) : "";
|
|
6000
6005
|
const pwaInstructions = addons?.includes("pwa") && frontend?.includes("react-router") ? getPwaInstructions() : "";
|
|
6001
6006
|
const starlightInstructions = addons?.includes("starlight") ? getStarlightInstructions(runCmd) : "";
|
|
6002
|
-
const clerkInstructions =
|
|
6007
|
+
const clerkInstructions = config.auth === "clerk" ? getClerkInstructions(frontend || [], backend, api) : "";
|
|
6003
6008
|
const polarInstructions = config.payments === "polar" && config.auth === "better-auth" ? getPolarInstructions(backend) : "";
|
|
6004
6009
|
const alchemyDeployInstructions = getAlchemyDeployInstructions(runCmd, webDeploy, serverDeploy, backend);
|
|
6005
6010
|
const hasWeb = frontend?.some((f) => types_exports.desktopWebFrontends.includes(f));
|
|
6006
6011
|
const hasNative = frontend?.includes("native-bare") || frontend?.includes("native-uniwind") || frontend?.includes("native-unistyles");
|
|
6007
6012
|
const hasReactRouter = frontend?.includes("react-router");
|
|
6013
|
+
const hasTanStackRouter = frontend?.includes("tanstack-router");
|
|
6008
6014
|
const hasSvelte = frontend?.includes("svelte");
|
|
6009
6015
|
const hasAstro = frontend?.includes("astro");
|
|
6010
|
-
const webPort = hasReactRouter || hasSvelte ? "5173" : hasAstro ? "4321" : "3001";
|
|
6016
|
+
const webPort = hasReactRouter || hasTanStackRouter || hasSvelte ? "5173" : hasAstro ? "4321" : "3001";
|
|
6011
6017
|
const betterAuthConvexInstructions = isConvex && config.auth === "better-auth" ? getBetterAuthConvexInstructions(hasWeb ?? false, webPort, packageManager) : "";
|
|
6012
6018
|
const bunWebNativeWarning = packageManager === "bun" && hasNative && hasWeb ? getBunWebNativeWarning() : "";
|
|
6013
6019
|
const noOrmWarning = !isConvex && database !== "none" && orm === "none" ? getNoOrmWarning() : "";
|
|
@@ -6140,8 +6146,64 @@ function getNoOrmWarning() {
|
|
|
6140
6146
|
function getBunWebNativeWarning() {
|
|
6141
6147
|
return `\n${pc.yellow("WARNING:")} 'bun' might cause issues with web + native apps in a monorepo.\n Use 'pnpm' if problems arise.`;
|
|
6142
6148
|
}
|
|
6143
|
-
function
|
|
6144
|
-
|
|
6149
|
+
function getClerkQuickstartUrl(frontend) {
|
|
6150
|
+
if (frontend.includes("next")) return "https://clerk.com/docs/nextjs/getting-started/quickstart";
|
|
6151
|
+
if (frontend.includes("react-router")) return "https://clerk.com/docs/react-router/getting-started/quickstart";
|
|
6152
|
+
if (frontend.includes("tanstack-start")) return "https://clerk.com/docs/tanstack-react-start/getting-started/quickstart";
|
|
6153
|
+
if (frontend.includes("tanstack-router")) return "https://clerk.com/docs/react/getting-started/quickstart";
|
|
6154
|
+
if (frontend.includes("native-bare") || frontend.includes("native-uniwind") || frontend.includes("native-unistyles")) return "https://clerk.com/docs/expo/getting-started/quickstart";
|
|
6155
|
+
return "https://clerk.com/docs";
|
|
6156
|
+
}
|
|
6157
|
+
function getClerkInstructionLines(frontend, backend, api) {
|
|
6158
|
+
const lines = [];
|
|
6159
|
+
if (frontend.includes("next")) lines.push("Set NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY in apps/web/.env");
|
|
6160
|
+
if (frontend.some((value) => [
|
|
6161
|
+
"react-router",
|
|
6162
|
+
"tanstack-router",
|
|
6163
|
+
"tanstack-start"
|
|
6164
|
+
].includes(value))) lines.push("Set VITE_CLERK_PUBLISHABLE_KEY in apps/web/.env");
|
|
6165
|
+
if (frontend.some((value) => [
|
|
6166
|
+
"native-bare",
|
|
6167
|
+
"native-uniwind",
|
|
6168
|
+
"native-unistyles"
|
|
6169
|
+
].includes(value))) lines.push("Set EXPO_PUBLIC_CLERK_PUBLISHABLE_KEY in apps/native/.env");
|
|
6170
|
+
if (backend === "convex") return [
|
|
6171
|
+
"Set CLERK_JWT_ISSUER_DOMAIN in Convex Dashboard",
|
|
6172
|
+
...lines,
|
|
6173
|
+
...frontend.some((value) => [
|
|
6174
|
+
"next",
|
|
6175
|
+
"react-router",
|
|
6176
|
+
"tanstack-start"
|
|
6177
|
+
].includes(value)) ? ["Set CLERK_SECRET_KEY in apps/web/.env for Clerk server middleware"] : []
|
|
6178
|
+
];
|
|
6179
|
+
const hasClerkServerFrontend = frontend.some((value) => [
|
|
6180
|
+
"next",
|
|
6181
|
+
"react-router",
|
|
6182
|
+
"tanstack-start"
|
|
6183
|
+
].includes(value));
|
|
6184
|
+
const serverEnvPath = backend === "self" ? "apps/web/.env" : "apps/server/.env";
|
|
6185
|
+
const needsServerSideClerkAuth = backend !== "none";
|
|
6186
|
+
const needsClerkBackendPublishableKey = ["express", "fastify"].includes(backend);
|
|
6187
|
+
const needsClerkRequestVerification = api !== "none" && [
|
|
6188
|
+
"self",
|
|
6189
|
+
"hono",
|
|
6190
|
+
"elysia"
|
|
6191
|
+
].includes(backend);
|
|
6192
|
+
if (hasClerkServerFrontend && backend === "self") lines.push("Set CLERK_SECRET_KEY in apps/web/.env for Clerk server middleware and server-side Clerk auth");
|
|
6193
|
+
else {
|
|
6194
|
+
if (hasClerkServerFrontend) lines.push("Set CLERK_SECRET_KEY in apps/web/.env for Clerk server middleware");
|
|
6195
|
+
if (needsServerSideClerkAuth) lines.push(`Set CLERK_SECRET_KEY in ${serverEnvPath} for server-side Clerk auth`);
|
|
6196
|
+
}
|
|
6197
|
+
if (needsClerkRequestVerification) lines.push(`Set CLERK_PUBLISHABLE_KEY in ${serverEnvPath} for server-side Clerk request verification`);
|
|
6198
|
+
if (needsClerkBackendPublishableKey) lines.push(`Set CLERK_PUBLISHABLE_KEY in ${serverEnvPath} for Clerk backend middleware`);
|
|
6199
|
+
return lines;
|
|
6200
|
+
}
|
|
6201
|
+
function getClerkInstructions(frontend, backend, api) {
|
|
6202
|
+
return [
|
|
6203
|
+
`${pc.bold("Clerk Authentication Setup:")}`,
|
|
6204
|
+
`${pc.cyan("•")} Follow the guide: ${pc.underline(getClerkQuickstartUrl(frontend))}`,
|
|
6205
|
+
...getClerkInstructionLines(frontend, backend, api).map((line) => `${pc.cyan("•")} ${line}`)
|
|
6206
|
+
].join("\n");
|
|
6145
6207
|
}
|
|
6146
6208
|
function getBetterAuthConvexInstructions(hasWeb, webPort, packageManager) {
|
|
6147
6209
|
const cmd = packageManager === "npm" ? "npx" : packageManager;
|
|
@@ -6770,30 +6832,51 @@ async function builder() {
|
|
|
6770
6832
|
* ```
|
|
6771
6833
|
*/
|
|
6772
6834
|
async function createVirtual(options) {
|
|
6835
|
+
const config = {
|
|
6836
|
+
projectName: options.projectName || "my-project",
|
|
6837
|
+
projectDir: "/virtual",
|
|
6838
|
+
relativePath: "./virtual",
|
|
6839
|
+
addonOptions: options.addonOptions,
|
|
6840
|
+
dbSetupOptions: options.dbSetupOptions,
|
|
6841
|
+
database: options.database || "none",
|
|
6842
|
+
orm: options.orm || "none",
|
|
6843
|
+
backend: options.backend || "hono",
|
|
6844
|
+
runtime: options.runtime || "bun",
|
|
6845
|
+
frontend: options.frontend || ["tanstack-router"],
|
|
6846
|
+
addons: options.addons || [],
|
|
6847
|
+
examples: options.examples || [],
|
|
6848
|
+
auth: options.auth || "none",
|
|
6849
|
+
payments: options.payments || "none",
|
|
6850
|
+
git: options.git ?? false,
|
|
6851
|
+
packageManager: options.packageManager || "bun",
|
|
6852
|
+
install: false,
|
|
6853
|
+
dbSetup: options.dbSetup || "none",
|
|
6854
|
+
api: options.api || "trpc",
|
|
6855
|
+
webDeploy: options.webDeploy || "none",
|
|
6856
|
+
serverDeploy: options.serverDeploy || "none"
|
|
6857
|
+
};
|
|
6858
|
+
const validationResult = validateConfigCompatibility(config, new Set([
|
|
6859
|
+
"database",
|
|
6860
|
+
"orm",
|
|
6861
|
+
"backend",
|
|
6862
|
+
"runtime",
|
|
6863
|
+
"frontend",
|
|
6864
|
+
"addons",
|
|
6865
|
+
"examples",
|
|
6866
|
+
"auth",
|
|
6867
|
+
"dbSetup",
|
|
6868
|
+
"payments",
|
|
6869
|
+
"api",
|
|
6870
|
+
"webDeploy",
|
|
6871
|
+
"serverDeploy"
|
|
6872
|
+
]), config);
|
|
6873
|
+
if (validationResult.isErr()) return Result.err(new GeneratorError({
|
|
6874
|
+
message: validationResult.error.message,
|
|
6875
|
+
phase: "validation",
|
|
6876
|
+
cause: validationResult.error
|
|
6877
|
+
}));
|
|
6773
6878
|
return generate({
|
|
6774
|
-
config
|
|
6775
|
-
projectName: options.projectName || "my-project",
|
|
6776
|
-
projectDir: "/virtual",
|
|
6777
|
-
relativePath: "./virtual",
|
|
6778
|
-
addonOptions: options.addonOptions,
|
|
6779
|
-
dbSetupOptions: options.dbSetupOptions,
|
|
6780
|
-
database: options.database || "none",
|
|
6781
|
-
orm: options.orm || "none",
|
|
6782
|
-
backend: options.backend || "hono",
|
|
6783
|
-
runtime: options.runtime || "bun",
|
|
6784
|
-
frontend: options.frontend || ["tanstack-router"],
|
|
6785
|
-
addons: options.addons || [],
|
|
6786
|
-
examples: options.examples || [],
|
|
6787
|
-
auth: options.auth || "none",
|
|
6788
|
-
payments: options.payments || "none",
|
|
6789
|
-
git: options.git ?? false,
|
|
6790
|
-
packageManager: options.packageManager || "bun",
|
|
6791
|
-
install: false,
|
|
6792
|
-
dbSetup: options.dbSetup || "none",
|
|
6793
|
-
api: options.api || "trpc",
|
|
6794
|
-
webDeploy: options.webDeploy || "none",
|
|
6795
|
-
serverDeploy: options.serverDeploy || "none"
|
|
6796
|
-
},
|
|
6879
|
+
config,
|
|
6797
6880
|
templates: EMBEDDED_TEMPLATES
|
|
6798
6881
|
});
|
|
6799
6882
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-better-t-stack",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.26.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",
|
|
@@ -70,12 +70,12 @@
|
|
|
70
70
|
"prepublishOnly": "npm run build"
|
|
71
71
|
},
|
|
72
72
|
"dependencies": {
|
|
73
|
-
"@better-t-stack/template-generator": "^3.
|
|
74
|
-
"@better-t-stack/types": "^3.
|
|
73
|
+
"@better-t-stack/template-generator": "^3.26.1",
|
|
74
|
+
"@better-t-stack/types": "^3.26.1",
|
|
75
75
|
"@clack/core": "^1.1.0",
|
|
76
76
|
"@clack/prompts": "^1.1.0",
|
|
77
77
|
"@modelcontextprotocol/sdk": "1.27.1",
|
|
78
|
-
"@trpc/server": "^11.4
|
|
78
|
+
"@trpc/server": "^11.13.4",
|
|
79
79
|
"better-result": "^2.7.0",
|
|
80
80
|
"consola": "^3.4.2",
|
|
81
81
|
"env-paths": "^4.0.0",
|