create-better-fullstack 1.1.16 → 1.2.0
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 +1 -1
- package/dist/cli.mjs +1 -1
- package/dist/index.d.mts +12 -4
- package/dist/index.mjs +1 -1
- package/dist/{src-DDAojCKV.mjs → src-BJjCw5ar.mjs} +184 -35
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -33,7 +33,7 @@ Options:
|
|
|
33
33
|
--runtime <runtime> Runtime (bun, node, workers, none)
|
|
34
34
|
--api <type> API type (trpc, orpc, ts-rest, garph, none)
|
|
35
35
|
--addons <types...> Additional addons
|
|
36
|
-
--examples <types...> Examples to include (
|
|
36
|
+
--examples <types...> Examples to include (ai, none)
|
|
37
37
|
--git / --no-git Initialize git repository
|
|
38
38
|
--package-manager <pm> Package manager (npm, pnpm, bun)
|
|
39
39
|
--install / --no-install Install dependencies
|
package/dist/cli.mjs
CHANGED
package/dist/index.d.mts
CHANGED
|
@@ -236,7 +236,6 @@ declare const router: {
|
|
|
236
236
|
}>>>;
|
|
237
237
|
examples: z.ZodOptional<z.ZodArray<z.ZodEnum<{
|
|
238
238
|
none: "none";
|
|
239
|
-
todo: "todo";
|
|
240
239
|
ai: "ai";
|
|
241
240
|
}>>>;
|
|
242
241
|
git: z.ZodOptional<z.ZodBoolean>;
|
|
@@ -419,6 +418,12 @@ declare const router: {
|
|
|
419
418
|
none: "none";
|
|
420
419
|
zap: "zap";
|
|
421
420
|
}>>;
|
|
421
|
+
aiDocs: z.ZodOptional<z.ZodArray<z.ZodEnum<{
|
|
422
|
+
none: "none";
|
|
423
|
+
"claude-md": "claude-md";
|
|
424
|
+
"agents-md": "agents-md";
|
|
425
|
+
cursorrules: "cursorrules";
|
|
426
|
+
}>>>;
|
|
422
427
|
}, z.core.$strip>], null>, _orpc_server0.Schema<{
|
|
423
428
|
success: boolean;
|
|
424
429
|
projectConfig: {
|
|
@@ -432,7 +437,7 @@ declare const router: {
|
|
|
432
437
|
runtime: "none" | "bun" | "node" | "workers";
|
|
433
438
|
frontend: ("none" | "tanstack-router" | "react-router" | "tanstack-start" | "next" | "nuxt" | "native-bare" | "native-uniwind" | "native-unistyles" | "svelte" | "solid" | "astro" | "qwik" | "angular" | "redwood" | "fresh")[];
|
|
434
439
|
addons: ("none" | "pwa" | "tauri" | "starlight" | "biome" | "lefthook" | "husky" | "ruler" | "turborepo" | "fumadocs" | "ultracite" | "oxlint" | "opentui" | "wxt" | "msw" | "storybook")[];
|
|
435
|
-
examples: ("ai" | "none"
|
|
440
|
+
examples: ("ai" | "none")[];
|
|
436
441
|
auth: "none" | "better-auth" | "clerk" | "nextauth" | "stack-auth" | "supabase-auth" | "auth0";
|
|
437
442
|
payments: "none" | "polar" | "stripe" | "lemon-squeezy" | "paddle" | "dodo";
|
|
438
443
|
git: boolean;
|
|
@@ -480,6 +485,7 @@ declare const router: {
|
|
|
480
485
|
goApi: "none" | "grpc-go";
|
|
481
486
|
goCli: "none" | "cobra" | "bubbletea";
|
|
482
487
|
goLogging: "none" | "zap";
|
|
488
|
+
aiDocs: ("none" | "claude-md" | "agents-md" | "cursorrules")[];
|
|
483
489
|
astroIntegration?: "none" | "svelte" | "solid" | "react" | "vue" | undefined;
|
|
484
490
|
};
|
|
485
491
|
reproducibleCommand: string;
|
|
@@ -510,7 +516,7 @@ declare const router: {
|
|
|
510
516
|
runtime: "none" | "bun" | "node" | "workers";
|
|
511
517
|
frontend: ("none" | "tanstack-router" | "react-router" | "tanstack-start" | "next" | "nuxt" | "native-bare" | "native-uniwind" | "native-unistyles" | "svelte" | "solid" | "astro" | "qwik" | "angular" | "redwood" | "fresh")[];
|
|
512
518
|
addons: ("none" | "pwa" | "tauri" | "starlight" | "biome" | "lefthook" | "husky" | "ruler" | "turborepo" | "fumadocs" | "ultracite" | "oxlint" | "opentui" | "wxt" | "msw" | "storybook")[];
|
|
513
|
-
examples: ("ai" | "none"
|
|
519
|
+
examples: ("ai" | "none")[];
|
|
514
520
|
auth: "none" | "better-auth" | "clerk" | "nextauth" | "stack-auth" | "supabase-auth" | "auth0";
|
|
515
521
|
payments: "none" | "polar" | "stripe" | "lemon-squeezy" | "paddle" | "dodo";
|
|
516
522
|
git: boolean;
|
|
@@ -558,6 +564,7 @@ declare const router: {
|
|
|
558
564
|
goApi: "none" | "grpc-go";
|
|
559
565
|
goCli: "none" | "cobra" | "bubbletea";
|
|
560
566
|
goLogging: "none" | "zap";
|
|
567
|
+
aiDocs: ("none" | "claude-md" | "agents-md" | "cursorrules")[];
|
|
561
568
|
astroIntegration?: "none" | "svelte" | "solid" | "react" | "vue" | undefined;
|
|
562
569
|
};
|
|
563
570
|
reproducibleCommand: string;
|
|
@@ -642,6 +649,7 @@ declare function createVirtual(options: Partial<Omit<types_d_exports.ProjectConf
|
|
|
642
649
|
}>;
|
|
643
650
|
type API = import__better_fullstack_types.API;
|
|
644
651
|
type Addons = import__better_fullstack_types.Addons;
|
|
652
|
+
type AiDocs = import__better_fullstack_types.AiDocs;
|
|
645
653
|
type Analytics = import__better_fullstack_types.Analytics;
|
|
646
654
|
type Animation = import__better_fullstack_types.Animation;
|
|
647
655
|
type Auth = import__better_fullstack_types.Auth;
|
|
@@ -686,4 +694,4 @@ type ServerDeploy = import__better_fullstack_types.ServerDeploy;
|
|
|
686
694
|
type Template = import__better_fullstack_types.Template;
|
|
687
695
|
type UILibrary = import__better_fullstack_types.UILibrary;
|
|
688
696
|
type WebDeploy = import__better_fullstack_types.WebDeploy;
|
|
689
|
-
export { type API, type Addons, type Analytics, type Animation, type Auth, type Backend, type BetterTStackConfig, type CMS, type CSSFramework, type Caching, type CreateInput, type Database, type DatabaseSetup, type DirectoryConflict, EMBEDDED_TEMPLATES, type Ecosystem, type Effect, type Examples, type Frontend, type GeneratorOptions, type GeneratorResult, type GoApi, type GoCli, type GoLogging, type GoOrm, type GoWebFramework, type InitResult, type Logging, type ORM, type PackageManager, type Payments, type PythonAi, type PythonOrm, type PythonQuality, type PythonTaskQueue, type PythonValidation, type PythonWebFramework, type Realtime, type Runtime, type RustApi, type RustCli, type RustFrontend, type RustLibraries, type RustOrm, type RustWebFramework, type ServerDeploy, TEMPLATE_COUNT, type Template, type UILibrary, type VirtualDirectory, type VirtualFile, VirtualFileSystem, type VirtualFileTree, type VirtualNode, type WebDeploy, builder, create, createBtsCli, createVirtual, docs, generateVirtualProject, router, sponsors };
|
|
697
|
+
export { type API, type Addons, type AiDocs, type Analytics, type Animation, type Auth, type Backend, type BetterTStackConfig, type CMS, type CSSFramework, type Caching, type CreateInput, type Database, type DatabaseSetup, type DirectoryConflict, EMBEDDED_TEMPLATES, type Ecosystem, type Effect, type Examples, type Frontend, type GeneratorOptions, type GeneratorResult, type GoApi, type GoCli, type GoLogging, type GoOrm, type GoWebFramework, type InitResult, type Logging, type ORM, type PackageManager, type Payments, type PythonAi, type PythonOrm, type PythonQuality, type PythonTaskQueue, type PythonValidation, type PythonWebFramework, type Realtime, type Runtime, type RustApi, type RustCli, type RustFrontend, type RustLibraries, type RustOrm, type RustWebFramework, type ServerDeploy, TEMPLATE_COUNT, type Template, type UILibrary, type VirtualDirectory, type VirtualFile, VirtualFileSystem, type VirtualFileTree, type VirtualNode, type WebDeploy, builder, create, createBtsCli, createVirtual, docs, generateVirtualProject, router, sponsors };
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { a as create, c as docs, d as sponsors, i as builder, l as generateVirtualProject, n as TEMPLATE_COUNT, o as createBtsCli, r as VirtualFileSystem, s as createVirtual, t as EMBEDDED_TEMPLATES, u as router } from "./src-
|
|
2
|
+
import { a as create, c as docs, d as sponsors, i as builder, l as generateVirtualProject, n as TEMPLATE_COUNT, o as createBtsCli, r as VirtualFileSystem, s as createVirtual, t as EMBEDDED_TEMPLATES, u as router } from "./src-BJjCw5ar.mjs";
|
|
3
3
|
|
|
4
4
|
export { EMBEDDED_TEMPLATES, TEMPLATE_COUNT, VirtualFileSystem, builder, create, createBtsCli, createVirtual, docs, generateVirtualProject, router, sponsors };
|
|
@@ -266,7 +266,8 @@ const DEFAULT_CONFIG_BASE = {
|
|
|
266
266
|
goOrm: "gorm",
|
|
267
267
|
goApi: "none",
|
|
268
268
|
goCli: "none",
|
|
269
|
-
goLogging: "zap"
|
|
269
|
+
goLogging: "zap",
|
|
270
|
+
aiDocs: ["claude-md"]
|
|
270
271
|
};
|
|
271
272
|
function getDefaultConfig() {
|
|
272
273
|
return {
|
|
@@ -277,7 +278,8 @@ function getDefaultConfig() {
|
|
|
277
278
|
addons: [...DEFAULT_CONFIG_BASE.addons],
|
|
278
279
|
examples: [...DEFAULT_CONFIG_BASE.examples],
|
|
279
280
|
rustLibraries: [...DEFAULT_CONFIG_BASE.rustLibraries],
|
|
280
|
-
pythonAi: [...DEFAULT_CONFIG_BASE.pythonAi]
|
|
281
|
+
pythonAi: [...DEFAULT_CONFIG_BASE.pythonAi],
|
|
282
|
+
aiDocs: [...DEFAULT_CONFIG_BASE.aiDocs]
|
|
281
283
|
};
|
|
282
284
|
}
|
|
283
285
|
const DEFAULT_CONFIG = getDefaultConfig();
|
|
@@ -950,11 +952,6 @@ function allowedApisForFrontends(frontends = [], astroIntegration) {
|
|
|
950
952
|
if (includesAstro && astroIntegration && astroIntegration !== "react") return ["orpc", "none"];
|
|
951
953
|
return base;
|
|
952
954
|
}
|
|
953
|
-
function isExampleTodoAllowed(backend, database, api) {
|
|
954
|
-
if (backend === "convex") return true;
|
|
955
|
-
if (database === "none" || api === "none") return false;
|
|
956
|
-
return true;
|
|
957
|
-
}
|
|
958
955
|
function isExampleAIAllowed(backend, frontends = []) {
|
|
959
956
|
if (frontends.includes("solid")) return false;
|
|
960
957
|
if (backend === "convex") {
|
|
@@ -995,13 +992,9 @@ function validatePaymentsCompatibility(payments, auth, _backend, frontends = [])
|
|
|
995
992
|
if (web.length === 0 && frontends.length > 0) exitWithError("Polar payments requires a web frontend or no frontend. Please select a web frontend or choose a different payments provider.");
|
|
996
993
|
}
|
|
997
994
|
}
|
|
998
|
-
function validateExamplesCompatibility(examples, backend,
|
|
995
|
+
function validateExamplesCompatibility(examples, backend, frontend) {
|
|
999
996
|
const examplesArr = examples ?? [];
|
|
1000
997
|
if (examplesArr.length === 0 || examplesArr.includes("none")) return;
|
|
1001
|
-
if (examplesArr.includes("todo") && backend !== "convex") {
|
|
1002
|
-
if (database === "none") exitWithError("The 'todo' example requires a database. Cannot use --examples todo when database is 'none'.");
|
|
1003
|
-
if (api === "none") exitWithError("The 'todo' example requires an API layer (tRPC or oRPC). Cannot use --examples todo when api is 'none'.");
|
|
1004
|
-
}
|
|
1005
998
|
if (examplesArr.includes("ai") && (frontend ?? []).includes("solid")) exitWithError("The 'ai' example is not compatible with the Solid frontend.");
|
|
1006
999
|
if (examplesArr.includes("ai") && backend === "convex") {
|
|
1007
1000
|
const frontendArr = frontend ?? [];
|
|
@@ -1546,6 +1539,42 @@ async function getAIChoice(ai) {
|
|
|
1546
1539
|
return response;
|
|
1547
1540
|
}
|
|
1548
1541
|
|
|
1542
|
+
//#endregion
|
|
1543
|
+
//#region src/prompts/ai-docs.ts
|
|
1544
|
+
const AI_DOCS_OPTIONS = [
|
|
1545
|
+
{
|
|
1546
|
+
value: "claude-md",
|
|
1547
|
+
label: "CLAUDE.md",
|
|
1548
|
+
hint: "Claude Code CLI documentation"
|
|
1549
|
+
},
|
|
1550
|
+
{
|
|
1551
|
+
value: "agents-md",
|
|
1552
|
+
label: "Agents.md",
|
|
1553
|
+
hint: "Generic AI assistant documentation"
|
|
1554
|
+
},
|
|
1555
|
+
{
|
|
1556
|
+
value: "cursorrules",
|
|
1557
|
+
label: ".cursorrules",
|
|
1558
|
+
hint: "Cursor IDE rules file"
|
|
1559
|
+
},
|
|
1560
|
+
{
|
|
1561
|
+
value: "none",
|
|
1562
|
+
label: "None",
|
|
1563
|
+
hint: "Skip AI documentation"
|
|
1564
|
+
}
|
|
1565
|
+
];
|
|
1566
|
+
async function getAiDocsChoice(aiDocs) {
|
|
1567
|
+
if (aiDocs !== void 0) return aiDocs;
|
|
1568
|
+
const response = await navigableMultiselect({
|
|
1569
|
+
message: "Generate AI documentation files?",
|
|
1570
|
+
options: AI_DOCS_OPTIONS,
|
|
1571
|
+
initialValues: DEFAULT_CONFIG.aiDocs
|
|
1572
|
+
});
|
|
1573
|
+
if (isCancel$1(response)) return exitCancelled("Operation cancelled");
|
|
1574
|
+
if (response.includes("none")) return [];
|
|
1575
|
+
return response;
|
|
1576
|
+
}
|
|
1577
|
+
|
|
1549
1578
|
//#endregion
|
|
1550
1579
|
//#region src/prompts/animation.ts
|
|
1551
1580
|
async function getAnimationChoice(animation, frontends) {
|
|
@@ -2237,16 +2266,11 @@ async function getEmailChoice(email, backend) {
|
|
|
2237
2266
|
|
|
2238
2267
|
//#endregion
|
|
2239
2268
|
//#region src/prompts/examples.ts
|
|
2240
|
-
async function getExamplesChoice(examples,
|
|
2269
|
+
async function getExamplesChoice(examples, frontends, backend) {
|
|
2241
2270
|
if (examples !== void 0) return examples;
|
|
2242
2271
|
if (backend === "none") return [];
|
|
2243
2272
|
let response = [];
|
|
2244
2273
|
const options = [];
|
|
2245
|
-
if (isExampleTodoAllowed(backend, database, api)) options.push({
|
|
2246
|
-
value: "todo",
|
|
2247
|
-
label: "Todo App",
|
|
2248
|
-
hint: "A simple CRUD example app"
|
|
2249
|
-
});
|
|
2250
2274
|
if (isExampleAIAllowed(backend, frontends ?? [])) options.push({
|
|
2251
2275
|
value: "ai",
|
|
2252
2276
|
label: "AI Chat",
|
|
@@ -2691,6 +2715,18 @@ async function getinstallChoice(install, ecosystem) {
|
|
|
2691
2715
|
if (isCancel$1(response$1)) return exitCancelled("Operation cancelled");
|
|
2692
2716
|
return response$1;
|
|
2693
2717
|
}
|
|
2718
|
+
if (ecosystem === "go") {
|
|
2719
|
+
if (!await commandExists("go")) {
|
|
2720
|
+
log.warn("Go is not installed. Please install Go from https://go.dev/dl/");
|
|
2721
|
+
return false;
|
|
2722
|
+
}
|
|
2723
|
+
const response$1 = await navigableConfirm({
|
|
2724
|
+
message: "Run go mod tidy?",
|
|
2725
|
+
initialValue: DEFAULT_CONFIG.install
|
|
2726
|
+
});
|
|
2727
|
+
if (isCancel$1(response$1)) return exitCancelled("Operation cancelled");
|
|
2728
|
+
return response$1;
|
|
2729
|
+
}
|
|
2694
2730
|
const response = await navigableConfirm({
|
|
2695
2731
|
message: "Install dependencies?",
|
|
2696
2732
|
initialValue: DEFAULT_CONFIG.install
|
|
@@ -3772,7 +3808,7 @@ async function gatherConfig(flags, projectName, projectDir, relativePath) {
|
|
|
3772
3808
|
},
|
|
3773
3809
|
examples: ({ results }) => {
|
|
3774
3810
|
if (results.ecosystem !== "typescript") return Promise.resolve([]);
|
|
3775
|
-
return getExamplesChoice(flags.examples, results.
|
|
3811
|
+
return getExamplesChoice(flags.examples, results.frontend, results.backend);
|
|
3776
3812
|
},
|
|
3777
3813
|
dbSetup: ({ results }) => {
|
|
3778
3814
|
if (results.ecosystem !== "typescript") return Promise.resolve("none");
|
|
@@ -3922,6 +3958,7 @@ async function gatherConfig(flags, projectName, projectDir, relativePath) {
|
|
|
3922
3958
|
if (results.ecosystem !== "go") return Promise.resolve("none");
|
|
3923
3959
|
return getGoLoggingChoice(flags.goLogging);
|
|
3924
3960
|
},
|
|
3961
|
+
aiDocs: () => getAiDocsChoice(flags.aiDocs),
|
|
3925
3962
|
git: () => getGitChoice(flags.git),
|
|
3926
3963
|
packageManager: ({ results }) => {
|
|
3927
3964
|
if (results.ecosystem === "rust" || results.ecosystem === "python" || results.ecosystem === "go") return Promise.resolve("npm");
|
|
@@ -3988,7 +4025,8 @@ async function gatherConfig(flags, projectName, projectDir, relativePath) {
|
|
|
3988
4025
|
goOrm: result.goOrm,
|
|
3989
4026
|
goApi: result.goApi,
|
|
3990
4027
|
goCli: result.goCli,
|
|
3991
|
-
goLogging: result.goLogging
|
|
4028
|
+
goLogging: result.goLogging,
|
|
4029
|
+
aiDocs: result.aiDocs
|
|
3992
4030
|
};
|
|
3993
4031
|
}
|
|
3994
4032
|
|
|
@@ -4159,6 +4197,11 @@ function generateReproducibleCommand(config) {
|
|
|
4159
4197
|
flags.push(`--db-setup ${config.dbSetup}`);
|
|
4160
4198
|
flags.push(`--web-deploy ${config.webDeploy}`);
|
|
4161
4199
|
flags.push(`--server-deploy ${config.serverDeploy}`);
|
|
4200
|
+
if (config.aiDocs && config.aiDocs.length > 0) {
|
|
4201
|
+
const validDocs = config.aiDocs.filter((d) => d !== "none");
|
|
4202
|
+
if (validDocs.length > 0) flags.push(`--ai-docs ${validDocs.join(" ")}`);
|
|
4203
|
+
else flags.push("--ai-docs none");
|
|
4204
|
+
} else flags.push("--ai-docs none");
|
|
4162
4205
|
flags.push(config.git ? "--git" : "--no-git");
|
|
4163
4206
|
flags.push(`--package-manager ${config.packageManager}`);
|
|
4164
4207
|
flags.push(config.install ? "--install" : "--no-install");
|
|
@@ -4297,7 +4340,7 @@ const TEMPLATE_PRESETS = {
|
|
|
4297
4340
|
auth: "better-auth",
|
|
4298
4341
|
payments: "none",
|
|
4299
4342
|
addons: ["turborepo"],
|
|
4300
|
-
examples: ["
|
|
4343
|
+
examples: ["none"],
|
|
4301
4344
|
dbSetup: "mongodb-atlas",
|
|
4302
4345
|
webDeploy: "none",
|
|
4303
4346
|
serverDeploy: "none"
|
|
@@ -4312,7 +4355,7 @@ const TEMPLATE_PRESETS = {
|
|
|
4312
4355
|
auth: "better-auth",
|
|
4313
4356
|
payments: "none",
|
|
4314
4357
|
addons: ["turborepo"],
|
|
4315
|
-
examples: ["
|
|
4358
|
+
examples: ["none"],
|
|
4316
4359
|
dbSetup: "none",
|
|
4317
4360
|
webDeploy: "none",
|
|
4318
4361
|
serverDeploy: "none"
|
|
@@ -4420,6 +4463,7 @@ function processFlags(options, projectName) {
|
|
|
4420
4463
|
if (options.uiLibrary) config.uiLibrary = options.uiLibrary;
|
|
4421
4464
|
if (options.addons && options.addons.length > 0) config.addons = processArrayOption(options.addons);
|
|
4422
4465
|
if (options.examples && options.examples.length > 0) config.examples = processArrayOption(options.examples);
|
|
4466
|
+
if (options.aiDocs !== void 0) config.aiDocs = processArrayOption(options.aiDocs);
|
|
4423
4467
|
return config;
|
|
4424
4468
|
}
|
|
4425
4469
|
function getProvidedFlags(options) {
|
|
@@ -4880,11 +4924,7 @@ function validateFrontendConstraints(config, providedFlags) {
|
|
|
4880
4924
|
const hasWebFrontendFlag = (frontend ?? []).some((f) => isWebFrontend(f));
|
|
4881
4925
|
validateWebDeployRequiresWebFrontend(config.webDeploy, hasWebFrontendFlag);
|
|
4882
4926
|
}
|
|
4883
|
-
function validateApiConstraints(
|
|
4884
|
-
if (config.api === "none") {
|
|
4885
|
-
if (options.examples?.includes("todo") && options.backend !== "convex" && options.backend !== "none") exitWithError("Cannot use '--examples todo' when '--api' is set to 'none'. The todo example requires an API layer. Please remove 'todo' from --examples or choose an API type.");
|
|
4886
|
-
}
|
|
4887
|
-
}
|
|
4927
|
+
function validateApiConstraints(_config, _options) {}
|
|
4888
4928
|
function validateFullConfig(config, providedFlags, options) {
|
|
4889
4929
|
validateDatabaseOrmAuth(config, providedFlags);
|
|
4890
4930
|
validateDatabaseSetup(config, providedFlags);
|
|
@@ -4895,7 +4935,7 @@ function validateFullConfig(config, providedFlags, options) {
|
|
|
4895
4935
|
validateAdonisJSConstraints(config, providedFlags);
|
|
4896
4936
|
validateBackendConstraints(config, providedFlags, options);
|
|
4897
4937
|
validateFrontendConstraints(config, providedFlags);
|
|
4898
|
-
validateApiConstraints(config, options);
|
|
4938
|
+
/* @__PURE__ */ validateApiConstraints(config, options);
|
|
4899
4939
|
validateServerDeployRequiresBackend(config.serverDeploy, config.backend);
|
|
4900
4940
|
validateSelfBackendCompatibility(providedFlags, options, config);
|
|
4901
4941
|
validateWorkersCompatibility(providedFlags, options, config);
|
|
@@ -4905,7 +4945,7 @@ function validateFullConfig(config, providedFlags, options) {
|
|
|
4905
4945
|
validateAddonsAgainstFrontends(config.addons, config.frontend, config.auth);
|
|
4906
4946
|
config.addons = [...new Set(config.addons)];
|
|
4907
4947
|
}
|
|
4908
|
-
validateExamplesCompatibility(config.examples ?? [], config.backend, config.
|
|
4948
|
+
validateExamplesCompatibility(config.examples ?? [], config.backend, config.frontend ?? []);
|
|
4909
4949
|
validatePaymentsCompatibility(config.payments, config.auth, config.backend, config.frontend ?? []);
|
|
4910
4950
|
validateNextAuthCompatibility(config.auth, config.backend, config.frontend ?? []);
|
|
4911
4951
|
validateStackAuthCompatibility(config.auth, config.backend, config.frontend ?? []);
|
|
@@ -4926,7 +4966,7 @@ function validateConfigForProgrammaticUse(config) {
|
|
|
4926
4966
|
validateSupabaseAuthCompatibility(config.auth, config.backend, config.frontend ?? []);
|
|
4927
4967
|
validateAuth0Compatibility(config.auth, config.backend, config.frontend ?? []);
|
|
4928
4968
|
if (config.addons && config.addons.length > 0) validateAddonsAgainstFrontends(config.addons, config.frontend, config.auth);
|
|
4929
|
-
validateExamplesCompatibility(config.examples ?? [], config.backend, config.
|
|
4969
|
+
validateExamplesCompatibility(config.examples ?? [], config.backend, config.frontend ?? []);
|
|
4930
4970
|
validateUILibraryFrontendCompatibility(config.uiLibrary, config.frontend ?? [], config.astroIntegration);
|
|
4931
4971
|
validateUILibraryCSSFrameworkCompatibility(config.uiLibrary, config.cssFramework);
|
|
4932
4972
|
validatePeerDependencies(config);
|
|
@@ -5074,7 +5114,8 @@ async function writeBtsConfig(projectConfig) {
|
|
|
5074
5114
|
goOrm: projectConfig.goOrm,
|
|
5075
5115
|
goApi: projectConfig.goApi,
|
|
5076
5116
|
goCli: projectConfig.goCli,
|
|
5077
|
-
goLogging: projectConfig.goLogging
|
|
5117
|
+
goLogging: projectConfig.goLogging,
|
|
5118
|
+
aiDocs: projectConfig.aiDocs
|
|
5078
5119
|
};
|
|
5079
5120
|
const baseContent = {
|
|
5080
5121
|
$schema: "https://better-fullstack-web.vercel.app/schema.json",
|
|
@@ -5132,7 +5173,8 @@ async function writeBtsConfig(projectConfig) {
|
|
|
5132
5173
|
goOrm: btsConfig.goOrm,
|
|
5133
5174
|
goApi: btsConfig.goApi,
|
|
5134
5175
|
goCli: btsConfig.goCli,
|
|
5135
|
-
goLogging: btsConfig.goLogging
|
|
5176
|
+
goLogging: btsConfig.goLogging,
|
|
5177
|
+
aiDocs: btsConfig.aiDocs
|
|
5136
5178
|
};
|
|
5137
5179
|
let configContent = JSON.stringify(baseContent);
|
|
5138
5180
|
const formatResult = JSONC.format(configContent, void 0, {
|
|
@@ -6983,6 +7025,20 @@ async function runUvSync({ projectDir }) {
|
|
|
6983
7025
|
if (error instanceof Error) consola.error(pc.red(`uv sync error: ${error.message}`));
|
|
6984
7026
|
}
|
|
6985
7027
|
}
|
|
7028
|
+
async function runGoModTidy({ projectDir }) {
|
|
7029
|
+
const s = spinner();
|
|
7030
|
+
try {
|
|
7031
|
+
s.start("Running go mod tidy...");
|
|
7032
|
+
await $({
|
|
7033
|
+
cwd: projectDir,
|
|
7034
|
+
stderr: "inherit"
|
|
7035
|
+
})`go mod tidy`;
|
|
7036
|
+
s.stop("Go dependencies installed successfully");
|
|
7037
|
+
} catch (error) {
|
|
7038
|
+
s.stop(pc.red("go mod tidy failed"));
|
|
7039
|
+
if (error instanceof Error) consola.error(pc.red(`go mod tidy error: ${error.message}`));
|
|
7040
|
+
}
|
|
7041
|
+
}
|
|
6986
7042
|
|
|
6987
7043
|
//#endregion
|
|
6988
7044
|
//#region src/utils/docker-utils.ts
|
|
@@ -7042,6 +7098,14 @@ async function displayPostInstallInstructions(config) {
|
|
|
7042
7098
|
displayRustInstructions(config);
|
|
7043
7099
|
return;
|
|
7044
7100
|
}
|
|
7101
|
+
if (ecosystem === "go") {
|
|
7102
|
+
displayGoInstructions(config);
|
|
7103
|
+
return;
|
|
7104
|
+
}
|
|
7105
|
+
if (ecosystem === "python") {
|
|
7106
|
+
displayPythonInstructions(config);
|
|
7107
|
+
return;
|
|
7108
|
+
}
|
|
7045
7109
|
const isConvex = backend === "convex";
|
|
7046
7110
|
const isBackendSelf = backend === "self";
|
|
7047
7111
|
const runCmd = packageManager === "npm" ? "npm run" : packageManager === "pnpm" ? "pnpm run" : "bun run";
|
|
@@ -7251,6 +7315,87 @@ function displayRustInstructions(config) {
|
|
|
7251
7315
|
output += pc.cyan("https://github.com/Marve10s/Better-Fullstack");
|
|
7252
7316
|
consola$1.box(output);
|
|
7253
7317
|
}
|
|
7318
|
+
function displayGoInstructions(config) {
|
|
7319
|
+
const { relativePath, depsInstalled, goWebFramework, goOrm, goApi, goCli, goLogging } = config;
|
|
7320
|
+
const cdCmd = `cd ${relativePath}`;
|
|
7321
|
+
let output = `${pc.bold("Next steps")}\n${pc.cyan("1.")} ${cdCmd}\n`;
|
|
7322
|
+
let stepCounter = 2;
|
|
7323
|
+
if (!depsInstalled) output += `${pc.cyan(`${stepCounter++}.`)} go mod tidy\n`;
|
|
7324
|
+
output += `${pc.cyan(`${stepCounter++}.`)} go run cmd/server/main.go\n`;
|
|
7325
|
+
output += `\n${pc.bold("Your Go project includes:")}\n`;
|
|
7326
|
+
if (goWebFramework && goWebFramework !== "none") output += `${pc.cyan("•")} Web Framework: ${{
|
|
7327
|
+
gin: "Gin",
|
|
7328
|
+
echo: "Echo"
|
|
7329
|
+
}[goWebFramework] || goWebFramework}\n`;
|
|
7330
|
+
if (goOrm && goOrm !== "none") output += `${pc.cyan("•")} Database: ${{
|
|
7331
|
+
gorm: "GORM",
|
|
7332
|
+
sqlc: "sqlc"
|
|
7333
|
+
}[goOrm] || goOrm}\n`;
|
|
7334
|
+
if (goApi && goApi !== "none") output += `${pc.cyan("•")} API: ${{ "grpc-go": "gRPC-Go" }[goApi] || goApi}\n`;
|
|
7335
|
+
if (goCli && goCli !== "none") output += `${pc.cyan("•")} CLI: ${{
|
|
7336
|
+
cobra: "Cobra",
|
|
7337
|
+
bubbletea: "Bubble Tea"
|
|
7338
|
+
}[goCli] || goCli}\n`;
|
|
7339
|
+
if (goLogging && goLogging !== "none") output += `${pc.cyan("•")} Logging: ${{ zap: "Zap" }[goLogging] || goLogging}\n`;
|
|
7340
|
+
output += `\n${pc.bold("Common Go commands:")}\n`;
|
|
7341
|
+
output += `${pc.cyan("•")} Build: go build ./...\n`;
|
|
7342
|
+
output += `${pc.cyan("•")} Run: go run cmd/server/main.go\n`;
|
|
7343
|
+
output += `${pc.cyan("•")} Test: go test ./...\n`;
|
|
7344
|
+
output += `${pc.cyan("•")} Tidy: go mod tidy\n`;
|
|
7345
|
+
output += `${pc.cyan("•")} Format: go fmt ./...\n`;
|
|
7346
|
+
output += `${pc.cyan("•")} Lint: golangci-lint run\n`;
|
|
7347
|
+
output += `\n${pc.bold("Your project will be available at:")}\n`;
|
|
7348
|
+
output += `${pc.cyan("•")} API: http://localhost:8080\n`;
|
|
7349
|
+
if (goApi === "grpc-go") output += `${pc.cyan("•")} gRPC: localhost:50051\n`;
|
|
7350
|
+
output += `\n${pc.bold("Like Better Fullstack?")} Please consider giving us a star\n on GitHub:\n`;
|
|
7351
|
+
output += pc.cyan("https://github.com/Marve10s/Better-Fullstack");
|
|
7352
|
+
consola$1.box(output);
|
|
7353
|
+
}
|
|
7354
|
+
function displayPythonInstructions(config) {
|
|
7355
|
+
const { relativePath, depsInstalled, pythonWebFramework, pythonOrm, pythonValidation, pythonAi, pythonTaskQueue, pythonQuality } = config;
|
|
7356
|
+
const cdCmd = `cd ${relativePath}`;
|
|
7357
|
+
let runCommand = "uv run uvicorn app.main:app --reload";
|
|
7358
|
+
if (pythonWebFramework === "django") runCommand = "uv run python manage.py runserver";
|
|
7359
|
+
let output = `${pc.bold("Next steps")}\n${pc.cyan("1.")} ${cdCmd}\n`;
|
|
7360
|
+
let stepCounter = 2;
|
|
7361
|
+
if (!depsInstalled) output += `${pc.cyan(`${stepCounter++}.`)} uv sync\n`;
|
|
7362
|
+
output += `${pc.cyan(`${stepCounter++}.`)} ${runCommand}\n`;
|
|
7363
|
+
output += `\n${pc.bold("Your Python project includes:")}\n`;
|
|
7364
|
+
if (pythonWebFramework && pythonWebFramework !== "none") output += `${pc.cyan("•")} Web Framework: ${{
|
|
7365
|
+
fastapi: "FastAPI",
|
|
7366
|
+
django: "Django"
|
|
7367
|
+
}[pythonWebFramework] || pythonWebFramework}\n`;
|
|
7368
|
+
if (pythonOrm && pythonOrm !== "none") output += `${pc.cyan("•")} ORM: ${{
|
|
7369
|
+
sqlalchemy: "SQLAlchemy",
|
|
7370
|
+
sqlmodel: "SQLModel"
|
|
7371
|
+
}[pythonOrm] || pythonOrm}\n`;
|
|
7372
|
+
if (pythonValidation && pythonValidation !== "none") output += `${pc.cyan("•")} Validation: ${{ pydantic: "Pydantic" }[pythonValidation] || pythonValidation}\n`;
|
|
7373
|
+
if (pythonAi && pythonAi.length > 0 && !pythonAi.includes("none")) {
|
|
7374
|
+
const aiNames = {
|
|
7375
|
+
langchain: "LangChain",
|
|
7376
|
+
langgraph: "LangGraph",
|
|
7377
|
+
llamaindex: "LlamaIndex",
|
|
7378
|
+
"openai-sdk": "OpenAI SDK",
|
|
7379
|
+
"anthropic-sdk": "Anthropic SDK",
|
|
7380
|
+
crewai: "CrewAI"
|
|
7381
|
+
};
|
|
7382
|
+
const aiList = pythonAi.filter((ai) => ai !== "none").map((ai) => aiNames[ai] || ai).join(", ");
|
|
7383
|
+
output += `${pc.cyan("•")} AI: ${aiList}\n`;
|
|
7384
|
+
}
|
|
7385
|
+
if (pythonTaskQueue && pythonTaskQueue !== "none") output += `${pc.cyan("•")} Task Queue: ${{ celery: "Celery" }[pythonTaskQueue] || pythonTaskQueue}\n`;
|
|
7386
|
+
if (pythonQuality && pythonQuality !== "none") output += `${pc.cyan("•")} Code Quality: ${{ ruff: "Ruff" }[pythonQuality] || pythonQuality}\n`;
|
|
7387
|
+
output += `\n${pc.bold("Common Python commands:")}\n`;
|
|
7388
|
+
output += `${pc.cyan("•")} Install: uv sync\n`;
|
|
7389
|
+
output += `${pc.cyan("•")} Run: ${runCommand}\n`;
|
|
7390
|
+
output += `${pc.cyan("•")} Test: uv run pytest\n`;
|
|
7391
|
+
output += `${pc.cyan("•")} Format: uv run ruff format .\n`;
|
|
7392
|
+
output += `${pc.cyan("•")} Lint: uv run ruff check .\n`;
|
|
7393
|
+
output += `\n${pc.bold("Your project will be available at:")}\n`;
|
|
7394
|
+
output += `${pc.cyan("•")} API: http://localhost:8000\n`;
|
|
7395
|
+
output += `\n${pc.bold("Like Better Fullstack?")} Please consider giving us a star\n on GitHub:\n`;
|
|
7396
|
+
output += pc.cyan("https://github.com/Marve10s/Better-Fullstack");
|
|
7397
|
+
consola$1.box(output);
|
|
7398
|
+
}
|
|
7254
7399
|
|
|
7255
7400
|
//#endregion
|
|
7256
7401
|
//#region src/helpers/core/create-project.ts
|
|
@@ -7277,6 +7422,7 @@ async function createProject(options, cliInput = {}) {
|
|
|
7277
7422
|
});
|
|
7278
7423
|
if (options.install && options.ecosystem === "rust") await runCargoBuild({ projectDir });
|
|
7279
7424
|
if (options.install && options.ecosystem === "python") await runUvSync({ projectDir });
|
|
7425
|
+
if (options.install && options.ecosystem === "go") await runGoModTidy({ projectDir });
|
|
7280
7426
|
await initializeGit(projectDir, options.git);
|
|
7281
7427
|
if (!isSilent()) await displayPostInstallInstructions({
|
|
7282
7428
|
...options,
|
|
@@ -7406,7 +7552,8 @@ async function createProjectHandler(input, options = {}) {
|
|
|
7406
7552
|
goOrm: "none",
|
|
7407
7553
|
goApi: "none",
|
|
7408
7554
|
goCli: "none",
|
|
7409
|
-
goLogging: "none"
|
|
7555
|
+
goLogging: "none",
|
|
7556
|
+
aiDocs: []
|
|
7410
7557
|
},
|
|
7411
7558
|
reproducibleCommand: "",
|
|
7412
7559
|
timeScaffolded,
|
|
@@ -7678,7 +7825,8 @@ const router = os.router({
|
|
|
7678
7825
|
goOrm: types_exports.GoOrmSchema.optional().describe("Go ORM/database (gorm, sqlc)"),
|
|
7679
7826
|
goApi: types_exports.GoApiSchema.optional().describe("Go API layer (grpc-go)"),
|
|
7680
7827
|
goCli: types_exports.GoCliSchema.optional().describe("Go CLI tools (cobra, bubbletea)"),
|
|
7681
|
-
goLogging: types_exports.GoLoggingSchema.optional().describe("Go logging (zap)")
|
|
7828
|
+
goLogging: types_exports.GoLoggingSchema.optional().describe("Go logging (zap)"),
|
|
7829
|
+
aiDocs: z.array(types_exports.AiDocsSchema).optional().describe("AI documentation files (claude-md, agents-md, cursorrules)")
|
|
7682
7830
|
})])).handler(async ({ input }) => {
|
|
7683
7831
|
const [projectName, options] = input;
|
|
7684
7832
|
const result = await createProjectHandler({
|
|
@@ -7878,7 +8026,8 @@ async function createVirtual(options) {
|
|
|
7878
8026
|
goOrm: options.goOrm || "none",
|
|
7879
8027
|
goApi: options.goApi || "none",
|
|
7880
8028
|
goCli: options.goCli || "none",
|
|
7881
|
-
goLogging: options.goLogging || "none"
|
|
8029
|
+
goLogging: options.goLogging || "none",
|
|
8030
|
+
aiDocs: options.aiDocs || ["claude-md"]
|
|
7882
8031
|
},
|
|
7883
8032
|
templates: EMBEDDED_TEMPLATES
|
|
7884
8033
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-better-fullstack",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "A CLI-first toolkit for building Full Stack applications. Skip the configuration. Ship the code.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"better-auth",
|
|
@@ -76,8 +76,8 @@
|
|
|
76
76
|
"prepublishOnly": "npm run build"
|
|
77
77
|
},
|
|
78
78
|
"dependencies": {
|
|
79
|
-
"@better-fullstack/template-generator": "^1.
|
|
80
|
-
"@better-fullstack/types": "^1.
|
|
79
|
+
"@better-fullstack/template-generator": "^1.2.0",
|
|
80
|
+
"@better-fullstack/types": "^1.2.0",
|
|
81
81
|
"@clack/core": "^0.5.0",
|
|
82
82
|
"@clack/prompts": "^1.0.0-alpha.8",
|
|
83
83
|
"@orpc/server": "^1.13.0",
|