create-better-fullstack 1.4.5 → 1.4.7
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-CISBB09-.mjs} +54 -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-CISBB09-.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",
|
|
@@ -5708,8 +5585,9 @@ async function gatherConfig(flags, projectName, projectDir, relativePath) {
|
|
|
5708
5585
|
return getApiChoice(flags.api, results.frontend, results.backend, results.astroIntegration);
|
|
5709
5586
|
},
|
|
5710
5587
|
auth: ({ results }) => {
|
|
5711
|
-
if (results.ecosystem
|
|
5712
|
-
return getAuthChoice(flags.auth,
|
|
5588
|
+
if (results.ecosystem === "typescript") return getAuthChoice(flags.auth, results.backend, results.frontend, "typescript");
|
|
5589
|
+
if (results.ecosystem === "go") return getAuthChoice(flags.auth, void 0, void 0, "go");
|
|
5590
|
+
return Promise.resolve("none");
|
|
5713
5591
|
},
|
|
5714
5592
|
payments: ({ results }) => {
|
|
5715
5593
|
if (results.ecosystem !== "typescript") return Promise.resolve("none");
|
|
@@ -6734,6 +6612,18 @@ function validateDatabaseSetup(config, providedFlags) {
|
|
|
6734
6612
|
}
|
|
6735
6613
|
}
|
|
6736
6614
|
}
|
|
6615
|
+
function validateEcosystemAuthCompatibility(config, providedFlags) {
|
|
6616
|
+
const auth = config.auth;
|
|
6617
|
+
if (!auth || auth === "none") return;
|
|
6618
|
+
const normalized = (0, types_exports.normalizeCapabilitySelection)("auth", {
|
|
6619
|
+
ecosystem: config.ecosystem,
|
|
6620
|
+
backend: config.backend,
|
|
6621
|
+
frontend: config.frontend
|
|
6622
|
+
}, auth);
|
|
6623
|
+
if (!normalized.normalized || normalized.value === auth) return;
|
|
6624
|
+
config.auth = normalized.value;
|
|
6625
|
+
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}'.`));
|
|
6626
|
+
}
|
|
6737
6627
|
function validateConvexConstraints(config, providedFlags) {
|
|
6738
6628
|
const { backend } = config;
|
|
6739
6629
|
if (backend !== "convex") return;
|
|
@@ -6786,30 +6676,6 @@ function validateConvexConstraints(config, providedFlags) {
|
|
|
6786
6676
|
},
|
|
6787
6677
|
suggestions: ["Remove --server-deploy flag", "Set --server-deploy none"]
|
|
6788
6678
|
});
|
|
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
6679
|
}
|
|
6814
6680
|
function validateBackendNoneConstraints(config, providedFlags) {
|
|
6815
6681
|
const { backend } = config;
|
|
@@ -6819,7 +6685,6 @@ function validateBackendNoneConstraints(config, providedFlags) {
|
|
|
6819
6685
|
if (has("database") && config.database !== "none") exitWithError("Backend 'none' requires '--database none'. Please remove the --database flag or set it to 'none'.");
|
|
6820
6686
|
if (has("orm") && config.orm !== "none") exitWithError("Backend 'none' requires '--orm none'. Please remove the --orm flag or set it to 'none'.");
|
|
6821
6687
|
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
6688
|
if (has("payments") && config.payments !== "none") exitWithError("Backend 'none' requires '--payments none'. Please remove the --payments flag or set it to 'none'.");
|
|
6824
6689
|
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
6690
|
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 +6753,7 @@ function validateShadcnConstraints(config, providedFlags) {
|
|
|
6888
6753
|
});
|
|
6889
6754
|
}
|
|
6890
6755
|
function validateFullConfig(config, providedFlags, options) {
|
|
6756
|
+
validateEcosystemAuthCompatibility(config, providedFlags);
|
|
6891
6757
|
validateDatabaseOrmAuth(config, providedFlags);
|
|
6892
6758
|
validateDatabaseSetup(config, providedFlags);
|
|
6893
6759
|
validateConvexConstraints(config, providedFlags);
|
|
@@ -6909,11 +6775,6 @@ function validateFullConfig(config, providedFlags, options) {
|
|
|
6909
6775
|
}
|
|
6910
6776
|
validateExamplesCompatibility(config.examples ?? [], config.backend, config.frontend ?? [], config.runtime, config.ai);
|
|
6911
6777
|
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
6778
|
validateUILibraryFrontendCompatibility(config.uiLibrary, config.frontend ?? [], config.astroIntegration);
|
|
6918
6779
|
validateUILibraryCSSFrameworkCompatibility(config.uiLibrary, config.cssFramework);
|
|
6919
6780
|
validateShadcnConstraints(config, providedFlags);
|
|
@@ -6921,15 +6782,11 @@ function validateFullConfig(config, providedFlags, options) {
|
|
|
6921
6782
|
}
|
|
6922
6783
|
function validateConfigForProgrammaticUse(config) {
|
|
6923
6784
|
try {
|
|
6785
|
+
validateEcosystemAuthCompatibility(config);
|
|
6924
6786
|
validateDatabaseOrmAuth(config);
|
|
6925
6787
|
if (config.frontend && config.frontend.length > 0) ensureSingleWebAndNative(config.frontend);
|
|
6926
6788
|
validateApiFrontendCompatibility(config.api, config.frontend, config.astroIntegration);
|
|
6927
6789
|
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
6790
|
if (config.addons && config.addons.length > 0) validateAddonsAgainstFrontends(config.addons, config.frontend, config.auth);
|
|
6934
6791
|
validateExamplesCompatibility(config.examples ?? [], config.backend, config.frontend ?? [], config.runtime, config.ai);
|
|
6935
6792
|
validateUILibraryFrontendCompatibility(config.uiLibrary, config.frontend ?? [], config.astroIntegration);
|
|
@@ -7037,6 +6894,8 @@ async function formatCode(filePath, content) {
|
|
|
7037
6894
|
}
|
|
7038
6895
|
async function formatProject(projectDir) {
|
|
7039
6896
|
async function formatDirectory(dir) {
|
|
6897
|
+
const denoConfigPath = path.join(dir, "deno.json");
|
|
6898
|
+
if (await fs.pathExists(denoConfigPath)) return;
|
|
7040
6899
|
const entries = await fs.readdir(dir, { withFileTypes: true });
|
|
7041
6900
|
await Promise.all(entries.map(async (entry) => {
|
|
7042
6901
|
const fullPath = path.join(dir, entry.name);
|
|
@@ -8260,13 +8119,13 @@ async function displayPostInstallInstructions(config) {
|
|
|
8260
8119
|
const hasNative = frontend?.includes("native-bare") || frontend?.includes("native-uniwind") || frontend?.includes("native-unistyles");
|
|
8261
8120
|
const bunWebNativeWarning = packageManager === "bun" && hasNative && hasWeb ? getBunWebNativeWarning() : "";
|
|
8262
8121
|
const noOrmWarning = !isConvex && database !== "none" && orm === "none" ? getNoOrmWarning() : "";
|
|
8263
|
-
const
|
|
8264
|
-
const
|
|
8265
|
-
const webPort = hasReactRouter || hasSvelte ? "5173" : "3001";
|
|
8122
|
+
const hasFresh = frontend?.includes("fresh");
|
|
8123
|
+
const webPort = String(getLocalWebDevPort(frontend ?? []));
|
|
8266
8124
|
const betterAuthConvexInstructions = isConvex && config.auth === "better-auth" ? getBetterAuthConvexInstructions(hasWeb ?? false, webPort, packageManager) : "";
|
|
8267
8125
|
let output = `${pc.bold("Next steps")}\n${pc.cyan("1.")} ${cdCmd}\n`;
|
|
8268
8126
|
let stepCounter = 2;
|
|
8269
8127
|
if (!depsInstalled) output += `${pc.cyan(`${stepCounter++}.`)} ${packageManager} install\n`;
|
|
8128
|
+
if (hasFresh) output += `${pc.yellow("NOTE:")} Fresh projects require ${pc.white("deno")} on your PATH\n`;
|
|
8270
8129
|
if (database === "sqlite" && dbSetup !== "d1") output += `${pc.cyan(`${stepCounter++}.`)} ${runCmd} db:local\n${pc.dim(" (optional - starts local SQLite database)")}\n`;
|
|
8271
8130
|
if (isConvex) {
|
|
8272
8131
|
output += `${pc.cyan(`${stepCounter++}.`)} ${runCmd} dev:setup\n${pc.dim(" (this will guide you through Convex project setup)")}\n`;
|
|
@@ -8908,7 +8767,7 @@ const router = os.router({
|
|
|
8908
8767
|
yes: z.boolean().optional().default(false).describe("Use default configuration"),
|
|
8909
8768
|
yolo: z.boolean().optional().default(false).describe("(WARNING - NOT RECOMMENDED) Bypass validations and compatibility checks"),
|
|
8910
8769
|
verbose: z.boolean().optional().default(false).describe("Show detailed result information"),
|
|
8911
|
-
ecosystem: types_exports.EcosystemSchema.optional().describe("Language ecosystem (typescript, rust, or
|
|
8770
|
+
ecosystem: types_exports.EcosystemSchema.optional().describe("Language ecosystem (typescript, rust, python, or go)"),
|
|
8912
8771
|
database: types_exports.DatabaseSchema.optional(),
|
|
8913
8772
|
orm: types_exports.ORMSchema.optional(),
|
|
8914
8773
|
auth: types_exports.AuthSchema.optional(),
|
|
@@ -8926,6 +8785,7 @@ const router = os.router({
|
|
|
8926
8785
|
animation: types_exports.AnimationSchema.optional(),
|
|
8927
8786
|
logging: types_exports.LoggingSchema.optional(),
|
|
8928
8787
|
observability: types_exports.ObservabilitySchema.optional(),
|
|
8788
|
+
featureFlags: types_exports.FeatureFlagsSchema.optional().describe("Feature flags provider"),
|
|
8929
8789
|
analytics: types_exports.AnalyticsSchema.optional().describe("Privacy-focused analytics"),
|
|
8930
8790
|
cms: types_exports.CMSSchema.optional().describe("Headless CMS solution"),
|
|
8931
8791
|
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.7",
|
|
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.7",
|
|
80
|
+
"@better-fullstack/types": "^1.4.7",
|
|
81
81
|
"@clack/core": "^0.5.0",
|
|
82
82
|
"@clack/prompts": "^1.0.0-alpha.8",
|
|
83
83
|
"@orpc/server": "^1.13.0",
|