create-better-fullstack 1.6.2 → 1.6.3
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 +2 -2
- package/dist/index.d.mts +11 -8
- package/dist/index.mjs +71 -17
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Better Fullstack
|
|
2
2
|
|
|
3
|
-
Scaffold production-ready fullstack apps in seconds. Pick your stack from
|
|
3
|
+
Scaffold production-ready fullstack apps in seconds. Pick your stack from 425 options — the CLI wires everything together.
|
|
4
4
|
|
|
5
5
|
## Quick Start
|
|
6
6
|
|
|
@@ -31,7 +31,7 @@ Configure your stack visually — pick every option from a UI, preview your choi
|
|
|
31
31
|
|
|
32
32
|
## Features
|
|
33
33
|
|
|
34
|
-
- **
|
|
34
|
+
- **425 options** — frontend, backend, database, auth, payments, AI, DevOps, and more
|
|
35
35
|
- **5 ecosystems** — TypeScript, Rust, Python, Go, Java
|
|
36
36
|
- **Visual builder** — configure your stack in the browser
|
|
37
37
|
- **Wired for you** — every picked integration is preconfigured and working out of the box
|
package/dist/index.d.mts
CHANGED
|
@@ -148,6 +148,7 @@ declare const router: {
|
|
|
148
148
|
langchain: "langchain";
|
|
149
149
|
llamaindex: "llamaindex";
|
|
150
150
|
"tanstack-ai": "tanstack-ai";
|
|
151
|
+
"ai-cli": "ai-cli";
|
|
151
152
|
}>>;
|
|
152
153
|
realtime: z.ZodOptional<z.ZodEnum<{
|
|
153
154
|
none: "none";
|
|
@@ -273,6 +274,7 @@ declare const router: {
|
|
|
273
274
|
"tanstack-virtual": "tanstack-virtual";
|
|
274
275
|
"tanstack-db": "tanstack-db";
|
|
275
276
|
"tanstack-pacer": "tanstack-pacer";
|
|
277
|
+
"docker-compose": "docker-compose";
|
|
276
278
|
}>>>;
|
|
277
279
|
examples: z.ZodOptional<z.ZodArray<z.ZodEnum<{
|
|
278
280
|
none: "none";
|
|
@@ -638,7 +640,7 @@ declare const router: {
|
|
|
638
640
|
backend: "none" | "hono" | "express" | "fastify" | "elysia" | "fets" | "nestjs" | "adonisjs" | "nitro" | "encore" | "convex" | "self";
|
|
639
641
|
runtime: "none" | "bun" | "node" | "workers";
|
|
640
642
|
frontend: ("none" | "tanstack-router" | "react-router" | "react-vite" | "tanstack-start" | "next" | "nuxt" | "native-bare" | "native-uniwind" | "native-unistyles" | "svelte" | "solid" | "solid-start" | "astro" | "qwik" | "angular" | "redwood" | "fresh")[];
|
|
641
|
-
addons: ("none" | "pwa" | "tauri" | "starlight" | "biome" | "lefthook" | "husky" | "ruler" | "mcp" | "skills" | "turborepo" | "fumadocs" | "ultracite" | "oxlint" | "opentui" | "wxt" | "msw" | "storybook" | "tanstack-query" | "tanstack-table" | "tanstack-virtual" | "tanstack-db" | "tanstack-pacer")[];
|
|
643
|
+
addons: ("none" | "pwa" | "tauri" | "starlight" | "biome" | "lefthook" | "husky" | "ruler" | "mcp" | "skills" | "turborepo" | "fumadocs" | "ultracite" | "oxlint" | "opentui" | "wxt" | "msw" | "storybook" | "tanstack-query" | "tanstack-table" | "tanstack-virtual" | "tanstack-db" | "tanstack-pacer" | "docker-compose")[];
|
|
642
644
|
examples: ("ai" | "none" | "chat-sdk" | "tanstack-showcase")[];
|
|
643
645
|
auth: "none" | "better-auth" | "go-better-auth" | "clerk" | "nextauth" | "stack-auth" | "supabase-auth" | "auth0";
|
|
644
646
|
payments: "none" | "polar" | "stripe" | "lemon-squeezy" | "paddle" | "dodo";
|
|
@@ -650,7 +652,7 @@ declare const router: {
|
|
|
650
652
|
api: "none" | "trpc" | "orpc" | "ts-rest" | "garph" | "graphql-yoga";
|
|
651
653
|
webDeploy: "none" | "docker" | "cloudflare" | "fly" | "railway" | "sst" | "vercel";
|
|
652
654
|
serverDeploy: "none" | "docker" | "cloudflare" | "fly" | "railway" | "sst" | "vercel";
|
|
653
|
-
ai: "none" | "langgraph" | "langchain" | "llamaindex" | "vercel-ai" | "mastra" | "voltagent" | "openai-agents" | "google-adk" | "modelfusion" | "tanstack-ai";
|
|
655
|
+
ai: "none" | "langgraph" | "langchain" | "llamaindex" | "vercel-ai" | "mastra" | "voltagent" | "openai-agents" | "google-adk" | "modelfusion" | "tanstack-ai" | "ai-cli";
|
|
654
656
|
effect: "effect" | "none" | "effect-full";
|
|
655
657
|
stateManagement: "none" | "zustand" | "jotai" | "nanostores" | "redux-toolkit" | "mobx" | "xstate" | "valtio" | "tanstack-store" | "legend-state";
|
|
656
658
|
forms: "none" | "tanstack-form" | "react-hook-form" | "formik" | "final-form" | "conform" | "modular-forms";
|
|
@@ -734,7 +736,7 @@ declare const router: {
|
|
|
734
736
|
backend: "none" | "hono" | "express" | "fastify" | "elysia" | "fets" | "nestjs" | "adonisjs" | "nitro" | "encore" | "convex" | "self";
|
|
735
737
|
runtime: "none" | "bun" | "node" | "workers";
|
|
736
738
|
frontend: ("none" | "tanstack-router" | "react-router" | "react-vite" | "tanstack-start" | "next" | "nuxt" | "native-bare" | "native-uniwind" | "native-unistyles" | "svelte" | "solid" | "solid-start" | "astro" | "qwik" | "angular" | "redwood" | "fresh")[];
|
|
737
|
-
addons: ("none" | "pwa" | "tauri" | "starlight" | "biome" | "lefthook" | "husky" | "ruler" | "mcp" | "skills" | "turborepo" | "fumadocs" | "ultracite" | "oxlint" | "opentui" | "wxt" | "msw" | "storybook" | "tanstack-query" | "tanstack-table" | "tanstack-virtual" | "tanstack-db" | "tanstack-pacer")[];
|
|
739
|
+
addons: ("none" | "pwa" | "tauri" | "starlight" | "biome" | "lefthook" | "husky" | "ruler" | "mcp" | "skills" | "turborepo" | "fumadocs" | "ultracite" | "oxlint" | "opentui" | "wxt" | "msw" | "storybook" | "tanstack-query" | "tanstack-table" | "tanstack-virtual" | "tanstack-db" | "tanstack-pacer" | "docker-compose")[];
|
|
738
740
|
examples: ("ai" | "none" | "chat-sdk" | "tanstack-showcase")[];
|
|
739
741
|
auth: "none" | "better-auth" | "go-better-auth" | "clerk" | "nextauth" | "stack-auth" | "supabase-auth" | "auth0";
|
|
740
742
|
payments: "none" | "polar" | "stripe" | "lemon-squeezy" | "paddle" | "dodo";
|
|
@@ -746,7 +748,7 @@ declare const router: {
|
|
|
746
748
|
api: "none" | "trpc" | "orpc" | "ts-rest" | "garph" | "graphql-yoga";
|
|
747
749
|
webDeploy: "none" | "docker" | "cloudflare" | "fly" | "railway" | "sst" | "vercel";
|
|
748
750
|
serverDeploy: "none" | "docker" | "cloudflare" | "fly" | "railway" | "sst" | "vercel";
|
|
749
|
-
ai: "none" | "langgraph" | "langchain" | "llamaindex" | "vercel-ai" | "mastra" | "voltagent" | "openai-agents" | "google-adk" | "modelfusion" | "tanstack-ai";
|
|
751
|
+
ai: "none" | "langgraph" | "langchain" | "llamaindex" | "vercel-ai" | "mastra" | "voltagent" | "openai-agents" | "google-adk" | "modelfusion" | "tanstack-ai" | "ai-cli";
|
|
750
752
|
effect: "effect" | "none" | "effect-full";
|
|
751
753
|
stateManagement: "none" | "zustand" | "jotai" | "nanostores" | "redux-toolkit" | "mobx" | "xstate" | "valtio" | "tanstack-store" | "legend-state";
|
|
752
754
|
forms: "none" | "tanstack-form" | "react-hook-form" | "formik" | "final-form" | "conform" | "modular-forms";
|
|
@@ -843,7 +845,7 @@ declare const router: {
|
|
|
843
845
|
backend: "none" | "hono" | "express" | "fastify" | "elysia" | "fets" | "nestjs" | "adonisjs" | "nitro" | "encore" | "convex" | "self";
|
|
844
846
|
runtime: "none" | "bun" | "node" | "workers";
|
|
845
847
|
frontend: ("none" | "tanstack-router" | "react-router" | "react-vite" | "tanstack-start" | "next" | "nuxt" | "native-bare" | "native-uniwind" | "native-unistyles" | "svelte" | "solid" | "solid-start" | "astro" | "qwik" | "angular" | "redwood" | "fresh")[];
|
|
846
|
-
addons: ("none" | "pwa" | "tauri" | "starlight" | "biome" | "lefthook" | "husky" | "ruler" | "mcp" | "skills" | "turborepo" | "fumadocs" | "ultracite" | "oxlint" | "opentui" | "wxt" | "msw" | "storybook" | "tanstack-query" | "tanstack-table" | "tanstack-virtual" | "tanstack-db" | "tanstack-pacer")[];
|
|
848
|
+
addons: ("none" | "pwa" | "tauri" | "starlight" | "biome" | "lefthook" | "husky" | "ruler" | "mcp" | "skills" | "turborepo" | "fumadocs" | "ultracite" | "oxlint" | "opentui" | "wxt" | "msw" | "storybook" | "tanstack-query" | "tanstack-table" | "tanstack-virtual" | "tanstack-db" | "tanstack-pacer" | "docker-compose")[];
|
|
847
849
|
examples: ("ai" | "none" | "chat-sdk" | "tanstack-showcase")[];
|
|
848
850
|
auth: "none" | "better-auth" | "go-better-auth" | "clerk" | "nextauth" | "stack-auth" | "supabase-auth" | "auth0";
|
|
849
851
|
payments: "none" | "polar" | "stripe" | "lemon-squeezy" | "paddle" | "dodo";
|
|
@@ -855,7 +857,7 @@ declare const router: {
|
|
|
855
857
|
api: "none" | "trpc" | "orpc" | "ts-rest" | "garph" | "graphql-yoga";
|
|
856
858
|
webDeploy: "none" | "docker" | "cloudflare" | "fly" | "railway" | "sst" | "vercel";
|
|
857
859
|
serverDeploy: "none" | "docker" | "cloudflare" | "fly" | "railway" | "sst" | "vercel";
|
|
858
|
-
ai: "none" | "langgraph" | "langchain" | "llamaindex" | "vercel-ai" | "mastra" | "voltagent" | "openai-agents" | "google-adk" | "modelfusion" | "tanstack-ai";
|
|
860
|
+
ai: "none" | "langgraph" | "langchain" | "llamaindex" | "vercel-ai" | "mastra" | "voltagent" | "openai-agents" | "google-adk" | "modelfusion" | "tanstack-ai" | "ai-cli";
|
|
859
861
|
effect: "effect" | "none" | "effect-full";
|
|
860
862
|
stateManagement: "none" | "zustand" | "jotai" | "nanostores" | "redux-toolkit" | "mobx" | "xstate" | "valtio" | "tanstack-store" | "legend-state";
|
|
861
863
|
forms: "none" | "tanstack-form" | "react-hook-form" | "formik" | "final-form" | "conform" | "modular-forms";
|
|
@@ -939,7 +941,7 @@ declare const router: {
|
|
|
939
941
|
backend: "none" | "hono" | "express" | "fastify" | "elysia" | "fets" | "nestjs" | "adonisjs" | "nitro" | "encore" | "convex" | "self";
|
|
940
942
|
runtime: "none" | "bun" | "node" | "workers";
|
|
941
943
|
frontend: ("none" | "tanstack-router" | "react-router" | "react-vite" | "tanstack-start" | "next" | "nuxt" | "native-bare" | "native-uniwind" | "native-unistyles" | "svelte" | "solid" | "solid-start" | "astro" | "qwik" | "angular" | "redwood" | "fresh")[];
|
|
942
|
-
addons: ("none" | "pwa" | "tauri" | "starlight" | "biome" | "lefthook" | "husky" | "ruler" | "mcp" | "skills" | "turborepo" | "fumadocs" | "ultracite" | "oxlint" | "opentui" | "wxt" | "msw" | "storybook" | "tanstack-query" | "tanstack-table" | "tanstack-virtual" | "tanstack-db" | "tanstack-pacer")[];
|
|
944
|
+
addons: ("none" | "pwa" | "tauri" | "starlight" | "biome" | "lefthook" | "husky" | "ruler" | "mcp" | "skills" | "turborepo" | "fumadocs" | "ultracite" | "oxlint" | "opentui" | "wxt" | "msw" | "storybook" | "tanstack-query" | "tanstack-table" | "tanstack-virtual" | "tanstack-db" | "tanstack-pacer" | "docker-compose")[];
|
|
943
945
|
examples: ("ai" | "none" | "chat-sdk" | "tanstack-showcase")[];
|
|
944
946
|
auth: "none" | "better-auth" | "go-better-auth" | "clerk" | "nextauth" | "stack-auth" | "supabase-auth" | "auth0";
|
|
945
947
|
payments: "none" | "polar" | "stripe" | "lemon-squeezy" | "paddle" | "dodo";
|
|
@@ -951,7 +953,7 @@ declare const router: {
|
|
|
951
953
|
api: "none" | "trpc" | "orpc" | "ts-rest" | "garph" | "graphql-yoga";
|
|
952
954
|
webDeploy: "none" | "docker" | "cloudflare" | "fly" | "railway" | "sst" | "vercel";
|
|
953
955
|
serverDeploy: "none" | "docker" | "cloudflare" | "fly" | "railway" | "sst" | "vercel";
|
|
954
|
-
ai: "none" | "langgraph" | "langchain" | "llamaindex" | "vercel-ai" | "mastra" | "voltagent" | "openai-agents" | "google-adk" | "modelfusion" | "tanstack-ai";
|
|
956
|
+
ai: "none" | "langgraph" | "langchain" | "llamaindex" | "vercel-ai" | "mastra" | "voltagent" | "openai-agents" | "google-adk" | "modelfusion" | "tanstack-ai" | "ai-cli";
|
|
955
957
|
effect: "effect" | "none" | "effect-full";
|
|
956
958
|
stateManagement: "none" | "zustand" | "jotai" | "nanostores" | "redux-toolkit" | "mobx" | "xstate" | "valtio" | "tanstack-store" | "legend-state";
|
|
957
959
|
forms: "none" | "tanstack-form" | "react-hook-form" | "formik" | "final-form" | "conform" | "modular-forms";
|
|
@@ -1065,6 +1067,7 @@ declare const router: {
|
|
|
1065
1067
|
"tanstack-virtual": "tanstack-virtual";
|
|
1066
1068
|
"tanstack-db": "tanstack-db";
|
|
1067
1069
|
"tanstack-pacer": "tanstack-pacer";
|
|
1070
|
+
"docker-compose": "docker-compose";
|
|
1068
1071
|
}>>>;
|
|
1069
1072
|
webDeploy: z.ZodOptional<z.ZodEnum<{
|
|
1070
1073
|
none: "none";
|
package/dist/index.mjs
CHANGED
|
@@ -10,7 +10,7 @@ import z from "zod";
|
|
|
10
10
|
import envPaths from "env-paths";
|
|
11
11
|
import fs from "fs-extra";
|
|
12
12
|
import path from "node:path";
|
|
13
|
-
import { allowedApisForFrontends, getCompatibleAddons, getCompatibleCSSFrameworks, getCompatibleUILibraries, getLocalWebDevPort, hasWebStyling, isExampleAIAllowed, isExampleChatSdkAllowed, isFrontendAllowedWithBackend, isWebFrontend, requiresChatSdkVercelAIForSelection, splitFrontends, validateAddonCompatibility } from "@better-fullstack/types";
|
|
13
|
+
import { allowedApisForFrontends, getCompatibleAddons, getCompatibleCSSFrameworks, getCompatibleUILibraries, getLocalWebDevPort, hasDockerComposeCompatibleFrontend, hasWebStyling, isExampleAIAllowed, isExampleChatSdkAllowed, isFrontendAllowedWithBackend, isWebFrontend, requiresChatSdkVercelAIForSelection, splitFrontends, validateAddonCompatibility } from "@better-fullstack/types";
|
|
14
14
|
import { ECOSYSTEM_GROUPS, EMBEDDED_TEMPLATES, EMBEDDED_TEMPLATES as EMBEDDED_TEMPLATES$1, TEMPLATE_COUNT, VirtualFileSystem, VirtualFileSystem as VirtualFileSystem$1, checkAllVersions, generateCliReport, generateVirtualProject, generateVirtualProject as generateVirtualProject$1, listEcosystems, processAddonTemplates, processAddonsDeps, validatePreflightConfig } from "@better-fullstack/template-generator";
|
|
15
15
|
import gradient from "gradient-string";
|
|
16
16
|
import path$1 from "path";
|
|
@@ -693,16 +693,51 @@ function validateWebDeployRequiresWebFrontend(webDeploy, hasWebFrontendFlag) {
|
|
|
693
693
|
function validateServerDeployRequiresBackend(serverDeploy, backend) {
|
|
694
694
|
if (serverDeploy && serverDeploy !== "none" && (!backend || backend === "none")) exitWithError("'--server-deploy' requires a backend. Please select a backend or set '--server-deploy none'.");
|
|
695
695
|
}
|
|
696
|
-
function validateAddonCompatibility$1(addon, frontend, _auth) {
|
|
697
|
-
|
|
696
|
+
function validateAddonCompatibility$1(addon, frontend, _auth, backend, runtime, ecosystem, rustFrontend, javaWebFramework, database) {
|
|
697
|
+
const baseCompatibility = validateAddonCompatibility(addon, frontend, _auth);
|
|
698
|
+
if (!baseCompatibility.isCompatible) return baseCompatibility;
|
|
699
|
+
if (addon === "docker-compose") {
|
|
700
|
+
if (backend === "convex") return {
|
|
701
|
+
isCompatible: false,
|
|
702
|
+
reason: "docker-compose is not compatible with Convex backend (managed service)"
|
|
703
|
+
};
|
|
704
|
+
if (runtime === "workers") return {
|
|
705
|
+
isCompatible: false,
|
|
706
|
+
reason: "docker-compose is not compatible with Cloudflare Workers runtime"
|
|
707
|
+
};
|
|
708
|
+
if (ecosystem === "typescript" && !hasDockerComposeCompatibleFrontend(frontend)) return {
|
|
709
|
+
isCompatible: false,
|
|
710
|
+
reason: "Docker Compose currently supports Next.js, TanStack Router, React Router, React Vite, Solid, or Astro"
|
|
711
|
+
};
|
|
712
|
+
if (ecosystem === "typescript" && backend === "self" && !frontend.includes("next")) return {
|
|
713
|
+
isCompatible: false,
|
|
714
|
+
reason: "Docker Compose self-backend support currently requires Next.js"
|
|
715
|
+
};
|
|
716
|
+
if (ecosystem === "rust" && rustFrontend && rustFrontend !== "none") return {
|
|
717
|
+
isCompatible: false,
|
|
718
|
+
reason: "Docker Compose for Rust currently supports server-only projects"
|
|
719
|
+
};
|
|
720
|
+
if (ecosystem === "java" && javaWebFramework && javaWebFramework !== "spring-boot") return {
|
|
721
|
+
isCompatible: false,
|
|
722
|
+
reason: "Docker Compose for Java currently requires Spring Boot"
|
|
723
|
+
};
|
|
724
|
+
if (ecosystem === "python" && database && database !== "none" && database !== "sqlite" && database !== "postgres") return {
|
|
725
|
+
isCompatible: false,
|
|
726
|
+
reason: "Docker Compose for Python ORM projects currently supports SQLite defaults or Postgres"
|
|
727
|
+
};
|
|
728
|
+
}
|
|
729
|
+
return { isCompatible: true };
|
|
698
730
|
}
|
|
699
|
-
function getCompatibleAddons$1(allAddons, frontend, existingAddons = [], auth) {
|
|
700
|
-
return getCompatibleAddons(allAddons, frontend, existingAddons, auth)
|
|
731
|
+
function getCompatibleAddons$1(allAddons, frontend, existingAddons = [], auth, backend, runtime) {
|
|
732
|
+
return getCompatibleAddons(allAddons, frontend, existingAddons, auth).filter((addon) => {
|
|
733
|
+
const { isCompatible } = validateAddonCompatibility$1(addon, frontend, auth, backend, runtime);
|
|
734
|
+
return isCompatible;
|
|
735
|
+
});
|
|
701
736
|
}
|
|
702
|
-
function validateAddonsAgainstFrontends(addons = [], frontends = [], auth) {
|
|
737
|
+
function validateAddonsAgainstFrontends(addons = [], frontends = [], auth, backend, runtime, ecosystem, rustFrontend, javaWebFramework, database) {
|
|
703
738
|
for (const addon of addons) {
|
|
704
739
|
if (addon === "none") continue;
|
|
705
|
-
const { isCompatible, reason } = validateAddonCompatibility$1(addon, frontends, auth);
|
|
740
|
+
const { isCompatible, reason } = validateAddonCompatibility$1(addon, frontends, auth, backend, runtime, ecosystem, rustFrontend, javaWebFramework, database);
|
|
706
741
|
if (!isCompatible) exitWithError(`Incompatible addon/frontend combination: ${reason}`);
|
|
707
742
|
}
|
|
708
743
|
}
|
|
@@ -1147,6 +1182,10 @@ function getAddonDisplay(addon) {
|
|
|
1147
1182
|
label = "TanStack Pacer";
|
|
1148
1183
|
hint = "Debounce, throttle, rate-limit & queue utilities (Beta)";
|
|
1149
1184
|
break;
|
|
1185
|
+
case "docker-compose":
|
|
1186
|
+
label = "Docker Compose";
|
|
1187
|
+
hint = "Containerize your app for deployment";
|
|
1188
|
+
break;
|
|
1150
1189
|
default:
|
|
1151
1190
|
label = addon;
|
|
1152
1191
|
hint = `Add ${addon}`;
|
|
@@ -1171,7 +1210,8 @@ const ADDON_GROUPS = {
|
|
|
1171
1210
|
"tauri",
|
|
1172
1211
|
"opentui",
|
|
1173
1212
|
"wxt",
|
|
1174
|
-
"ruler"
|
|
1213
|
+
"ruler",
|
|
1214
|
+
"docker-compose"
|
|
1175
1215
|
],
|
|
1176
1216
|
Integrations: ["msw", "storybook"],
|
|
1177
1217
|
"AI Agents": ["mcp", "skills"],
|
|
@@ -1183,7 +1223,13 @@ const ADDON_GROUPS = {
|
|
|
1183
1223
|
"tanstack-pacer"
|
|
1184
1224
|
]
|
|
1185
1225
|
};
|
|
1186
|
-
|
|
1226
|
+
function validateAddonCompatibilityForPrompt(addon, frontends, auth, backend, runtime) {
|
|
1227
|
+
return validateAddonCompatibility$1(addon, frontends, auth, backend, runtime);
|
|
1228
|
+
}
|
|
1229
|
+
function getCompatibleAddonsForPrompt(allAddons, frontends, existingAddons = [], auth, backend, runtime) {
|
|
1230
|
+
return getCompatibleAddons$1(allAddons, frontends, existingAddons, auth, backend, runtime);
|
|
1231
|
+
}
|
|
1232
|
+
async function getAddonsChoice(addons, frontends, auth, backend, runtime) {
|
|
1187
1233
|
if (addons !== void 0) return addons;
|
|
1188
1234
|
const allAddons = types_exports.AddonsSchema.options.filter((addon) => addon !== "none");
|
|
1189
1235
|
const groupedOptions = {
|
|
@@ -1196,7 +1242,7 @@ async function getAddonsChoice(addons, frontends, auth) {
|
|
|
1196
1242
|
};
|
|
1197
1243
|
const frontendsArray = frontends || [];
|
|
1198
1244
|
for (const addon of allAddons) {
|
|
1199
|
-
const { isCompatible } =
|
|
1245
|
+
const { isCompatible } = validateAddonCompatibilityForPrompt(addon, frontendsArray, auth, backend, runtime);
|
|
1200
1246
|
if (!isCompatible) continue;
|
|
1201
1247
|
const { label, hint } = getAddonDisplay(addon);
|
|
1202
1248
|
const option = {
|
|
@@ -1229,7 +1275,7 @@ async function getAddonsChoice(addons, frontends, auth) {
|
|
|
1229
1275
|
if (isCancel$1(response)) return exitCancelled("Operation cancelled");
|
|
1230
1276
|
return response;
|
|
1231
1277
|
}
|
|
1232
|
-
async function getAddonsToAdd(frontend, existingAddons = [], auth) {
|
|
1278
|
+
async function getAddonsToAdd(frontend, existingAddons = [], auth, backend, runtime) {
|
|
1233
1279
|
const groupedOptions = {
|
|
1234
1280
|
Tooling: [],
|
|
1235
1281
|
Documentation: [],
|
|
@@ -1239,7 +1285,7 @@ async function getAddonsToAdd(frontend, existingAddons = [], auth) {
|
|
|
1239
1285
|
TanStack: []
|
|
1240
1286
|
};
|
|
1241
1287
|
const frontendArray = frontend || [];
|
|
1242
|
-
const compatibleAddons =
|
|
1288
|
+
const compatibleAddons = getCompatibleAddonsForPrompt(types_exports.AddonsSchema.options.filter((addon) => addon !== "none"), frontendArray, existingAddons, auth, backend, runtime);
|
|
1243
1289
|
for (const addon of compatibleAddons) {
|
|
1244
1290
|
const { label, hint } = getAddonDisplay(addon);
|
|
1245
1291
|
const option = {
|
|
@@ -1752,6 +1798,11 @@ const AI_PROMPT_OPTIONS = [
|
|
|
1752
1798
|
label: "TanStack AI",
|
|
1753
1799
|
hint: "Unified LLM interface for AI-powered apps (Alpha)"
|
|
1754
1800
|
},
|
|
1801
|
+
{
|
|
1802
|
+
value: "ai-cli",
|
|
1803
|
+
label: "AI CLI",
|
|
1804
|
+
hint: "Agent-native terminal CLI for generating text, images, and video"
|
|
1805
|
+
},
|
|
1755
1806
|
{
|
|
1756
1807
|
value: "none",
|
|
1757
1808
|
label: "None",
|
|
@@ -5623,7 +5674,7 @@ async function gatherConfig(flags, projectName, projectDir, relativePath) {
|
|
|
5623
5674
|
return getRuntimeChoice(flags.runtime, results.backend);
|
|
5624
5675
|
},
|
|
5625
5676
|
database: ({ results }) => {
|
|
5626
|
-
if (results.ecosystem !== "typescript") return Promise.resolve("none");
|
|
5677
|
+
if (results.ecosystem !== "typescript") return Promise.resolve(results.ecosystem === "python" ? flags.database ?? "none" : "none");
|
|
5627
5678
|
return getDatabaseChoice(flags.database, results.backend, results.runtime);
|
|
5628
5679
|
},
|
|
5629
5680
|
orm: ({ results }) => {
|
|
@@ -5652,8 +5703,11 @@ async function gatherConfig(flags, projectName, projectDir, relativePath) {
|
|
|
5652
5703
|
return getEffectChoice(flags.effect);
|
|
5653
5704
|
},
|
|
5654
5705
|
addons: ({ results }) => {
|
|
5655
|
-
if (results.ecosystem !== "typescript")
|
|
5656
|
-
|
|
5706
|
+
if (results.ecosystem !== "typescript") {
|
|
5707
|
+
const nonTypeScriptAddons = (flags.addons ?? []).filter((addon) => addon === "docker-compose");
|
|
5708
|
+
return Promise.resolve(nonTypeScriptAddons);
|
|
5709
|
+
}
|
|
5710
|
+
return getAddonsChoice(flags.addons, results.frontend, results.auth, results.backend, results.runtime);
|
|
5657
5711
|
},
|
|
5658
5712
|
examples: ({ results }) => {
|
|
5659
5713
|
if (results.ecosystem !== "typescript") return Promise.resolve([]);
|
|
@@ -7095,7 +7149,7 @@ function validateFullConfig(config, providedFlags, options) {
|
|
|
7095
7149
|
suggestions: ["Use --server-deploy fly or --server-deploy railway for NestJS/AdonisJS", "Switch to a serverless-compatible backend like Hono or Express"]
|
|
7096
7150
|
});
|
|
7097
7151
|
if (config.addons && config.addons.length > 0) {
|
|
7098
|
-
validateAddonsAgainstFrontends(config.addons, config.frontend, config.auth);
|
|
7152
|
+
validateAddonsAgainstFrontends(config.addons, config.frontend, config.auth, config.backend, config.runtime, config.ecosystem, config.rustFrontend, config.javaWebFramework, config.database);
|
|
7099
7153
|
config.addons = [...new Set(config.addons)];
|
|
7100
7154
|
}
|
|
7101
7155
|
validateExamplesCompatibility(config.examples ?? [], config.backend, config.frontend ?? [], config.runtime, config.ai);
|
|
@@ -7114,7 +7168,7 @@ function validateConfigForProgrammaticUse(config) {
|
|
|
7114
7168
|
validateApiFrontendCompatibility(config.api, config.frontend, config.astroIntegration);
|
|
7115
7169
|
validateJavaConstraints(config);
|
|
7116
7170
|
validatePaymentsCompatibility(config.payments, config.auth, config.backend, config.frontend);
|
|
7117
|
-
if (config.addons && config.addons.length > 0) validateAddonsAgainstFrontends(config.addons, config.frontend, config.auth);
|
|
7171
|
+
if (config.addons && config.addons.length > 0) validateAddonsAgainstFrontends(config.addons, config.frontend, config.auth, config.backend, config.runtime, config.ecosystem, config.rustFrontend, config.javaWebFramework, config.database);
|
|
7118
7172
|
validateExamplesCompatibility(config.examples ?? [], config.backend, config.frontend ?? [], config.runtime, config.ai);
|
|
7119
7173
|
validateAIFrontendCompatibility(config.ai, config.frontend ?? []);
|
|
7120
7174
|
validateUILibraryFrontendCompatibility(config.uiLibrary, config.frontend ?? [], config.astroIntegration);
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-better-fullstack",
|
|
3
|
-
"version": "1.6.
|
|
4
|
-
"description": "Scaffold production-ready fullstack apps in seconds. Pick your stack from
|
|
3
|
+
"version": "1.6.3",
|
|
4
|
+
"description": "Scaffold production-ready fullstack apps in seconds. Pick your stack from 425 options — the CLI wires everything together.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"algolia",
|
|
7
7
|
"angular",
|
|
@@ -127,8 +127,8 @@
|
|
|
127
127
|
"prepublishOnly": "npm run build"
|
|
128
128
|
},
|
|
129
129
|
"dependencies": {
|
|
130
|
-
"@better-fullstack/template-generator": "^1.6.
|
|
131
|
-
"@better-fullstack/types": "^1.6.
|
|
130
|
+
"@better-fullstack/template-generator": "^1.6.3",
|
|
131
|
+
"@better-fullstack/types": "^1.6.3",
|
|
132
132
|
"@clack/core": "^0.5.0",
|
|
133
133
|
"@clack/prompts": "^1.2.0",
|
|
134
134
|
"@orpc/server": "^1.14.0",
|