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 +1 -1
- package/dist/index.js +1 -1
- package/dist/{src-CzVr9ZoP.js → src-ByxWjVSi.js} +52 -16
- package/package.json +1 -1
package/dist/cli.js
CHANGED
package/dist/index.js
CHANGED
|
@@ -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 ||
|
|
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 ||
|
|
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
|
|
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"
|
|
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(
|
|
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.
|
|
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",
|