create-better-fullstack 1.4.6 → 1.4.8
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 +8 -2
- package/dist/index.mjs +1 -1
- package/dist/{src-B5kV0Yns.mjs → src-Cu97R-IA.mjs} +60 -194
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -26,7 +26,7 @@ Options:
|
|
|
26
26
|
--yolo Random configuration (experimental)
|
|
27
27
|
--database <type> Database type (none, sqlite, postgres, mysql, mongodb)
|
|
28
28
|
--orm <type> ORM type (drizzle, prisma, mongoose, typeorm, kysely, mikroorm, sequelize, none)
|
|
29
|
-
--auth <type> Authentication (better-auth, clerk, nextauth, none)
|
|
29
|
+
--auth <type> Authentication (better-auth, go-better-auth, clerk, nextauth, stack-auth, supabase-auth, auth0, none)
|
|
30
30
|
--payments <type> Payments (polar, stripe, lemon-squeezy, paddle, dodo, none)
|
|
31
31
|
--frontend <types...> Frontend types
|
|
32
32
|
--backend <framework> Backend framework
|
package/dist/cli.mjs
CHANGED
package/dist/index.d.mts
CHANGED
|
@@ -57,6 +57,7 @@ declare const router: {
|
|
|
57
57
|
auth: z.ZodOptional<z.ZodEnum<{
|
|
58
58
|
none: "none";
|
|
59
59
|
"better-auth": "better-auth";
|
|
60
|
+
"go-better-auth": "go-better-auth";
|
|
60
61
|
clerk: "clerk";
|
|
61
62
|
nextauth: "nextauth";
|
|
62
63
|
"stack-auth": "stack-auth";
|
|
@@ -179,6 +180,11 @@ declare const router: {
|
|
|
179
180
|
sentry: "sentry";
|
|
180
181
|
grafana: "grafana";
|
|
181
182
|
}>>;
|
|
183
|
+
featureFlags: z.ZodOptional<z.ZodEnum<{
|
|
184
|
+
none: "none";
|
|
185
|
+
growthbook: "growthbook";
|
|
186
|
+
posthog: "posthog";
|
|
187
|
+
}>>;
|
|
182
188
|
analytics: z.ZodOptional<z.ZodEnum<{
|
|
183
189
|
none: "none";
|
|
184
190
|
plausible: "plausible";
|
|
@@ -523,7 +529,7 @@ declare const router: {
|
|
|
523
529
|
frontend: ("none" | "tanstack-router" | "react-router" | "tanstack-start" | "next" | "nuxt" | "native-bare" | "native-uniwind" | "native-unistyles" | "svelte" | "solid" | "solid-start" | "astro" | "qwik" | "angular" | "redwood" | "fresh")[];
|
|
524
530
|
addons: ("none" | "pwa" | "tauri" | "starlight" | "biome" | "lefthook" | "husky" | "ruler" | "mcp" | "skills" | "turborepo" | "fumadocs" | "ultracite" | "oxlint" | "opentui" | "wxt" | "msw" | "storybook")[];
|
|
525
531
|
examples: ("ai" | "none" | "chat-sdk")[];
|
|
526
|
-
auth: "none" | "better-auth" | "clerk" | "nextauth" | "stack-auth" | "supabase-auth" | "auth0";
|
|
532
|
+
auth: "none" | "better-auth" | "go-better-auth" | "clerk" | "nextauth" | "stack-auth" | "supabase-auth" | "auth0";
|
|
527
533
|
payments: "none" | "polar" | "stripe" | "lemon-squeezy" | "paddle" | "dodo";
|
|
528
534
|
git: boolean;
|
|
529
535
|
packageManager: "bun" | "npm" | "pnpm";
|
|
@@ -609,7 +615,7 @@ declare const router: {
|
|
|
609
615
|
frontend: ("none" | "tanstack-router" | "react-router" | "tanstack-start" | "next" | "nuxt" | "native-bare" | "native-uniwind" | "native-unistyles" | "svelte" | "solid" | "solid-start" | "astro" | "qwik" | "angular" | "redwood" | "fresh")[];
|
|
610
616
|
addons: ("none" | "pwa" | "tauri" | "starlight" | "biome" | "lefthook" | "husky" | "ruler" | "mcp" | "skills" | "turborepo" | "fumadocs" | "ultracite" | "oxlint" | "opentui" | "wxt" | "msw" | "storybook")[];
|
|
611
617
|
examples: ("ai" | "none" | "chat-sdk")[];
|
|
612
|
-
auth: "none" | "better-auth" | "clerk" | "nextauth" | "stack-auth" | "supabase-auth" | "auth0";
|
|
618
|
+
auth: "none" | "better-auth" | "go-better-auth" | "clerk" | "nextauth" | "stack-auth" | "supabase-auth" | "auth0";
|
|
613
619
|
payments: "none" | "polar" | "stripe" | "lemon-squeezy" | "paddle" | "dodo";
|
|
614
620
|
git: boolean;
|
|
615
621
|
packageManager: "bun" | "npm" | "pnpm";
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { a as builder, c as createVirtual, d as history, f as router, i as add, l as docs, n as TEMPLATE_COUNT, o as create, p as sponsors, r as VirtualFileSystem, s as createBtsCli, t as EMBEDDED_TEMPLATES, u as generateVirtualProject } from "./src-
|
|
2
|
+
import { a as builder, c as createVirtual, d as history, f as router, i as add, l as docs, n as TEMPLATE_COUNT, o as create, p as sponsors, r as VirtualFileSystem, s as createBtsCli, t as EMBEDDED_TEMPLATES, u as generateVirtualProject } from "./src-Cu97R-IA.mjs";
|
|
3
3
|
|
|
4
4
|
export { EMBEDDED_TEMPLATES, TEMPLATE_COUNT, VirtualFileSystem, add, builder, create, createBtsCli, createVirtual, docs, generateVirtualProject, history, router, sponsors };
|
|
@@ -13,7 +13,7 @@ import { ECOSYSTEM_GROUPS, EMBEDDED_TEMPLATES, EMBEDDED_TEMPLATES as EMBEDDED_TE
|
|
|
13
13
|
import gradient from "gradient-string";
|
|
14
14
|
import path$1 from "path";
|
|
15
15
|
import { writeTreeToFilesystem } from "@better-fullstack/template-generator/fs-writer";
|
|
16
|
-
import { allowedApisForFrontends, getCompatibleAddons, getCompatibleCSSFrameworks, getCompatibleUILibraries, hasWebStyling, isExampleAIAllowed, isExampleChatSdkAllowed, isFrontendAllowedWithBackend, isWebFrontend, requiresChatSdkVercelAIForSelection, splitFrontends, validateAddonCompatibility } from "@better-fullstack/types";
|
|
16
|
+
import { allowedApisForFrontends, getCompatibleAddons, getCompatibleCSSFrameworks, getCompatibleUILibraries, getLocalWebDevPort, hasWebStyling, isExampleAIAllowed, isExampleChatSdkAllowed, isFrontendAllowedWithBackend, isWebFrontend, requiresChatSdkVercelAIForSelection, splitFrontends, validateAddonCompatibility } from "@better-fullstack/types";
|
|
17
17
|
import consola, { consola as consola$1 } from "consola";
|
|
18
18
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
19
19
|
import { ConfirmPrompt, GroupMultiSelectPrompt, MultiSelectPrompt, SelectPrompt, isCancel as isCancel$1 } from "@clack/core";
|
|
@@ -791,61 +791,6 @@ function validateApiFrontendCompatibility(api, frontends = [], astroIntegration)
|
|
|
791
791
|
function isFrontendAllowedWithBackend$1(frontend, backend, auth) {
|
|
792
792
|
return isFrontendAllowedWithBackend(frontend, backend, auth);
|
|
793
793
|
}
|
|
794
|
-
function validateClerkCompatibility(auth, backend, frontends = []) {
|
|
795
|
-
if (auth !== "clerk") return;
|
|
796
|
-
if (backend === "convex") {
|
|
797
|
-
const incompatibleFrontends = frontends.filter((f) => [
|
|
798
|
-
"nuxt",
|
|
799
|
-
"svelte",
|
|
800
|
-
"solid",
|
|
801
|
-
"solid-start"
|
|
802
|
-
].includes(f));
|
|
803
|
-
if (incompatibleFrontends.length > 0) exitWithError(`In Better-Fullstack, Clerk + Convex is not compatible with the following frontends: ${incompatibleFrontends.join(", ")}. Please choose a different frontend or auth provider.`);
|
|
804
|
-
return;
|
|
805
|
-
}
|
|
806
|
-
if (backend === "self") {
|
|
807
|
-
if (frontends.some((f) => [
|
|
808
|
-
"native-bare",
|
|
809
|
-
"native-uniwind",
|
|
810
|
-
"native-unistyles"
|
|
811
|
-
].includes(f))) exitWithError("In Better-Fullstack, Clerk with the 'self' backend is currently supported only for web-only Next.js or TanStack Start projects (no native companion app). Please remove the native frontend or choose a different auth provider.");
|
|
812
|
-
const hasNextJs = frontends.includes("next");
|
|
813
|
-
const hasTanStackStart = frontends.includes("tanstack-start");
|
|
814
|
-
if (!hasNextJs && !hasTanStackStart) {
|
|
815
|
-
if (frontends.includes("astro")) exitWithError("In Better-Fullstack, Clerk is not yet supported for Astro fullstack projects. Please use '--frontend next' or '--frontend tanstack-start' with '--backend self', or choose a different auth provider.");
|
|
816
|
-
if (frontends.includes("nuxt")) exitWithError("In Better-Fullstack, Clerk is not yet supported for Nuxt fullstack projects. Please use '--frontend next' or '--frontend tanstack-start' with '--backend self', or choose a different auth provider.");
|
|
817
|
-
if (frontends.includes("svelte")) exitWithError("In Better-Fullstack, Clerk is not yet supported for SvelteKit fullstack projects. Please use '--frontend next' or '--frontend tanstack-start' with '--backend self', or choose a different auth provider.");
|
|
818
|
-
if (frontends.includes("solid-start")) exitWithError("In Better-Fullstack, Clerk is not yet supported for SolidStart fullstack projects. Please use '--frontend next' or '--frontend tanstack-start' with '--backend self', or choose a different auth provider.");
|
|
819
|
-
exitWithError("In Better-Fullstack, Clerk with the 'self' backend currently requires the Next.js or TanStack Start frontend. Please use '--frontend next' or '--frontend tanstack-start', or choose a different auth provider.");
|
|
820
|
-
}
|
|
821
|
-
return;
|
|
822
|
-
}
|
|
823
|
-
exitWithError("In Better-Fullstack, Clerk authentication is currently supported with the Convex backend, or with the 'self' backend when using Next.js or TanStack Start. Please choose a supported backend/frontend combination or a different auth provider.");
|
|
824
|
-
}
|
|
825
|
-
function validateNextAuthCompatibility(auth, backend, frontends = []) {
|
|
826
|
-
if (auth !== "nextauth") return;
|
|
827
|
-
const hasNextJs = frontends.includes("next");
|
|
828
|
-
if (backend !== "self") exitWithError("In Better-Fullstack, Auth.js (NextAuth) is currently supported only with the 'self' backend (fullstack Next.js). Please use '--backend self' or choose a different auth provider.");
|
|
829
|
-
if (!hasNextJs) exitWithError("In Better-Fullstack, Auth.js (NextAuth) currently requires the Next.js frontend. Please use '--frontend next' or choose a different auth provider.");
|
|
830
|
-
}
|
|
831
|
-
function validateStackAuthCompatibility(auth, backend, frontends = []) {
|
|
832
|
-
if (auth !== "stack-auth") return;
|
|
833
|
-
const hasNextJs = frontends.includes("next");
|
|
834
|
-
if (backend !== "self") exitWithError("In Better-Fullstack, Stack Auth is currently supported only with the 'self' backend (fullstack Next.js). Please use '--backend self' or choose a different auth provider.");
|
|
835
|
-
if (!hasNextJs) exitWithError("In Better-Fullstack, Stack Auth currently requires the Next.js frontend. Please use '--frontend next' or choose a different auth provider.");
|
|
836
|
-
}
|
|
837
|
-
function validateSupabaseAuthCompatibility(auth, backend, frontends = []) {
|
|
838
|
-
if (auth !== "supabase-auth") return;
|
|
839
|
-
const hasNextJs = frontends.includes("next");
|
|
840
|
-
if (backend !== "self") exitWithError("In Better-Fullstack, Supabase Auth is currently supported only with the 'self' backend (fullstack Next.js). Please use '--backend self' or choose a different auth provider.");
|
|
841
|
-
if (!hasNextJs) exitWithError("In Better-Fullstack, Supabase Auth currently requires the Next.js frontend. Please use '--frontend next' or choose a different auth provider.");
|
|
842
|
-
}
|
|
843
|
-
function validateAuth0Compatibility(auth, backend, frontends = []) {
|
|
844
|
-
if (auth !== "auth0") return;
|
|
845
|
-
const hasNextJs = frontends.includes("next");
|
|
846
|
-
if (backend !== "self") exitWithError("In Better-Fullstack, Auth0 is currently supported only with the 'self' backend (fullstack Next.js). Please use '--backend self' or choose a different auth provider.");
|
|
847
|
-
if (!hasNextJs) exitWithError("In Better-Fullstack, Auth0 currently requires the Next.js frontend. Please use '--frontend next' or choose a different auth provider.");
|
|
848
|
-
}
|
|
849
794
|
function allowedApisForFrontends$1(frontends = [], astroIntegration) {
|
|
850
795
|
return allowedApisForFrontends(frontends, astroIntegration);
|
|
851
796
|
}
|
|
@@ -2411,12 +2356,11 @@ async function setupTauri(config) {
|
|
|
2411
2356
|
if (!await fs.pathExists(clientPackageDir)) return;
|
|
2412
2357
|
try {
|
|
2413
2358
|
s.start("Setting up Tauri desktop app support...");
|
|
2414
|
-
const hasReactRouter = frontend.includes("react-router");
|
|
2415
2359
|
const hasNuxt = frontend.includes("nuxt");
|
|
2416
2360
|
const hasSvelte = frontend.includes("svelte");
|
|
2417
2361
|
const hasNext = frontend.includes("next");
|
|
2418
|
-
const devUrl =
|
|
2419
|
-
const frontendDist = hasNuxt ? "../.output/public" : hasSvelte ? "../build" : hasNext ? "../.next" :
|
|
2362
|
+
const devUrl = `http://localhost:${getLocalWebDevPort(frontend)}`;
|
|
2363
|
+
const frontendDist = hasNuxt ? "../.output/public" : hasSvelte ? "../build" : hasNext ? "../.next" : frontend.includes("react-router") ? "../build/client" : "../dist";
|
|
2420
2364
|
const tauriArgs = [
|
|
2421
2365
|
"@tauri-apps/cli@latest",
|
|
2422
2366
|
"init",
|
|
@@ -3205,103 +3149,36 @@ async function getAstroIntegrationChoice(astroIntegration) {
|
|
|
3205
3149
|
|
|
3206
3150
|
//#endregion
|
|
3207
3151
|
//#region src/prompts/auth.ts
|
|
3208
|
-
async function getAuthChoice(auth, backend, frontend) {
|
|
3152
|
+
async function getAuthChoice(auth, backend, frontend, ecosystem = "typescript") {
|
|
3209
3153
|
if (auth !== void 0) return auth;
|
|
3210
|
-
|
|
3211
|
-
|
|
3212
|
-
|
|
3213
|
-
|
|
3214
|
-
|
|
3215
|
-
|
|
3216
|
-
|
|
3217
|
-
|
|
3218
|
-
|
|
3219
|
-
|
|
3220
|
-
|
|
3221
|
-
|
|
3222
|
-
|
|
3223
|
-
|
|
3224
|
-
"next",
|
|
3225
|
-
"native-bare",
|
|
3226
|
-
"native-uniwind",
|
|
3227
|
-
"native-unistyles"
|
|
3228
|
-
].includes(f));
|
|
3229
|
-
const options$1 = [];
|
|
3230
|
-
if (supportedBetterAuthFrontends) options$1.push({
|
|
3231
|
-
value: "better-auth",
|
|
3232
|
-
label: "Better-Auth",
|
|
3233
|
-
hint: "comprehensive auth framework for TypeScript"
|
|
3234
|
-
});
|
|
3235
|
-
if (hasClerkCompatibleFrontends) options$1.push({
|
|
3236
|
-
value: "clerk",
|
|
3237
|
-
label: "Clerk",
|
|
3238
|
-
hint: "More than auth, Complete User Management"
|
|
3239
|
-
});
|
|
3240
|
-
if (options$1.length === 0) return "none";
|
|
3241
|
-
options$1.push({
|
|
3242
|
-
value: "none",
|
|
3243
|
-
label: "None",
|
|
3244
|
-
hint: "No auth"
|
|
3245
|
-
});
|
|
3246
|
-
const response$1 = await navigableSelect({
|
|
3247
|
-
message: "Select authentication provider",
|
|
3248
|
-
options: options$1,
|
|
3249
|
-
initialValue: "none"
|
|
3250
|
-
});
|
|
3251
|
-
if (isCancel$1(response$1)) return exitCancelled("Operation cancelled");
|
|
3252
|
-
return response$1;
|
|
3253
|
-
}
|
|
3254
|
-
const hasNextJs = frontend?.includes("next");
|
|
3255
|
-
const hasTanStackStart = frontend?.includes("tanstack-start");
|
|
3256
|
-
const isSelfBackend = backend === "self";
|
|
3257
|
-
const supportsNextJsAuth = hasNextJs && isSelfBackend;
|
|
3258
|
-
const hasNativeFrontend$2 = frontend?.some((f) => [
|
|
3259
|
-
"native-bare",
|
|
3260
|
-
"native-uniwind",
|
|
3261
|
-
"native-unistyles"
|
|
3262
|
-
].includes(f));
|
|
3263
|
-
const supportsClerkSelf = isSelfBackend && !hasNativeFrontend$2 && Boolean(hasNextJs || hasTanStackStart);
|
|
3264
|
-
const options = [{
|
|
3265
|
-
value: "better-auth",
|
|
3266
|
-
label: "Better-Auth",
|
|
3267
|
-
hint: "comprehensive auth framework for TypeScript"
|
|
3268
|
-
}];
|
|
3269
|
-
if (supportsClerkSelf) options.push({
|
|
3270
|
-
value: "clerk",
|
|
3271
|
-
label: "Clerk",
|
|
3272
|
-
hint: "More than auth, Complete User Management"
|
|
3154
|
+
const authOptionOrder = [
|
|
3155
|
+
{ value: "better-auth" },
|
|
3156
|
+
{ value: "go-better-auth" },
|
|
3157
|
+
{ value: "clerk" },
|
|
3158
|
+
{ value: "nextauth" },
|
|
3159
|
+
{ value: "stack-auth" },
|
|
3160
|
+
{ value: "supabase-auth" },
|
|
3161
|
+
{ value: "auth0" },
|
|
3162
|
+
{ value: "none" }
|
|
3163
|
+
];
|
|
3164
|
+
const supportedOptions = (0, types_exports.getSupportedCapabilityOptions)("auth", {
|
|
3165
|
+
ecosystem,
|
|
3166
|
+
backend,
|
|
3167
|
+
frontend
|
|
3273
3168
|
});
|
|
3274
|
-
|
|
3275
|
-
|
|
3276
|
-
|
|
3277
|
-
label: "Auth.js (NextAuth)",
|
|
3278
|
-
hint: "Authentication for Next.js (formerly NextAuth.js)"
|
|
3279
|
-
});
|
|
3280
|
-
options.push({
|
|
3281
|
-
value: "stack-auth",
|
|
3282
|
-
label: "Stack Auth",
|
|
3283
|
-
hint: "Open-source Auth0/Clerk alternative"
|
|
3284
|
-
});
|
|
3285
|
-
options.push({
|
|
3286
|
-
value: "supabase-auth",
|
|
3287
|
-
label: "Supabase Auth",
|
|
3288
|
-
hint: "Auth with Supabase platform integration"
|
|
3289
|
-
});
|
|
3290
|
-
options.push({
|
|
3291
|
-
value: "auth0",
|
|
3292
|
-
label: "Auth0",
|
|
3293
|
-
hint: "Flexible identity platform for authentication"
|
|
3294
|
-
});
|
|
3295
|
-
}
|
|
3296
|
-
options.push({
|
|
3297
|
-
value: "none",
|
|
3298
|
-
label: "None",
|
|
3299
|
-
hint: "No authentication"
|
|
3169
|
+
const options = authOptionOrder.flatMap(({ value }) => {
|
|
3170
|
+
const option = supportedOptions.find((candidate) => candidate.id === value);
|
|
3171
|
+
return option ? [option] : [];
|
|
3300
3172
|
});
|
|
3173
|
+
if (options.length === 1 && options[0]?.id === "none") return "none";
|
|
3301
3174
|
const response = await navigableSelect({
|
|
3302
3175
|
message: "Select authentication provider",
|
|
3303
|
-
options
|
|
3304
|
-
|
|
3176
|
+
options: options.map((option) => ({
|
|
3177
|
+
value: option.id,
|
|
3178
|
+
label: option.label,
|
|
3179
|
+
hint: option.promptHint
|
|
3180
|
+
})),
|
|
3181
|
+
initialValue: options.some((option) => option.id === DEFAULT_CONFIG.auth) ? DEFAULT_CONFIG.auth : options.find((option) => option.id !== "none")?.id ?? "none"
|
|
3305
3182
|
});
|
|
3306
3183
|
if (isCancel$1(response)) return exitCancelled("Operation cancelled");
|
|
3307
3184
|
return response;
|
|
@@ -3976,8 +3853,8 @@ async function getFrontendChoice(frontendOptions, backend, auth) {
|
|
|
3976
3853
|
},
|
|
3977
3854
|
{
|
|
3978
3855
|
value: "svelte",
|
|
3979
|
-
label: "
|
|
3980
|
-
hint: "
|
|
3856
|
+
label: "SvelteKit",
|
|
3857
|
+
hint: "Full-stack Svelte framework with SSR and server routes"
|
|
3981
3858
|
},
|
|
3982
3859
|
{
|
|
3983
3860
|
value: "solid",
|
|
@@ -4627,6 +4504,11 @@ async function getPythonAiChoice(pythonAi) {
|
|
|
4627
4504
|
const response = await navigableMultiselect({
|
|
4628
4505
|
message: "Select Python AI/ML frameworks",
|
|
4629
4506
|
options: [
|
|
4507
|
+
{
|
|
4508
|
+
value: "none",
|
|
4509
|
+
label: "None",
|
|
4510
|
+
hint: "No AI/ML framework"
|
|
4511
|
+
},
|
|
4630
4512
|
{
|
|
4631
4513
|
value: "langchain",
|
|
4632
4514
|
label: "LangChain",
|
|
@@ -4662,6 +4544,7 @@ async function getPythonAiChoice(pythonAi) {
|
|
|
4662
4544
|
initialValues: []
|
|
4663
4545
|
});
|
|
4664
4546
|
if (isCancel$1(response)) return exitCancelled("Operation cancelled");
|
|
4547
|
+
if (response.includes("none")) return [];
|
|
4665
4548
|
return response;
|
|
4666
4549
|
}
|
|
4667
4550
|
async function getPythonTaskQueueChoice(pythonTaskQueue) {
|
|
@@ -5708,8 +5591,9 @@ async function gatherConfig(flags, projectName, projectDir, relativePath) {
|
|
|
5708
5591
|
return getApiChoice(flags.api, results.frontend, results.backend, results.astroIntegration);
|
|
5709
5592
|
},
|
|
5710
5593
|
auth: ({ results }) => {
|
|
5711
|
-
if (results.ecosystem
|
|
5712
|
-
return getAuthChoice(flags.auth,
|
|
5594
|
+
if (results.ecosystem === "typescript") return getAuthChoice(flags.auth, results.backend, results.frontend, "typescript");
|
|
5595
|
+
if (results.ecosystem === "go") return getAuthChoice(flags.auth, void 0, void 0, "go");
|
|
5596
|
+
return Promise.resolve("none");
|
|
5713
5597
|
},
|
|
5714
5598
|
payments: ({ results }) => {
|
|
5715
5599
|
if (results.ecosystem !== "typescript") return Promise.resolve("none");
|
|
@@ -6734,6 +6618,18 @@ function validateDatabaseSetup(config, providedFlags) {
|
|
|
6734
6618
|
}
|
|
6735
6619
|
}
|
|
6736
6620
|
}
|
|
6621
|
+
function validateEcosystemAuthCompatibility(config, providedFlags) {
|
|
6622
|
+
const auth = config.auth;
|
|
6623
|
+
if (!auth || auth === "none") return;
|
|
6624
|
+
const normalized = (0, types_exports.normalizeCapabilitySelection)("auth", {
|
|
6625
|
+
ecosystem: config.ecosystem,
|
|
6626
|
+
backend: config.backend,
|
|
6627
|
+
frontend: config.frontend
|
|
6628
|
+
}, auth);
|
|
6629
|
+
if (!normalized.normalized || normalized.value === auth) return;
|
|
6630
|
+
config.auth = normalized.value;
|
|
6631
|
+
if (providedFlags?.has("auth") && normalized.reason && !isSilent()) consola.warn(pc.yellow(`Unsupported auth selection '${auth}' for the current stack: ${normalized.reason}. Falling back to '--auth ${normalized.value}'.`));
|
|
6632
|
+
}
|
|
6737
6633
|
function validateConvexConstraints(config, providedFlags) {
|
|
6738
6634
|
const { backend } = config;
|
|
6739
6635
|
if (backend !== "convex") return;
|
|
@@ -6786,30 +6682,6 @@ function validateConvexConstraints(config, providedFlags) {
|
|
|
6786
6682
|
},
|
|
6787
6683
|
suggestions: ["Remove --server-deploy flag", "Set --server-deploy none"]
|
|
6788
6684
|
});
|
|
6789
|
-
if (has("auth") && config.auth === "better-auth") {
|
|
6790
|
-
const supportedFrontends = [
|
|
6791
|
-
"tanstack-router",
|
|
6792
|
-
"tanstack-start",
|
|
6793
|
-
"next",
|
|
6794
|
-
"native-bare",
|
|
6795
|
-
"native-uniwind",
|
|
6796
|
-
"native-unistyles"
|
|
6797
|
-
];
|
|
6798
|
-
if (!config.frontend?.some((f) => supportedFrontends.includes(f))) incompatibilityError({
|
|
6799
|
-
message: "Better-Auth with Convex requires specific frontends.",
|
|
6800
|
-
provided: {
|
|
6801
|
-
backend: "convex",
|
|
6802
|
-
auth: "better-auth",
|
|
6803
|
-
frontend: config.frontend || []
|
|
6804
|
-
},
|
|
6805
|
-
suggestions: [
|
|
6806
|
-
"Use --frontend tanstack-router",
|
|
6807
|
-
"Use --frontend tanstack-start",
|
|
6808
|
-
"Use --frontend next",
|
|
6809
|
-
"Use a native frontend"
|
|
6810
|
-
]
|
|
6811
|
-
});
|
|
6812
|
-
}
|
|
6813
6685
|
}
|
|
6814
6686
|
function validateBackendNoneConstraints(config, providedFlags) {
|
|
6815
6687
|
const { backend } = config;
|
|
@@ -6819,7 +6691,6 @@ function validateBackendNoneConstraints(config, providedFlags) {
|
|
|
6819
6691
|
if (has("database") && config.database !== "none") exitWithError("Backend 'none' requires '--database none'. Please remove the --database flag or set it to 'none'.");
|
|
6820
6692
|
if (has("orm") && config.orm !== "none") exitWithError("Backend 'none' requires '--orm none'. Please remove the --orm flag or set it to 'none'.");
|
|
6821
6693
|
if (has("api") && config.api !== "none") exitWithError("Backend 'none' requires '--api none'. Please remove the --api flag or set it to 'none'.");
|
|
6822
|
-
if (has("auth") && config.auth !== "none") exitWithError("Backend 'none' requires '--auth none'. Please remove the --auth flag or set it to 'none'.");
|
|
6823
6694
|
if (has("payments") && config.payments !== "none") exitWithError("Backend 'none' requires '--payments none'. Please remove the --payments flag or set it to 'none'.");
|
|
6824
6695
|
if (has("dbSetup") && config.dbSetup !== "none") exitWithError("Backend 'none' requires '--db-setup none'. Please remove the --db-setup flag or set it to 'none'.");
|
|
6825
6696
|
if (has("serverDeploy") && config.serverDeploy !== "none") exitWithError("Backend 'none' requires '--server-deploy none'. Please remove the --server-deploy flag or set it to 'none'.");
|
|
@@ -6888,6 +6759,7 @@ function validateShadcnConstraints(config, providedFlags) {
|
|
|
6888
6759
|
});
|
|
6889
6760
|
}
|
|
6890
6761
|
function validateFullConfig(config, providedFlags, options) {
|
|
6762
|
+
validateEcosystemAuthCompatibility(config, providedFlags);
|
|
6891
6763
|
validateDatabaseOrmAuth(config, providedFlags);
|
|
6892
6764
|
validateDatabaseSetup(config, providedFlags);
|
|
6893
6765
|
validateConvexConstraints(config, providedFlags);
|
|
@@ -6909,11 +6781,6 @@ function validateFullConfig(config, providedFlags, options) {
|
|
|
6909
6781
|
}
|
|
6910
6782
|
validateExamplesCompatibility(config.examples ?? [], config.backend, config.frontend ?? [], config.runtime, config.ai);
|
|
6911
6783
|
validatePaymentsCompatibility(config.payments, config.auth, config.backend, config.frontend ?? []);
|
|
6912
|
-
validateClerkCompatibility(config.auth, config.backend, config.frontend ?? []);
|
|
6913
|
-
validateNextAuthCompatibility(config.auth, config.backend, config.frontend ?? []);
|
|
6914
|
-
validateStackAuthCompatibility(config.auth, config.backend, config.frontend ?? []);
|
|
6915
|
-
validateSupabaseAuthCompatibility(config.auth, config.backend, config.frontend ?? []);
|
|
6916
|
-
validateAuth0Compatibility(config.auth, config.backend, config.frontend ?? []);
|
|
6917
6784
|
validateUILibraryFrontendCompatibility(config.uiLibrary, config.frontend ?? [], config.astroIntegration);
|
|
6918
6785
|
validateUILibraryCSSFrameworkCompatibility(config.uiLibrary, config.cssFramework);
|
|
6919
6786
|
validateShadcnConstraints(config, providedFlags);
|
|
@@ -6921,15 +6788,11 @@ function validateFullConfig(config, providedFlags, options) {
|
|
|
6921
6788
|
}
|
|
6922
6789
|
function validateConfigForProgrammaticUse(config) {
|
|
6923
6790
|
try {
|
|
6791
|
+
validateEcosystemAuthCompatibility(config);
|
|
6924
6792
|
validateDatabaseOrmAuth(config);
|
|
6925
6793
|
if (config.frontend && config.frontend.length > 0) ensureSingleWebAndNative(config.frontend);
|
|
6926
6794
|
validateApiFrontendCompatibility(config.api, config.frontend, config.astroIntegration);
|
|
6927
6795
|
validatePaymentsCompatibility(config.payments, config.auth, config.backend, config.frontend);
|
|
6928
|
-
validateClerkCompatibility(config.auth, config.backend, config.frontend ?? []);
|
|
6929
|
-
validateNextAuthCompatibility(config.auth, config.backend, config.frontend ?? []);
|
|
6930
|
-
validateStackAuthCompatibility(config.auth, config.backend, config.frontend ?? []);
|
|
6931
|
-
validateSupabaseAuthCompatibility(config.auth, config.backend, config.frontend ?? []);
|
|
6932
|
-
validateAuth0Compatibility(config.auth, config.backend, config.frontend ?? []);
|
|
6933
6796
|
if (config.addons && config.addons.length > 0) validateAddonsAgainstFrontends(config.addons, config.frontend, config.auth);
|
|
6934
6797
|
validateExamplesCompatibility(config.examples ?? [], config.backend, config.frontend ?? [], config.runtime, config.ai);
|
|
6935
6798
|
validateUILibraryFrontendCompatibility(config.uiLibrary, config.frontend ?? [], config.astroIntegration);
|
|
@@ -7037,6 +6900,8 @@ async function formatCode(filePath, content) {
|
|
|
7037
6900
|
}
|
|
7038
6901
|
async function formatProject(projectDir) {
|
|
7039
6902
|
async function formatDirectory(dir) {
|
|
6903
|
+
const denoConfigPath = path.join(dir, "deno.json");
|
|
6904
|
+
if (await fs.pathExists(denoConfigPath)) return;
|
|
7040
6905
|
const entries = await fs.readdir(dir, { withFileTypes: true });
|
|
7041
6906
|
await Promise.all(entries.map(async (entry) => {
|
|
7042
6907
|
const fullPath = path.join(dir, entry.name);
|
|
@@ -8260,13 +8125,13 @@ async function displayPostInstallInstructions(config) {
|
|
|
8260
8125
|
const hasNative = frontend?.includes("native-bare") || frontend?.includes("native-uniwind") || frontend?.includes("native-unistyles");
|
|
8261
8126
|
const bunWebNativeWarning = packageManager === "bun" && hasNative && hasWeb ? getBunWebNativeWarning() : "";
|
|
8262
8127
|
const noOrmWarning = !isConvex && database !== "none" && orm === "none" ? getNoOrmWarning() : "";
|
|
8263
|
-
const
|
|
8264
|
-
const
|
|
8265
|
-
const webPort = hasReactRouter || hasSvelte ? "5173" : "3001";
|
|
8128
|
+
const hasFresh = frontend?.includes("fresh");
|
|
8129
|
+
const webPort = String(getLocalWebDevPort(frontend ?? []));
|
|
8266
8130
|
const betterAuthConvexInstructions = isConvex && config.auth === "better-auth" ? getBetterAuthConvexInstructions(hasWeb ?? false, webPort, packageManager) : "";
|
|
8267
8131
|
let output = `${pc.bold("Next steps")}\n${pc.cyan("1.")} ${cdCmd}\n`;
|
|
8268
8132
|
let stepCounter = 2;
|
|
8269
8133
|
if (!depsInstalled) output += `${pc.cyan(`${stepCounter++}.`)} ${packageManager} install\n`;
|
|
8134
|
+
if (hasFresh) output += `${pc.yellow("NOTE:")} Fresh projects require ${pc.white("deno")} on your PATH\n`;
|
|
8270
8135
|
if (database === "sqlite" && dbSetup !== "d1") output += `${pc.cyan(`${stepCounter++}.`)} ${runCmd} db:local\n${pc.dim(" (optional - starts local SQLite database)")}\n`;
|
|
8271
8136
|
if (isConvex) {
|
|
8272
8137
|
output += `${pc.cyan(`${stepCounter++}.`)} ${runCmd} dev:setup\n${pc.dim(" (this will guide you through Convex project setup)")}\n`;
|
|
@@ -8908,7 +8773,7 @@ const router = os.router({
|
|
|
8908
8773
|
yes: z.boolean().optional().default(false).describe("Use default configuration"),
|
|
8909
8774
|
yolo: z.boolean().optional().default(false).describe("(WARNING - NOT RECOMMENDED) Bypass validations and compatibility checks"),
|
|
8910
8775
|
verbose: z.boolean().optional().default(false).describe("Show detailed result information"),
|
|
8911
|
-
ecosystem: types_exports.EcosystemSchema.optional().describe("Language ecosystem (typescript, rust, or
|
|
8776
|
+
ecosystem: types_exports.EcosystemSchema.optional().describe("Language ecosystem (typescript, rust, python, or go)"),
|
|
8912
8777
|
database: types_exports.DatabaseSchema.optional(),
|
|
8913
8778
|
orm: types_exports.ORMSchema.optional(),
|
|
8914
8779
|
auth: types_exports.AuthSchema.optional(),
|
|
@@ -8926,6 +8791,7 @@ const router = os.router({
|
|
|
8926
8791
|
animation: types_exports.AnimationSchema.optional(),
|
|
8927
8792
|
logging: types_exports.LoggingSchema.optional(),
|
|
8928
8793
|
observability: types_exports.ObservabilitySchema.optional(),
|
|
8794
|
+
featureFlags: types_exports.FeatureFlagsSchema.optional().describe("Feature flags provider"),
|
|
8929
8795
|
analytics: types_exports.AnalyticsSchema.optional().describe("Privacy-focused analytics"),
|
|
8930
8796
|
cms: types_exports.CMSSchema.optional().describe("Headless CMS solution"),
|
|
8931
8797
|
caching: types_exports.CachingSchema.optional().describe("Caching solution"),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-better-fullstack",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.8",
|
|
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.4.
|
|
80
|
-
"@better-fullstack/types": "^1.4.
|
|
79
|
+
"@better-fullstack/template-generator": "^1.4.8",
|
|
80
|
+
"@better-fullstack/types": "^1.4.8",
|
|
81
81
|
"@clack/core": "^0.5.0",
|
|
82
82
|
"@clack/prompts": "^1.0.0-alpha.8",
|
|
83
83
|
"@orpc/server": "^1.13.0",
|