create-better-t-stack 2.37.0-canary.28c5b8e0 → 2.37.0-canary.6846bd90

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 CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { createBtsCli } from "./src-CzVr9ZoP.js";
2
+ import { createBtsCli } from "./src-ByxWjVSi.js";
3
3
 
4
4
  //#region src/cli.ts
5
5
  createBtsCli().run();
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
1
  #!/usr/bin/env node
2
- import { builder, createBtsCli, docs, init, router, sponsors } from "./src-CzVr9ZoP.js";
2
+ import { builder, createBtsCli, docs, init, router, sponsors } from "./src-ByxWjVSi.js";
3
3
 
4
4
  export { builder, createBtsCli, docs, init, router, sponsors };
@@ -504,7 +504,6 @@ function validateWorkersCompatibility(providedFlags, options, config) {
504
504
  }
505
505
  function coerceBackendPresets(config) {
506
506
  if (config.backend === "convex") {
507
- if (config.auth !== "clerk") config.auth = "none";
508
507
  config.database = "none";
509
508
  config.orm = "none";
510
509
  config.api = "none";
@@ -552,8 +551,16 @@ function validateApiFrontendCompatibility(api, frontends = []) {
552
551
  const includesSolid = frontends.includes("solid");
553
552
  if ((includesNuxt || includesSvelte || includesSolid) && api === "trpc") exitWithError(`tRPC API is not supported with '${includesNuxt ? "nuxt" : includesSvelte ? "svelte" : "solid"}' frontend. Please use --api orpc or --api none or remove '${includesNuxt ? "nuxt" : includesSvelte ? "svelte" : "solid"}' from --frontend.`);
554
553
  }
555
- function isFrontendAllowedWithBackend(frontend, backend) {
554
+ function isFrontendAllowedWithBackend(frontend, backend, auth) {
556
555
  if (backend === "convex" && frontend === "solid") return false;
556
+ if (auth === "clerk" && backend === "convex") {
557
+ const incompatibleFrontends = [
558
+ "nuxt",
559
+ "svelte",
560
+ "solid"
561
+ ];
562
+ if (incompatibleFrontends.includes(frontend)) return false;
563
+ }
557
564
  return true;
558
565
  }
559
566
  function allowedApisForFrontends(frontends = []) {
@@ -639,14 +646,21 @@ async function getApiChoice(Api, frontend, backend) {
639
646
 
640
647
  //#endregion
641
648
  //#region src/prompts/auth.ts
642
- async function getAuthChoice(auth, hasDatabase, backend) {
649
+ async function getAuthChoice(auth, hasDatabase, backend, frontend) {
643
650
  if (auth !== void 0) return auth;
644
651
  if (backend === "convex") {
652
+ const unsupportedFrontends = frontend?.filter((f) => [
653
+ "nuxt",
654
+ "svelte",
655
+ "solid"
656
+ ].includes(f));
657
+ if (unsupportedFrontends && unsupportedFrontends.length > 0) return "none";
645
658
  const response$1 = await select({
646
659
  message: "Select authentication provider",
647
660
  options: [{
648
661
  value: "clerk",
649
- label: "Clerk"
662
+ label: "Clerk",
663
+ hint: "More than auth, Complete User Management"
650
664
  }, {
651
665
  value: "none",
652
666
  label: "None"
@@ -661,7 +675,8 @@ async function getAuthChoice(auth, hasDatabase, backend) {
661
675
  message: "Select authentication provider",
662
676
  options: [{
663
677
  value: "better-auth",
664
- label: "Better-Auth"
678
+ label: "Better-Auth",
679
+ hint: "comprehensive auth framework for TypeScript"
665
680
  }, {
666
681
  value: "none",
667
682
  label: "None"
@@ -887,7 +902,7 @@ async function getExamplesChoice(examples, database, frontends, backend, api) {
887
902
 
888
903
  //#endregion
889
904
  //#region src/prompts/frontend.ts
890
- async function getFrontendChoice(frontendOptions, backend) {
905
+ async function getFrontendChoice(frontendOptions, backend, auth) {
891
906
  if (frontendOptions !== void 0) return frontendOptions;
892
907
  const frontendTypes = await multiselect({
893
908
  message: "Select project type",
@@ -943,7 +958,7 @@ async function getFrontendChoice(frontendOptions, backend) {
943
958
  hint: "SSR, Server Functions, API Routes and more with TanStack Router"
944
959
  }
945
960
  ];
946
- const webOptions = allWebOptions.filter((option) => isFrontendAllowedWithBackend(option.value, backend));
961
+ const webOptions = allWebOptions.filter((option) => isFrontendAllowedWithBackend(option.value, backend, auth));
947
962
  const webFramework = await select({
948
963
  message: "Choose web",
949
964
  options: webOptions,
@@ -1244,13 +1259,13 @@ async function getDeploymentToAdd(frontend, existingDeployment) {
1244
1259
  //#region src/prompts/config-prompts.ts
1245
1260
  async function gatherConfig(flags, projectName, projectDir, relativePath) {
1246
1261
  const result = await group({
1247
- frontend: () => getFrontendChoice(flags.frontend, flags.backend),
1262
+ frontend: () => getFrontendChoice(flags.frontend, flags.backend, flags.auth),
1248
1263
  backend: ({ results }) => getBackendFrameworkChoice(flags.backend, results.frontend),
1249
1264
  runtime: ({ results }) => getRuntimeChoice(flags.runtime, results.backend),
1250
1265
  database: ({ results }) => getDatabaseChoice(flags.database, results.backend, results.runtime),
1251
1266
  orm: ({ results }) => getORMChoice(flags.orm, results.database !== "none", results.database, results.backend, results.runtime),
1252
1267
  api: ({ results }) => getApiChoice(flags.api, results.frontend, results.backend),
1253
- auth: ({ results }) => getAuthChoice(flags.auth, results.database !== "none", results.backend),
1268
+ auth: ({ results }) => getAuthChoice(flags.auth, results.database !== "none", results.backend, results.frontend),
1254
1269
  addons: ({ results }) => getAddonsChoice(flags.addons, results.frontend),
1255
1270
  examples: ({ results }) => getExamplesChoice(flags.examples, results.database, results.frontend, results.backend, results.api),
1256
1271
  dbSetup: ({ results }) => getDBSetupChoice(results.database ?? "none", flags.dbSetup, results.orm, results.backend, results.runtime),
@@ -1724,6 +1739,15 @@ function validateDatabaseSetup(config, providedFlags) {
1724
1739
  function validateBackendConstraints(config, providedFlags, options) {
1725
1740
  const { backend } = config;
1726
1741
  if (config.auth === "clerk" && backend !== "convex") exitWithError("Clerk authentication is only supported with the Convex backend. Please use '--backend convex' or choose a different auth provider.");
1742
+ if (backend === "convex" && config.auth === "clerk" && config.frontend) {
1743
+ const incompatibleFrontends = config.frontend.filter((f) => [
1744
+ "nuxt",
1745
+ "svelte",
1746
+ "solid"
1747
+ ].includes(f));
1748
+ if (incompatibleFrontends.length > 0) exitWithError(`Clerk authentication is not compatible with the following frontends: ${incompatibleFrontends.join(", ")}. Please choose a different frontend or auth provider.`);
1749
+ }
1750
+ if (backend === "convex" && config.auth === "better-auth" && providedFlags.has("auth")) exitWithError("Better-Auth is not compatible with the Convex backend. Please use '--auth clerk' or '--auth none'.");
1727
1751
  if (providedFlags.has("backend") && backend && backend !== "convex" && backend !== "none") {
1728
1752
  if (providedFlags.has("runtime") && options.runtime === "none") exitWithError("'--runtime none' is only supported with '--backend convex' or '--backend none'. Please choose 'bun', 'node', or remove the --runtime flag.");
1729
1753
  }
@@ -2962,7 +2986,7 @@ async function addAddonsToProject(input) {
2962
2986
  frontend: detectedConfig.frontend || [],
2963
2987
  addons: input.addons,
2964
2988
  examples: detectedConfig.examples || [],
2965
- auth: detectedConfig.auth || false,
2989
+ auth: detectedConfig.auth || "none",
2966
2990
  git: false,
2967
2991
  packageManager: input.packageManager || detectedConfig.packageManager || "npm",
2968
2992
  install: input.install || false,
@@ -3734,7 +3758,7 @@ async function addDeploymentToProject(input) {
3734
3758
  frontend: detectedConfig.frontend || [],
3735
3759
  addons: detectedConfig.addons || [],
3736
3760
  examples: detectedConfig.examples || [],
3737
- auth: detectedConfig.auth || false,
3761
+ auth: detectedConfig.auth || "none",
3738
3762
  git: false,
3739
3763
  packageManager: input.packageManager || detectedConfig.packageManager || "npm",
3740
3764
  install: input.install || false,
@@ -5349,7 +5373,7 @@ This project uses Convex as a backend. You'll need to set up Convex before runni
5349
5373
  ${packageManagerRunCmd} dev:setup
5350
5374
  \`\`\`
5351
5375
 
5352
- Follow the prompts to create a new Convex project and connect it to your application.` : generateDatabaseSetup(database, auth, packageManagerRunCmd, orm, options.dbSetup, options.serverDeploy)}
5376
+ Follow the prompts to create a new Convex project and connect it to your application.${auth === "clerk" ? " See [Convex + Clerk guide](https://docs.convex.dev/auth/clerk) for auth setup." : ""}` : generateDatabaseSetup(database, auth, packageManagerRunCmd, orm, options.dbSetup, options.serverDeploy)}
5353
5377
 
5354
5378
  Then, run the development server:
5355
5379
 
@@ -5366,7 +5390,7 @@ ${generateDeploymentCommands(packageManagerRunCmd, webDeploy, serverDeploy)}
5366
5390
  ## Project Structure
5367
5391
 
5368
5392
  \`\`\`
5369
- ${generateProjectStructure(projectName, frontend, backend, addons, isConvex, api)}
5393
+ ${generateProjectStructure(projectName, frontend, backend, addons, isConvex, api, auth)}
5370
5394
  \`\`\`
5371
5395
 
5372
5396
  ## Available Scripts
@@ -5416,7 +5440,7 @@ function generateRunningInstructions(frontend, backend, webPort, hasNative, isCo
5416
5440
  else if (!isBackendNone) instructions.push("The API is running at [http://localhost:3000](http://localhost:3000).");
5417
5441
  return instructions.join("\n");
5418
5442
  }
5419
- function generateProjectStructure(projectName, frontend, backend, addons, isConvex, api) {
5443
+ function generateProjectStructure(projectName, frontend, backend, addons, isConvex, api, auth) {
5420
5444
  const structure = [`${projectName}/`, "├── apps/"];
5421
5445
  const hasFrontendNone = frontend.length === 0 || frontend.includes("none");
5422
5446
  const isBackendNone = backend === "none";
@@ -5446,6 +5470,7 @@ function generateProjectStructure(projectName, frontend, backend, addons, isConv
5446
5470
  if (isConvex) {
5447
5471
  structure.push("├── packages/");
5448
5472
  structure.push("│ └── backend/ # Convex backend functions and schema");
5473
+ if (auth === "clerk") structure.push("│ ├── convex/ # Convex functions and schema", "│ └── .env.local # Convex environment variables");
5449
5474
  } else if (!isBackendNone) {
5450
5475
  const backendName = backend[0].toUpperCase() + backend.slice(1);
5451
5476
  const apiName = api !== "none" ? api.toUpperCase() : "";
@@ -5497,7 +5522,7 @@ function generateFeaturesList(database, auth, addons, orm, runtime, frontend, ba
5497
5522
  const dbName = database === "sqlite" ? "SQLite/Turso" : database === "postgres" ? "PostgreSQL" : database === "mysql" ? "MySQL" : database === "mongodb" ? "MongoDB" : "Database";
5498
5523
  addonsList.push(`- **${ormName}** - TypeScript-first ORM`, `- **${dbName}** - Database engine`);
5499
5524
  }
5500
- if (auth !== "none" && !isConvex) {
5525
+ if (auth !== "none") {
5501
5526
  const authLabel = auth === "clerk" ? "Clerk" : "Better-Auth";
5502
5527
  addonsList.push(`- **Authentication** - ${authLabel}`);
5503
5528
  }
@@ -5691,6 +5716,7 @@ async function displayPostInstallInstructions(config) {
5691
5716
  const nativeInstructions = frontend?.includes("native-nativewind") || frontend?.includes("native-unistyles") ? getNativeInstructions(isConvex) : "";
5692
5717
  const pwaInstructions = addons?.includes("pwa") && frontend?.includes("react-router") ? getPwaInstructions() : "";
5693
5718
  const starlightInstructions = addons?.includes("starlight") ? getStarlightInstructions(runCmd) : "";
5719
+ const clerkInstructions = isConvex && config.auth === "clerk" ? getClerkInstructions() : "";
5694
5720
  const wranglerDeployInstructions = getWranglerDeployInstructions(runCmd, webDeploy, serverDeploy);
5695
5721
  const alchemyDeployInstructions = getAlchemyDeployInstructions(runCmd, webDeploy, serverDeploy);
5696
5722
  const hasWeb = frontend?.some((f) => [
@@ -5714,6 +5740,12 @@ async function displayPostInstallInstructions(config) {
5714
5740
  if (!depsInstalled) output += `${pc.cyan(`${stepCounter++}.`)} ${packageManager} install\n`;
5715
5741
  if (isConvex) {
5716
5742
  output += `${pc.cyan(`${stepCounter++}.`)} ${runCmd} dev:setup\n${pc.dim(" (this will guide you through Convex project setup)")}\n`;
5743
+ if (config.auth === "clerk") {
5744
+ output += `${pc.cyan(`${stepCounter++}.`)} ${pc.bold("Clerk Setup:")}\n${pc.dim(" Follow the Convex + Clerk guide to configure authentication:")}\n${pc.cyan(" ")}${pc.underline("https://docs.convex.dev/auth/clerk")}\n\n`;
5745
+ output += `${pc.cyan(`${stepCounter++}.`)} ${pc.bold("Required Environment Variables:")}\n`;
5746
+ output += `${pc.dim(" •")} Set CLERK_JWT_ISSUER_DOMAIN in Convex Dashboard\n`;
5747
+ output += `${pc.dim(" •")} Set CLERK_PUBLISHABLE_KEY in apps/*/.env\n`;
5748
+ }
5717
5749
  output += `${pc.cyan(`${stepCounter++}.`)} Copy environment variables from\n${pc.white(" packages/backend/.env.local")} to ${pc.white("apps/*/.env")}\n`;
5718
5750
  output += `${pc.cyan(`${stepCounter++}.`)} ${runCmd} dev\n\n`;
5719
5751
  } else {
@@ -5738,6 +5770,7 @@ async function displayPostInstallInstructions(config) {
5738
5770
  if (wranglerDeployInstructions) output += `\n${wranglerDeployInstructions.trim()}\n`;
5739
5771
  if (alchemyDeployInstructions) output += `\n${alchemyDeployInstructions.trim()}\n`;
5740
5772
  if (starlightInstructions) output += `\n${starlightInstructions.trim()}\n`;
5773
+ if (clerkInstructions) output += `\n${clerkInstructions.trim()}\n`;
5741
5774
  if (noOrmWarning) output += `\n${noOrmWarning.trim()}\n`;
5742
5775
  if (bunWebNativeWarning) output += `\n${bunWebNativeWarning.trim()}\n`;
5743
5776
  output += `\n${pc.bold("Update all dependencies:\n")}${pc.cyan(tazeCommand)}\n\n`;
@@ -5813,6 +5846,9 @@ function getWranglerDeployInstructions(runCmd, webDeploy, serverDeploy) {
5813
5846
  if (serverDeploy === "wrangler") instructions.push(`${pc.bold("Deploy server to Cloudflare Workers:")}\n${pc.cyan("•")} Deploy: ${`cd apps/server && ${runCmd} run deploy`}`);
5814
5847
  return instructions.length ? `\n${instructions.join("\n")}` : "";
5815
5848
  }
5849
+ function getClerkInstructions() {
5850
+ return `${pc.bold("Clerk Authentication Setup:")}\n${pc.cyan("1.")} Sign up for Clerk at ${pc.underline("https://clerk.com/sign-up")}\n${pc.cyan("2.")} Create a new application in Clerk Dashboard\n${pc.cyan("3.")} Create a JWT template named ${pc.bold("'convex'")} (exact name required)\n${pc.cyan("4.")} Copy your Clerk Frontend API URL (Issuer URL)\n${pc.cyan("5.")} Set environment variables:\n${pc.dim(" •")} CLERK_JWT_ISSUER_DOMAIN in Convex Dashboard\n${pc.dim(" •")} CLERK_PUBLISHABLE_KEY in apps/*/.env\n${pc.cyan("6.")} Follow the complete guide: ${pc.underline("https://docs.convex.dev/auth/clerk")}\n${pc.yellow("NOTE:")} Use Convex's <Authenticated> components instead of Clerk's <SignedIn>`;
5851
+ }
5816
5852
  function getAlchemyDeployInstructions(runCmd, webDeploy, serverDeploy) {
5817
5853
  const instructions = [];
5818
5854
  if (webDeploy === "alchemy" && serverDeploy !== "alchemy") instructions.push(`${pc.bold("Deploy web with Alchemy:")}\n${pc.cyan("•")} Dev: ${`cd apps/web && ${runCmd} dev`}\n${pc.cyan("•")} Deploy: ${`cd apps/web && ${runCmd} deploy`}\n${pc.cyan("•")} Destroy: ${`cd apps/web && ${runCmd} destroy`}`);
@@ -6142,7 +6178,7 @@ async function createProjectHandler(input) {
6142
6178
  };
6143
6179
  coerceBackendPresets(config);
6144
6180
  validateConfigCompatibility(config, providedFlags, cliInput);
6145
- if (config.backend === "convex") log.info("Due to '--backend convex' flag, the following options have been automatically set: auth=none, database=none, orm=none, api=none, runtime=none, dbSetup=none, examples=todo");
6181
+ if (config.backend === "convex") log.info(`Due to '--backend convex' flag, the following options have been automatically set: database=none, orm=none, api=none, runtime=none, dbSetup=none, examples=todo`);
6146
6182
  else if (config.backend === "none") log.info("Due to '--backend none', the following options have been automatically set: --auth none, --database=none, --orm=none, --api=none, --runtime=none, --db-setup=none, --examples=none");
6147
6183
  log.info(pc.yellow("Using default/flag options (config prompts skipped):"));
6148
6184
  log.message(displayConfig(config));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-better-t-stack",
3
- "version": "2.37.0-canary.28c5b8e0",
3
+ "version": "2.37.0-canary.6846bd90",
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",