create-better-fullstack 1.6.1 → 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 +13 -8
- package/dist/{addons-setup-Cx9DU_sr.mjs → addons-setup-CBK1Htlc.mjs} +1 -1
- package/dist/{addons-setup-Cgup_RHm.mjs → addons-setup-DQa6TRrx.mjs} +48 -39
- package/dist/index.d.mts +30 -16
- package/dist/index.mjs +151 -22
- package/dist/mcp-entry.mjs +3 -3
- package/package.json +6 -6
package/README.md
CHANGED
|
@@ -1,23 +1,28 @@
|
|
|
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
|
|
|
7
7
|
```bash
|
|
8
|
-
# Using
|
|
9
|
-
|
|
8
|
+
# Using npm
|
|
9
|
+
npm create better-fullstack@latest
|
|
10
|
+
|
|
11
|
+
# Using npx
|
|
12
|
+
npx create-better-fullstack@latest
|
|
10
13
|
|
|
11
14
|
# Using pnpm
|
|
12
15
|
pnpm create better-fullstack@latest
|
|
13
16
|
|
|
14
|
-
# Using
|
|
15
|
-
|
|
17
|
+
# Using bun
|
|
18
|
+
bun create better-fullstack@latest
|
|
16
19
|
|
|
17
20
|
# Using yarn
|
|
18
21
|
yarn create better-fullstack@latest
|
|
19
22
|
```
|
|
20
23
|
|
|
24
|
+
Bun is required only when the generated project selects Bun as its runtime or package manager. Node.js with npm is enough for Node-based projects.
|
|
25
|
+
|
|
21
26
|
## Web Builder
|
|
22
27
|
|
|
23
28
|
Configure your stack visually — pick every option from a UI, preview your choices, and get a ready-to-run command.
|
|
@@ -26,8 +31,8 @@ Configure your stack visually — pick every option from a UI, preview your choi
|
|
|
26
31
|
|
|
27
32
|
## Features
|
|
28
33
|
|
|
29
|
-
- **
|
|
30
|
-
- **
|
|
34
|
+
- **425 options** — frontend, backend, database, auth, payments, AI, DevOps, and more
|
|
35
|
+
- **5 ecosystems** — TypeScript, Rust, Python, Go, Java
|
|
31
36
|
- **Visual builder** — configure your stack in the browser
|
|
32
37
|
- **Wired for you** — every picked integration is preconfigured and working out of the box
|
|
33
38
|
|
|
@@ -37,7 +42,7 @@ Configure your stack visually — pick every option from a UI, preview your choi
|
|
|
37
42
|
--yes # Accept all defaults
|
|
38
43
|
--yolo # Scaffold a random stack — good for exploring
|
|
39
44
|
--template <name> # Use a preset (t3, mern, pern, uniwind)
|
|
40
|
-
--ecosystem <lang> # Start in rust, python, or
|
|
45
|
+
--ecosystem <lang> # Start in typescript, rust, python, go, or java mode
|
|
41
46
|
--version-channel # Dependency channel: stable, latest, beta
|
|
42
47
|
--no-git # Skip git initialization
|
|
43
48
|
--no-install # Skip dependency installation
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import "./bts-config-B_rZ4_sj.mjs";
|
|
3
|
-
import { i as setupLefthook, n as setupBiome, r as setupHusky, t as setupAddons } from "./addons-setup-
|
|
3
|
+
import { i as setupLefthook, n as setupBiome, r as setupHusky, t as setupAddons } from "./addons-setup-DQa6TRrx.mjs";
|
|
4
4
|
|
|
5
5
|
export { setupAddons };
|
|
@@ -626,45 +626,50 @@ async function setupRuler(config) {
|
|
|
626
626
|
log.error(pc.red("Ruler template directory not found. Please ensure ruler addon is properly installed."));
|
|
627
627
|
return;
|
|
628
628
|
}
|
|
629
|
-
const
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
629
|
+
const EDITORS$1 = {
|
|
630
|
+
agentsmd: { label: "Agents.md" },
|
|
631
|
+
aider: { label: "Aider" },
|
|
632
|
+
amazonqcli: { label: "Amazon Q CLI" },
|
|
633
|
+
amp: { label: "AMP" },
|
|
634
|
+
antigravity: { label: "Antigravity" },
|
|
635
|
+
augmentcode: { label: "AugmentCode" },
|
|
636
|
+
claude: { label: "Claude Code" },
|
|
637
|
+
cline: { label: "Cline" },
|
|
638
|
+
codex: { label: "OpenAI Codex CLI" },
|
|
639
|
+
copilot: { label: "GitHub Copilot" },
|
|
640
|
+
crush: { label: "Crush" },
|
|
641
|
+
cursor: { label: "Cursor" },
|
|
642
|
+
firebase: { label: "Firebase Studio" },
|
|
643
|
+
firebender: { label: "Firebender" },
|
|
644
|
+
"gemini-cli": { label: "Gemini CLI" },
|
|
645
|
+
goose: { label: "Goose" },
|
|
646
|
+
jules: { label: "Jules" },
|
|
647
|
+
junie: { label: "Junie" },
|
|
648
|
+
kilocode: { label: "Kilo Code" },
|
|
649
|
+
kiro: { label: "Kiro" },
|
|
650
|
+
mistral: { label: "Mistral" },
|
|
651
|
+
opencode: { label: "OpenCode" },
|
|
652
|
+
openhands: { label: "Open Hands" },
|
|
653
|
+
qwen: { label: "Qwen" },
|
|
654
|
+
roo: { label: "RooCode" },
|
|
655
|
+
trae: { label: "Trae AI" },
|
|
656
|
+
warp: { label: "Warp" },
|
|
657
|
+
windsurf: { label: "Windsurf" },
|
|
658
|
+
zed: { label: "Zed" }
|
|
659
|
+
};
|
|
660
|
+
let selectedEditors = [];
|
|
661
|
+
if (canPromptInteractively()) {
|
|
662
|
+
const prompted = await autocompleteMultiselect({
|
|
663
|
+
message: "Select AI assistants for Ruler",
|
|
664
|
+
options: Object.entries(EDITORS$1).map(([key, v]) => ({
|
|
665
|
+
value: key,
|
|
666
|
+
label: v.label
|
|
667
|
+
})),
|
|
668
|
+
required: false
|
|
669
|
+
});
|
|
670
|
+
if (isCancel(prompted)) return exitCancelled("Operation cancelled");
|
|
671
|
+
selectedEditors = [...prompted];
|
|
672
|
+
} else log.info("Skipping AI assistant selection (non-interactive mode).");
|
|
668
673
|
if (selectedEditors.length === 0) {
|
|
669
674
|
log.info("No AI assistants selected. To apply rules later, run:");
|
|
670
675
|
log.info(pc.cyan(`${getPackageExecutionCommand(packageManager, "@intellectronica/ruler@latest apply --local-only")}`));
|
|
@@ -940,6 +945,10 @@ async function setupSkills(config) {
|
|
|
940
945
|
}));
|
|
941
946
|
});
|
|
942
947
|
if (skillOptions.length === 0) return;
|
|
948
|
+
if (!canPromptInteractively()) {
|
|
949
|
+
log.info("Skipping skills installation (non-interactive mode). Run the skills CLI manually to install.");
|
|
950
|
+
return;
|
|
951
|
+
}
|
|
943
952
|
const scope = await select({
|
|
944
953
|
message: "Where should skills be installed?",
|
|
945
954
|
options: [{
|
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";
|
|
@@ -602,12 +604,23 @@ declare const router: {
|
|
|
602
604
|
"spring-actuator": "spring-actuator";
|
|
603
605
|
"spring-validation": "spring-validation";
|
|
604
606
|
flyway: "flyway";
|
|
607
|
+
liquibase: "liquibase";
|
|
608
|
+
"springdoc-openapi": "springdoc-openapi";
|
|
609
|
+
lombok: "lombok";
|
|
610
|
+
mapstruct: "mapstruct";
|
|
611
|
+
caffeine: "caffeine";
|
|
605
612
|
}>>>;
|
|
606
613
|
javaTestingLibraries: z.ZodOptional<z.ZodArray<z.ZodEnum<{
|
|
607
614
|
none: "none";
|
|
608
615
|
junit5: "junit5";
|
|
609
616
|
mockito: "mockito";
|
|
610
617
|
testcontainers: "testcontainers";
|
|
618
|
+
assertj: "assertj";
|
|
619
|
+
"rest-assured": "rest-assured";
|
|
620
|
+
wiremock: "wiremock";
|
|
621
|
+
awaitility: "awaitility";
|
|
622
|
+
archunit: "archunit";
|
|
623
|
+
jqwik: "jqwik";
|
|
611
624
|
}>>>;
|
|
612
625
|
aiDocs: z.ZodOptional<z.ZodArray<z.ZodEnum<{
|
|
613
626
|
none: "none";
|
|
@@ -627,7 +640,7 @@ declare const router: {
|
|
|
627
640
|
backend: "none" | "hono" | "express" | "fastify" | "elysia" | "fets" | "nestjs" | "adonisjs" | "nitro" | "encore" | "convex" | "self";
|
|
628
641
|
runtime: "none" | "bun" | "node" | "workers";
|
|
629
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")[];
|
|
630
|
-
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")[];
|
|
631
644
|
examples: ("ai" | "none" | "chat-sdk" | "tanstack-showcase")[];
|
|
632
645
|
auth: "none" | "better-auth" | "go-better-auth" | "clerk" | "nextauth" | "stack-auth" | "supabase-auth" | "auth0";
|
|
633
646
|
payments: "none" | "polar" | "stripe" | "lemon-squeezy" | "paddle" | "dodo";
|
|
@@ -639,7 +652,7 @@ declare const router: {
|
|
|
639
652
|
api: "none" | "trpc" | "orpc" | "ts-rest" | "garph" | "graphql-yoga";
|
|
640
653
|
webDeploy: "none" | "docker" | "cloudflare" | "fly" | "railway" | "sst" | "vercel";
|
|
641
654
|
serverDeploy: "none" | "docker" | "cloudflare" | "fly" | "railway" | "sst" | "vercel";
|
|
642
|
-
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";
|
|
643
656
|
effect: "effect" | "none" | "effect-full";
|
|
644
657
|
stateManagement: "none" | "zustand" | "jotai" | "nanostores" | "redux-toolkit" | "mobx" | "xstate" | "valtio" | "tanstack-store" | "legend-state";
|
|
645
658
|
forms: "none" | "tanstack-form" | "react-hook-form" | "formik" | "final-form" | "conform" | "modular-forms";
|
|
@@ -689,8 +702,8 @@ declare const router: {
|
|
|
689
702
|
javaBuildTool: "none" | "maven" | "gradle";
|
|
690
703
|
javaOrm: "none" | "spring-data-jpa";
|
|
691
704
|
javaAuth: "none" | "spring-security";
|
|
692
|
-
javaLibraries: ("none" | "spring-actuator" | "spring-validation" | "flyway")[];
|
|
693
|
-
javaTestingLibraries: ("none" | "junit5" | "mockito" | "testcontainers")[];
|
|
705
|
+
javaLibraries: ("none" | "spring-actuator" | "spring-validation" | "flyway" | "liquibase" | "springdoc-openapi" | "lombok" | "mapstruct" | "caffeine")[];
|
|
706
|
+
javaTestingLibraries: ("none" | "junit5" | "mockito" | "testcontainers" | "assertj" | "rest-assured" | "wiremock" | "awaitility" | "archunit" | "jqwik")[];
|
|
694
707
|
aiDocs: ("none" | "claude-md" | "agents-md" | "cursorrules")[];
|
|
695
708
|
astroIntegration?: "none" | "svelte" | "solid" | "react" | "vue" | undefined;
|
|
696
709
|
shadcnBase?: "radix" | "base" | undefined;
|
|
@@ -723,7 +736,7 @@ declare const router: {
|
|
|
723
736
|
backend: "none" | "hono" | "express" | "fastify" | "elysia" | "fets" | "nestjs" | "adonisjs" | "nitro" | "encore" | "convex" | "self";
|
|
724
737
|
runtime: "none" | "bun" | "node" | "workers";
|
|
725
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")[];
|
|
726
|
-
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")[];
|
|
727
740
|
examples: ("ai" | "none" | "chat-sdk" | "tanstack-showcase")[];
|
|
728
741
|
auth: "none" | "better-auth" | "go-better-auth" | "clerk" | "nextauth" | "stack-auth" | "supabase-auth" | "auth0";
|
|
729
742
|
payments: "none" | "polar" | "stripe" | "lemon-squeezy" | "paddle" | "dodo";
|
|
@@ -735,7 +748,7 @@ declare const router: {
|
|
|
735
748
|
api: "none" | "trpc" | "orpc" | "ts-rest" | "garph" | "graphql-yoga";
|
|
736
749
|
webDeploy: "none" | "docker" | "cloudflare" | "fly" | "railway" | "sst" | "vercel";
|
|
737
750
|
serverDeploy: "none" | "docker" | "cloudflare" | "fly" | "railway" | "sst" | "vercel";
|
|
738
|
-
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";
|
|
739
752
|
effect: "effect" | "none" | "effect-full";
|
|
740
753
|
stateManagement: "none" | "zustand" | "jotai" | "nanostores" | "redux-toolkit" | "mobx" | "xstate" | "valtio" | "tanstack-store" | "legend-state";
|
|
741
754
|
forms: "none" | "tanstack-form" | "react-hook-form" | "formik" | "final-form" | "conform" | "modular-forms";
|
|
@@ -785,8 +798,8 @@ declare const router: {
|
|
|
785
798
|
javaBuildTool: "none" | "maven" | "gradle";
|
|
786
799
|
javaOrm: "none" | "spring-data-jpa";
|
|
787
800
|
javaAuth: "none" | "spring-security";
|
|
788
|
-
javaLibraries: ("none" | "spring-actuator" | "spring-validation" | "flyway")[];
|
|
789
|
-
javaTestingLibraries: ("none" | "junit5" | "mockito" | "testcontainers")[];
|
|
801
|
+
javaLibraries: ("none" | "spring-actuator" | "spring-validation" | "flyway" | "liquibase" | "springdoc-openapi" | "lombok" | "mapstruct" | "caffeine")[];
|
|
802
|
+
javaTestingLibraries: ("none" | "junit5" | "mockito" | "testcontainers" | "assertj" | "rest-assured" | "wiremock" | "awaitility" | "archunit" | "jqwik")[];
|
|
790
803
|
aiDocs: ("none" | "claude-md" | "agents-md" | "cursorrules")[];
|
|
791
804
|
astroIntegration?: "none" | "svelte" | "solid" | "react" | "vue" | undefined;
|
|
792
805
|
shadcnBase?: "radix" | "base" | undefined;
|
|
@@ -832,7 +845,7 @@ declare const router: {
|
|
|
832
845
|
backend: "none" | "hono" | "express" | "fastify" | "elysia" | "fets" | "nestjs" | "adonisjs" | "nitro" | "encore" | "convex" | "self";
|
|
833
846
|
runtime: "none" | "bun" | "node" | "workers";
|
|
834
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")[];
|
|
835
|
-
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")[];
|
|
836
849
|
examples: ("ai" | "none" | "chat-sdk" | "tanstack-showcase")[];
|
|
837
850
|
auth: "none" | "better-auth" | "go-better-auth" | "clerk" | "nextauth" | "stack-auth" | "supabase-auth" | "auth0";
|
|
838
851
|
payments: "none" | "polar" | "stripe" | "lemon-squeezy" | "paddle" | "dodo";
|
|
@@ -844,7 +857,7 @@ declare const router: {
|
|
|
844
857
|
api: "none" | "trpc" | "orpc" | "ts-rest" | "garph" | "graphql-yoga";
|
|
845
858
|
webDeploy: "none" | "docker" | "cloudflare" | "fly" | "railway" | "sst" | "vercel";
|
|
846
859
|
serverDeploy: "none" | "docker" | "cloudflare" | "fly" | "railway" | "sst" | "vercel";
|
|
847
|
-
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";
|
|
848
861
|
effect: "effect" | "none" | "effect-full";
|
|
849
862
|
stateManagement: "none" | "zustand" | "jotai" | "nanostores" | "redux-toolkit" | "mobx" | "xstate" | "valtio" | "tanstack-store" | "legend-state";
|
|
850
863
|
forms: "none" | "tanstack-form" | "react-hook-form" | "formik" | "final-form" | "conform" | "modular-forms";
|
|
@@ -894,8 +907,8 @@ declare const router: {
|
|
|
894
907
|
javaBuildTool: "none" | "maven" | "gradle";
|
|
895
908
|
javaOrm: "none" | "spring-data-jpa";
|
|
896
909
|
javaAuth: "none" | "spring-security";
|
|
897
|
-
javaLibraries: ("none" | "spring-actuator" | "spring-validation" | "flyway")[];
|
|
898
|
-
javaTestingLibraries: ("none" | "junit5" | "mockito" | "testcontainers")[];
|
|
910
|
+
javaLibraries: ("none" | "spring-actuator" | "spring-validation" | "flyway" | "liquibase" | "springdoc-openapi" | "lombok" | "mapstruct" | "caffeine")[];
|
|
911
|
+
javaTestingLibraries: ("none" | "junit5" | "mockito" | "testcontainers" | "assertj" | "rest-assured" | "wiremock" | "awaitility" | "archunit" | "jqwik")[];
|
|
899
912
|
aiDocs: ("none" | "claude-md" | "agents-md" | "cursorrules")[];
|
|
900
913
|
astroIntegration?: "none" | "svelte" | "solid" | "react" | "vue" | undefined;
|
|
901
914
|
shadcnBase?: "radix" | "base" | undefined;
|
|
@@ -928,7 +941,7 @@ declare const router: {
|
|
|
928
941
|
backend: "none" | "hono" | "express" | "fastify" | "elysia" | "fets" | "nestjs" | "adonisjs" | "nitro" | "encore" | "convex" | "self";
|
|
929
942
|
runtime: "none" | "bun" | "node" | "workers";
|
|
930
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")[];
|
|
931
|
-
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")[];
|
|
932
945
|
examples: ("ai" | "none" | "chat-sdk" | "tanstack-showcase")[];
|
|
933
946
|
auth: "none" | "better-auth" | "go-better-auth" | "clerk" | "nextauth" | "stack-auth" | "supabase-auth" | "auth0";
|
|
934
947
|
payments: "none" | "polar" | "stripe" | "lemon-squeezy" | "paddle" | "dodo";
|
|
@@ -940,7 +953,7 @@ declare const router: {
|
|
|
940
953
|
api: "none" | "trpc" | "orpc" | "ts-rest" | "garph" | "graphql-yoga";
|
|
941
954
|
webDeploy: "none" | "docker" | "cloudflare" | "fly" | "railway" | "sst" | "vercel";
|
|
942
955
|
serverDeploy: "none" | "docker" | "cloudflare" | "fly" | "railway" | "sst" | "vercel";
|
|
943
|
-
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";
|
|
944
957
|
effect: "effect" | "none" | "effect-full";
|
|
945
958
|
stateManagement: "none" | "zustand" | "jotai" | "nanostores" | "redux-toolkit" | "mobx" | "xstate" | "valtio" | "tanstack-store" | "legend-state";
|
|
946
959
|
forms: "none" | "tanstack-form" | "react-hook-form" | "formik" | "final-form" | "conform" | "modular-forms";
|
|
@@ -990,8 +1003,8 @@ declare const router: {
|
|
|
990
1003
|
javaBuildTool: "none" | "maven" | "gradle";
|
|
991
1004
|
javaOrm: "none" | "spring-data-jpa";
|
|
992
1005
|
javaAuth: "none" | "spring-security";
|
|
993
|
-
javaLibraries: ("none" | "spring-actuator" | "spring-validation" | "flyway")[];
|
|
994
|
-
javaTestingLibraries: ("none" | "junit5" | "mockito" | "testcontainers")[];
|
|
1006
|
+
javaLibraries: ("none" | "spring-actuator" | "spring-validation" | "flyway" | "liquibase" | "springdoc-openapi" | "lombok" | "mapstruct" | "caffeine")[];
|
|
1007
|
+
javaTestingLibraries: ("none" | "junit5" | "mockito" | "testcontainers" | "assertj" | "rest-assured" | "wiremock" | "awaitility" | "archunit" | "jqwik")[];
|
|
995
1008
|
aiDocs: ("none" | "claude-md" | "agents-md" | "cursorrules")[];
|
|
996
1009
|
astroIntegration?: "none" | "svelte" | "solid" | "react" | "vue" | undefined;
|
|
997
1010
|
shadcnBase?: "radix" | "base" | undefined;
|
|
@@ -1054,6 +1067,7 @@ declare const router: {
|
|
|
1054
1067
|
"tanstack-virtual": "tanstack-virtual";
|
|
1055
1068
|
"tanstack-db": "tanstack-db";
|
|
1056
1069
|
"tanstack-pacer": "tanstack-pacer";
|
|
1070
|
+
"docker-compose": "docker-compose";
|
|
1057
1071
|
}>>>;
|
|
1058
1072
|
webDeploy: z.ZodOptional<z.ZodEnum<{
|
|
1059
1073
|
none: "none";
|
package/dist/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { t as __reExport } from "./chunk-CCII7kTE.mjs";
|
|
3
3
|
import { a as DEFAULT_CONFIG, c as getDefaultConfig, i as getLatestCLIVersion, l as getUserPkgManager, n as updateBtsConfig, o as DEFAULT_UI_LIBRARY_BY_FRONTEND, r as writeBtsConfig, t as readBtsConfig } from "./bts-config-B_rZ4_sj.mjs";
|
|
4
|
-
import { _ as setIsFirstPrompt$1, a as canPromptInteractively, c as CLIError, d as exitWithError, f as handleError, g as runWithContextAsync, h as isSilent, l as UserCancelledError, m as isFirstPrompt, o as getPackageExecutionArgs, p as didLastPromptShowUI, s as addPackageDependency, t as setupAddons, u as exitCancelled, v as setLastPromptShownUI } from "./addons-setup-
|
|
4
|
+
import { _ as setIsFirstPrompt$1, a as canPromptInteractively, c as CLIError, d as exitWithError, f as handleError, g as runWithContextAsync, h as isSilent, l as UserCancelledError, m as isFirstPrompt, o as getPackageExecutionArgs, p as didLastPromptShowUI, s as addPackageDependency, t as setupAddons, u as exitCancelled, v as setLastPromptShownUI } from "./addons-setup-DQa6TRrx.mjs";
|
|
5
5
|
import { cancel, confirm, intro, isCancel, log, outro, select, spinner, text } from "@clack/prompts";
|
|
6
6
|
import { createRouterClient, os } from "@orpc/server";
|
|
7
7
|
import pc from "picocolors";
|
|
@@ -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",
|
|
@@ -3480,6 +3531,36 @@ const JAVA_TESTING_LIBRARY_PROMPT_OPTIONS = [
|
|
|
3480
3531
|
label: "Testcontainers",
|
|
3481
3532
|
hint: "Disposable Docker-based integration tests"
|
|
3482
3533
|
},
|
|
3534
|
+
{
|
|
3535
|
+
value: "assertj",
|
|
3536
|
+
label: "AssertJ",
|
|
3537
|
+
hint: "Fluent assertions for Java tests"
|
|
3538
|
+
},
|
|
3539
|
+
{
|
|
3540
|
+
value: "rest-assured",
|
|
3541
|
+
label: "REST Assured",
|
|
3542
|
+
hint: "DSL for HTTP API and REST endpoint tests"
|
|
3543
|
+
},
|
|
3544
|
+
{
|
|
3545
|
+
value: "wiremock",
|
|
3546
|
+
label: "WireMock",
|
|
3547
|
+
hint: "HTTP service stubs for integration tests"
|
|
3548
|
+
},
|
|
3549
|
+
{
|
|
3550
|
+
value: "awaitility",
|
|
3551
|
+
label: "Awaitility",
|
|
3552
|
+
hint: "Wait helpers for asynchronous Java tests"
|
|
3553
|
+
},
|
|
3554
|
+
{
|
|
3555
|
+
value: "archunit",
|
|
3556
|
+
label: "ArchUnit",
|
|
3557
|
+
hint: "Architecture rules for Java package boundaries"
|
|
3558
|
+
},
|
|
3559
|
+
{
|
|
3560
|
+
value: "jqwik",
|
|
3561
|
+
label: "jqwik",
|
|
3562
|
+
hint: "Property-based testing on the JUnit Platform"
|
|
3563
|
+
},
|
|
3483
3564
|
{
|
|
3484
3565
|
value: "none",
|
|
3485
3566
|
label: "None",
|
|
@@ -3502,6 +3583,31 @@ const JAVA_LIBRARY_PROMPT_OPTIONS = [
|
|
|
3502
3583
|
label: "Flyway",
|
|
3503
3584
|
hint: "Versioned SQL database migrations for JPA-backed apps"
|
|
3504
3585
|
},
|
|
3586
|
+
{
|
|
3587
|
+
value: "liquibase",
|
|
3588
|
+
label: "Liquibase",
|
|
3589
|
+
hint: "Database change management for JPA-backed apps"
|
|
3590
|
+
},
|
|
3591
|
+
{
|
|
3592
|
+
value: "springdoc-openapi",
|
|
3593
|
+
label: "Springdoc OpenAPI",
|
|
3594
|
+
hint: "OpenAPI and Swagger UI documentation for Spring MVC APIs"
|
|
3595
|
+
},
|
|
3596
|
+
{
|
|
3597
|
+
value: "lombok",
|
|
3598
|
+
label: "Lombok",
|
|
3599
|
+
hint: "Annotation processor for reducing Java boilerplate"
|
|
3600
|
+
},
|
|
3601
|
+
{
|
|
3602
|
+
value: "mapstruct",
|
|
3603
|
+
label: "MapStruct",
|
|
3604
|
+
hint: "Compile-time generated mappers for DTO and entity conversions"
|
|
3605
|
+
},
|
|
3606
|
+
{
|
|
3607
|
+
value: "caffeine",
|
|
3608
|
+
label: "Caffeine",
|
|
3609
|
+
hint: "High-performance in-memory caching through Spring Cache"
|
|
3610
|
+
},
|
|
3505
3611
|
{
|
|
3506
3612
|
value: "none",
|
|
3507
3613
|
label: "None",
|
|
@@ -5568,7 +5674,7 @@ async function gatherConfig(flags, projectName, projectDir, relativePath) {
|
|
|
5568
5674
|
return getRuntimeChoice(flags.runtime, results.backend);
|
|
5569
5675
|
},
|
|
5570
5676
|
database: ({ results }) => {
|
|
5571
|
-
if (results.ecosystem !== "typescript") return Promise.resolve("none");
|
|
5677
|
+
if (results.ecosystem !== "typescript") return Promise.resolve(results.ecosystem === "python" ? flags.database ?? "none" : "none");
|
|
5572
5678
|
return getDatabaseChoice(flags.database, results.backend, results.runtime);
|
|
5573
5679
|
},
|
|
5574
5680
|
orm: ({ results }) => {
|
|
@@ -5597,8 +5703,11 @@ async function gatherConfig(flags, projectName, projectDir, relativePath) {
|
|
|
5597
5703
|
return getEffectChoice(flags.effect);
|
|
5598
5704
|
},
|
|
5599
5705
|
addons: ({ results }) => {
|
|
5600
|
-
if (results.ecosystem !== "typescript")
|
|
5601
|
-
|
|
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);
|
|
5602
5711
|
},
|
|
5603
5712
|
examples: ({ results }) => {
|
|
5604
5713
|
if (results.ecosystem !== "typescript") return Promise.resolve([]);
|
|
@@ -7040,7 +7149,7 @@ function validateFullConfig(config, providedFlags, options) {
|
|
|
7040
7149
|
suggestions: ["Use --server-deploy fly or --server-deploy railway for NestJS/AdonisJS", "Switch to a serverless-compatible backend like Hono or Express"]
|
|
7041
7150
|
});
|
|
7042
7151
|
if (config.addons && config.addons.length > 0) {
|
|
7043
|
-
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);
|
|
7044
7153
|
config.addons = [...new Set(config.addons)];
|
|
7045
7154
|
}
|
|
7046
7155
|
validateExamplesCompatibility(config.examples ?? [], config.backend, config.frontend ?? [], config.runtime, config.ai);
|
|
@@ -7059,7 +7168,7 @@ function validateConfigForProgrammaticUse(config) {
|
|
|
7059
7168
|
validateApiFrontendCompatibility(config.api, config.frontend, config.astroIntegration);
|
|
7060
7169
|
validateJavaConstraints(config);
|
|
7061
7170
|
validatePaymentsCompatibility(config.payments, config.auth, config.backend, config.frontend);
|
|
7062
|
-
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);
|
|
7063
7172
|
validateExamplesCompatibility(config.examples ?? [], config.backend, config.frontend ?? [], config.runtime, config.ai);
|
|
7064
7173
|
validateAIFrontendCompatibility(config.ai, config.frontend ?? []);
|
|
7065
7174
|
validateUILibraryFrontendCompatibility(config.uiLibrary, config.frontend ?? [], config.astroIntegration);
|
|
@@ -8833,7 +8942,15 @@ function displayJavaInstructions(config) {
|
|
|
8833
8942
|
const { projectName, relativePath, depsInstalled, javaWebFramework, javaBuildTool, javaOrm, javaAuth, javaLibraries, javaTestingLibraries } = config;
|
|
8834
8943
|
const cdCmd = `cd ${relativePath}`;
|
|
8835
8944
|
const isSpringBoot = javaWebFramework === "spring-boot" && javaBuildTool !== "none";
|
|
8836
|
-
const
|
|
8945
|
+
const rawJavaLibraries = isSpringBoot ? javaLibraries.filter((library) => library !== "none") : [];
|
|
8946
|
+
const rawJavaLibrarySet = new Set(rawJavaLibraries);
|
|
8947
|
+
const jpaRequiredJavaLibraries = new Set(["flyway", "liquibase"]);
|
|
8948
|
+
const effectiveJavaLibraries = [];
|
|
8949
|
+
for (const library of rawJavaLibraries) {
|
|
8950
|
+
if (jpaRequiredJavaLibraries.has(library) && javaOrm !== "spring-data-jpa") continue;
|
|
8951
|
+
if (library === "liquibase" && rawJavaLibrarySet.has("flyway")) continue;
|
|
8952
|
+
effectiveJavaLibraries.push(library);
|
|
8953
|
+
}
|
|
8837
8954
|
const effectiveJavaTestingLibraries = javaBuildTool === "none" ? [] : javaTestingLibraries.filter((library) => library !== "none");
|
|
8838
8955
|
const buildToolCommand = javaBuildTool === "none" ? null : javaBuildTool === "gradle" ? process.platform === "win32" ? "gradlew.bat" : "./gradlew" : process.platform === "win32" ? "mvnw.cmd" : "./mvnw";
|
|
8839
8956
|
const runCommand = buildToolCommand ? isSpringBoot ? javaBuildTool === "gradle" ? `${buildToolCommand} bootRun` : `${buildToolCommand} spring-boot:run` : javaBuildTool === "gradle" ? `${buildToolCommand} run` : `${buildToolCommand} exec:java` : null;
|
|
@@ -8862,7 +8979,12 @@ function displayJavaInstructions(config) {
|
|
|
8862
8979
|
const libraryNames = {
|
|
8863
8980
|
"spring-actuator": "Spring Actuator",
|
|
8864
8981
|
"spring-validation": "Spring Validation",
|
|
8865
|
-
flyway: "Flyway"
|
|
8982
|
+
flyway: "Flyway",
|
|
8983
|
+
liquibase: "Liquibase",
|
|
8984
|
+
"springdoc-openapi": "Springdoc OpenAPI",
|
|
8985
|
+
lombok: "Lombok",
|
|
8986
|
+
mapstruct: "MapStruct",
|
|
8987
|
+
caffeine: "Caffeine"
|
|
8866
8988
|
};
|
|
8867
8989
|
const libraryList = effectiveJavaLibraries.map((library) => libraryNames[library] || library).join(", ");
|
|
8868
8990
|
output += `${pc.cyan("•")} Libraries: ${libraryList}\n`;
|
|
@@ -8871,7 +8993,13 @@ function displayJavaInstructions(config) {
|
|
|
8871
8993
|
const testingNames = {
|
|
8872
8994
|
junit5: "JUnit 5",
|
|
8873
8995
|
mockito: "Mockito",
|
|
8874
|
-
testcontainers: "Testcontainers"
|
|
8996
|
+
testcontainers: "Testcontainers",
|
|
8997
|
+
assertj: "AssertJ",
|
|
8998
|
+
"rest-assured": "REST Assured",
|
|
8999
|
+
wiremock: "WireMock",
|
|
9000
|
+
awaitility: "Awaitility",
|
|
9001
|
+
archunit: "ArchUnit",
|
|
9002
|
+
jqwik: "jqwik"
|
|
8875
9003
|
};
|
|
8876
9004
|
const testingList = effectiveJavaTestingLibraries.map((library) => testingNames[library] || library).join(", ");
|
|
8877
9005
|
output += `${pc.cyan("•")} Testing: ${testingList}\n`;
|
|
@@ -9402,9 +9530,10 @@ function displaySponsorsBox(sponsors$1) {
|
|
|
9402
9530
|
|
|
9403
9531
|
//#endregion
|
|
9404
9532
|
//#region src/index.ts
|
|
9533
|
+
const OPTION_ENTRY_COUNT = Object.values(types_exports.OPTION_CATEGORY_METADATA).reduce((sum, metadata) => sum + metadata.options.length, 0);
|
|
9405
9534
|
const router = os.router({
|
|
9406
9535
|
create: os.meta({
|
|
9407
|
-
description:
|
|
9536
|
+
description: `Scaffold a new Better Fullstack project from ${OPTION_ENTRY_COUNT} compatible stack options`,
|
|
9408
9537
|
default: true,
|
|
9409
9538
|
negateBooleans: true
|
|
9410
9539
|
}).input(CreateCommandInputSchema).handler(async ({ input }) => {
|
package/dist/mcp-entry.mjs
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { i as getLatestCLIVersion, r as writeBtsConfig, t as readBtsConfig } from "./bts-config-B_rZ4_sj.mjs";
|
|
3
3
|
import z from "zod";
|
|
4
|
-
import { AISchema, APISchema, AddonsSchema, AnalyticsSchema, AnimationSchema, AstroIntegrationSchema, AuthSchema, BackendSchema, CMSSchema, CSSFrameworkSchema, CachingSchema, DatabaseSchema, DatabaseSetupSchema, EcosystemSchema, EffectSchema, EmailSchema, ExamplesSchema, FeatureFlagsSchema, FileStorageSchema, FileUploadSchema, FormsSchema, FrontendSchema, GoApiSchema, GoAuthSchema, GoCliSchema, GoLoggingSchema, GoOrmSchema, GoWebFrameworkSchema, I18nSchema, JavaAuthSchema, JavaBuildToolSchema, JavaLibrariesSchema, JavaOrmSchema, JavaTestingLibrariesSchema, JavaWebFrameworkSchema, JobQueueSchema, LoggingSchema, ORMSchema, ObservabilitySchema, PackageManagerSchema, PaymentsSchema, PythonAiSchema, PythonAuthSchema, PythonGraphqlSchema, PythonOrmSchema, PythonQualitySchema, PythonTaskQueueSchema, PythonValidationSchema, PythonWebFrameworkSchema, RealtimeSchema, RuntimeSchema, RustApiSchema, RustAuthSchema, RustCachingSchema, RustCliSchema, RustErrorHandlingSchema, RustFrontendSchema, RustLibrariesSchema, RustLoggingSchema, RustOrmSchema, RustWebFrameworkSchema, SearchSchema, ServerDeploySchema, StateManagementSchema, TestingSchema, UILibrarySchema, ValidationSchema, WebDeploySchema, analyzeStackCompatibility } from "@better-fullstack/types";
|
|
4
|
+
import { AISchema, APISchema, AddonsSchema, AnalyticsSchema, AnimationSchema, AstroIntegrationSchema, AuthSchema, BackendSchema, CMSSchema, CSSFrameworkSchema, CachingSchema, DatabaseSchema, DatabaseSetupSchema, EcosystemSchema, EffectSchema, EmailSchema, ExamplesSchema, FeatureFlagsSchema, FileStorageSchema, FileUploadSchema, FormsSchema, FrontendSchema, GoApiSchema, GoAuthSchema, GoCliSchema, GoLoggingSchema, GoOrmSchema, GoWebFrameworkSchema, I18nSchema, JavaAuthSchema, JavaBuildToolSchema, JavaLibrariesSchema, JavaOrmSchema, JavaTestingLibrariesSchema, JavaWebFrameworkSchema, JobQueueSchema, LoggingSchema, OPTION_CATEGORY_METADATA, ORMSchema, ObservabilitySchema, PackageManagerSchema, PaymentsSchema, PythonAiSchema, PythonAuthSchema, PythonGraphqlSchema, PythonOrmSchema, PythonQualitySchema, PythonTaskQueueSchema, PythonValidationSchema, PythonWebFrameworkSchema, RealtimeSchema, RuntimeSchema, RustApiSchema, RustAuthSchema, RustCachingSchema, RustCliSchema, RustErrorHandlingSchema, RustFrontendSchema, RustLibrariesSchema, RustLoggingSchema, RustOrmSchema, RustWebFrameworkSchema, SearchSchema, ServerDeploySchema, StateManagementSchema, TestingSchema, UILibrarySchema, ValidationSchema, WebDeploySchema, analyzeStackCompatibility } from "@better-fullstack/types";
|
|
5
5
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
6
6
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
7
7
|
|
|
8
8
|
//#region src/mcp.ts
|
|
9
|
-
const INSTRUCTIONS = `Better-Fullstack scaffolds fullstack projects across TypeScript, Rust, Go, Python, and Java ecosystems with
|
|
9
|
+
const INSTRUCTIONS = `Better-Fullstack scaffolds fullstack projects across TypeScript, Rust, Go, Python, and Java ecosystems with ${Object.values(OPTION_CATEGORY_METADATA).reduce((sum, metadata) => sum + metadata.options.length, 0)} configurable options.
|
|
10
10
|
|
|
11
11
|
RECOMMENDED WORKFLOW:
|
|
12
12
|
1. Call bfs_get_guidance to understand field semantics, required fields, and workflow rules.
|
|
@@ -766,7 +766,7 @@ async function startMcpServer() {
|
|
|
766
766
|
await writeBtsConfig(config);
|
|
767
767
|
let addonWarnings = [];
|
|
768
768
|
if (config.addons.length > 0 && config.addons[0] !== "none") {
|
|
769
|
-
const { setupAddons } = await import("./addons-setup-
|
|
769
|
+
const { setupAddons } = await import("./addons-setup-CBK1Htlc.mjs");
|
|
770
770
|
addonWarnings = await setupAddons(config);
|
|
771
771
|
}
|
|
772
772
|
const installCmd = getInstallCommand(input.ecosystem ?? "typescript", projectName, input.packageManager, input.javaBuildTool);
|
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,11 +127,11 @@
|
|
|
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
|
-
"@orpc/server": "^1.
|
|
134
|
+
"@orpc/server": "^1.14.0",
|
|
135
135
|
"consola": "^3.4.2",
|
|
136
136
|
"env-paths": "^4.0.0",
|
|
137
137
|
"execa": "^9.6.1",
|
|
@@ -149,7 +149,7 @@
|
|
|
149
149
|
"zod": "^4.3.6"
|
|
150
150
|
},
|
|
151
151
|
"devDependencies": {
|
|
152
|
-
"@types/bun": "^1.3.
|
|
152
|
+
"@types/bun": "^1.3.13",
|
|
153
153
|
"@types/fs-extra": "^11.0.4",
|
|
154
154
|
"@types/node": "^25.6.0",
|
|
155
155
|
"publint": "^0.3.18",
|