mirror of
https://github.com/FranP-code/create-better-t-stack.git
synced 2025-10-12 23:52:15 +00:00
add express, automated mongodb atlas setup, fix stack architech
This commit is contained in:
@@ -74,32 +74,45 @@ const StackArchitect = () => {
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (stack.database === "none" && stack.orm !== "none") {
|
||||
setStack((prev) => ({ ...prev, orm: "none" }));
|
||||
}
|
||||
|
||||
if (stack.database !== "postgres" || stack.orm !== "prisma") {
|
||||
if (stack.prismaPostgres === "true") {
|
||||
setStack((prev) => ({ ...prev, prismaPostgres: "false" }));
|
||||
if (stack.database === "none") {
|
||||
if (stack.orm !== "none") {
|
||||
setStack((prev) => ({ ...prev, orm: "none" }));
|
||||
}
|
||||
if (stack.auth === "true") {
|
||||
setStack((prev) => ({ ...prev, auth: "false" }));
|
||||
}
|
||||
if (stack.dbSetup !== "none") {
|
||||
setStack((prev) => ({ ...prev, dbSetup: "none" }));
|
||||
}
|
||||
}
|
||||
|
||||
if (stack.database !== "sqlite" || stack.orm === "prisma") {
|
||||
if (stack.turso === "true") {
|
||||
setStack((prev) => ({ ...prev, turso: "false" }));
|
||||
}
|
||||
if (stack.database === "mongodb" && stack.orm === "drizzle") {
|
||||
setStack((prev) => ({ ...prev, orm: "prisma" }));
|
||||
}
|
||||
|
||||
if (stack.database === "none" && stack.auth === "true") {
|
||||
setStack((prev) => ({ ...prev, auth: "false" }));
|
||||
if (stack.dbSetup === "turso") {
|
||||
if (stack.database !== "sqlite") {
|
||||
setStack((prev) => ({ ...prev, database: "sqlite" }));
|
||||
}
|
||||
if (stack.orm === "prisma") {
|
||||
setStack((prev) => ({ ...prev, orm: "drizzle" }));
|
||||
}
|
||||
} else if (stack.dbSetup === "prisma-postgres") {
|
||||
if (stack.database !== "postgres") {
|
||||
setStack((prev) => ({ ...prev, database: "postgres" }));
|
||||
}
|
||||
if (stack.orm !== "prisma") {
|
||||
setStack((prev) => ({ ...prev, orm: "prisma" }));
|
||||
}
|
||||
} else if (stack.dbSetup === "mongodb-atlas") {
|
||||
if (stack.database !== "mongodb") {
|
||||
setStack((prev) => ({ ...prev, database: "mongodb" }));
|
||||
}
|
||||
if (stack.orm !== "prisma") {
|
||||
setStack((prev) => ({ ...prev, orm: "prisma" }));
|
||||
}
|
||||
}
|
||||
}, [
|
||||
stack.database,
|
||||
stack.orm,
|
||||
stack.prismaPostgres,
|
||||
stack.turso,
|
||||
stack.auth,
|
||||
]);
|
||||
}, [stack.database, stack.orm, stack.dbSetup, stack.auth]);
|
||||
|
||||
useEffect(() => {
|
||||
const cmd = generateCommand(stack);
|
||||
@@ -113,6 +126,33 @@ const StackArchitect = () => {
|
||||
|
||||
notes.frontend = [];
|
||||
|
||||
notes.dbSetup = [];
|
||||
if (stack.database === "none") {
|
||||
notes.dbSetup.push("Database setup requires a database.");
|
||||
} else {
|
||||
if (stack.dbSetup === "turso") {
|
||||
if (stack.database !== "sqlite") {
|
||||
notes.dbSetup.push("Turso setup requires SQLite database.");
|
||||
}
|
||||
if (stack.orm === "prisma") {
|
||||
notes.dbSetup.push("Turso is not compatible with Prisma ORM.");
|
||||
}
|
||||
} else if (stack.dbSetup === "prisma-postgres") {
|
||||
if (stack.database !== "postgres") {
|
||||
notes.dbSetup.push(
|
||||
"Prisma PostgreSQL setup requires PostgreSQL database.",
|
||||
);
|
||||
}
|
||||
if (stack.orm !== "prisma") {
|
||||
notes.dbSetup.push("Prisma PostgreSQL setup requires Prisma ORM.");
|
||||
}
|
||||
} else if (stack.dbSetup === "mongodb-atlas") {
|
||||
if (stack.database !== "mongodb") {
|
||||
notes.dbSetup.push("MongoDB Atlas setup requires MongoDB database.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
notes.addons = [];
|
||||
if (!hasWebFrontend) {
|
||||
notes.addons.push("PWA and Tauri are only available with React Web.");
|
||||
@@ -125,6 +165,8 @@ const StackArchitect = () => {
|
||||
notes.orm.push(
|
||||
"ORM options are only available when a database is selected.",
|
||||
);
|
||||
} else if (stack.database === "mongodb" && stack.orm === "drizzle") {
|
||||
notes.orm.push("MongoDB is only available with Prisma ORM.");
|
||||
}
|
||||
|
||||
notes.auth = [];
|
||||
@@ -132,23 +174,6 @@ const StackArchitect = () => {
|
||||
notes.auth.push("Authentication requires a database.");
|
||||
}
|
||||
|
||||
notes.turso = [];
|
||||
if (stack.database !== "sqlite") {
|
||||
notes.turso.push(
|
||||
"Turso integration is only available with SQLite database.",
|
||||
);
|
||||
}
|
||||
if (stack.orm === "prisma") {
|
||||
notes.turso.push("Turso is not compatible with Prisma ORM.");
|
||||
}
|
||||
|
||||
notes.prismaPostgres = [];
|
||||
if (stack.database !== "postgres" || stack.orm !== "prisma") {
|
||||
notes.prismaPostgres.push(
|
||||
"Prisma PostgreSQL setup requires PostgreSQL database with Prisma ORM.",
|
||||
);
|
||||
}
|
||||
|
||||
notes.examples = [];
|
||||
if (!hasWebFrontend) {
|
||||
notes.examples.push(
|
||||
@@ -198,12 +223,8 @@ const StackArchitect = () => {
|
||||
flags.push("--no-auth");
|
||||
}
|
||||
|
||||
if (stackState.turso === "true") {
|
||||
flags.push("--turso");
|
||||
}
|
||||
|
||||
if (stackState.prismaPostgres === "true") {
|
||||
flags.push("--prisma-postgres");
|
||||
if (stackState.dbSetup !== "none") {
|
||||
flags.push(`--db-setup ${stackState.dbSetup}`);
|
||||
}
|
||||
|
||||
if (stackState.backendFramework !== "hono") {
|
||||
@@ -263,7 +284,6 @@ const StackArchitect = () => {
|
||||
if (currentSelection.length === 1) {
|
||||
return prev;
|
||||
}
|
||||
|
||||
return {
|
||||
...prev,
|
||||
frontend: currentSelection.filter((id) => id !== techId),
|
||||
@@ -296,6 +316,10 @@ const StackArchitect = () => {
|
||||
prev.frontend.includes("react-router") ||
|
||||
prev.frontend.includes("tanstack-start");
|
||||
|
||||
const hasPWACompatibleFrontend =
|
||||
prev.frontend.includes("tanstack-router") ||
|
||||
prev.frontend.includes("react-router");
|
||||
|
||||
if (index >= 0) {
|
||||
currentArray.splice(index, 1);
|
||||
} else {
|
||||
@@ -318,8 +342,7 @@ const StackArchitect = () => {
|
||||
if (
|
||||
category === "addons" &&
|
||||
(techId === "pwa" || techId === "tauri") &&
|
||||
!prev.frontend.includes("tanstack-router") &&
|
||||
!prev.frontend.includes("react-router")
|
||||
!hasPWACompatibleFrontend
|
||||
) {
|
||||
return prev;
|
||||
}
|
||||
@@ -342,45 +365,40 @@ const StackArchitect = () => {
|
||||
}
|
||||
|
||||
if (category === "database") {
|
||||
let updatedState = { ...prev, database: techId };
|
||||
|
||||
if (techId === "none") {
|
||||
return {
|
||||
...prev,
|
||||
database: techId,
|
||||
updatedState = {
|
||||
...updatedState,
|
||||
orm: "none",
|
||||
turso: "false",
|
||||
prismaPostgres: "false",
|
||||
dbSetup: "none",
|
||||
auth: "false",
|
||||
};
|
||||
}
|
||||
} else if (prev.database === "none") {
|
||||
updatedState.orm = techId === "mongodb" ? "prisma" : "drizzle";
|
||||
updatedState.dbSetup = "none";
|
||||
|
||||
if (prev.database === "none") {
|
||||
return {
|
||||
...prev,
|
||||
database: techId,
|
||||
orm: "drizzle",
|
||||
turso: techId === "sqlite" ? prev.turso : "false",
|
||||
prismaPostgres:
|
||||
techId === "postgres" && prev.orm === "prisma"
|
||||
? prev.prismaPostgres
|
||||
: "false",
|
||||
auth:
|
||||
hasWebFrontend(prev.frontend) ||
|
||||
prev.frontend.includes("native")
|
||||
? "true"
|
||||
: "false",
|
||||
};
|
||||
}
|
||||
|
||||
const updatedState = {
|
||||
...prev,
|
||||
database: techId,
|
||||
};
|
||||
|
||||
if (techId === "sqlite") {
|
||||
updatedState.prismaPostgres = "false";
|
||||
} else if (techId === "postgres" && prev.orm === "prisma") {
|
||||
const hasCompatibleFrontend =
|
||||
prev.frontend.length > 0 && !prev.frontend.includes("none");
|
||||
if (hasCompatibleFrontend) {
|
||||
updatedState.auth = "true";
|
||||
}
|
||||
} else {
|
||||
updatedState.turso = "false";
|
||||
if (techId === "mongodb" && updatedState.orm === "drizzle") {
|
||||
updatedState.orm = "prisma";
|
||||
}
|
||||
|
||||
if (updatedState.dbSetup !== "none") {
|
||||
if (
|
||||
(updatedState.dbSetup === "turso" && techId !== "sqlite") ||
|
||||
(updatedState.dbSetup === "prisma-postgres" &&
|
||||
techId !== "postgres") ||
|
||||
(updatedState.dbSetup === "mongodb-atlas" &&
|
||||
techId !== "mongodb")
|
||||
) {
|
||||
updatedState.dbSetup = "none";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return updatedState;
|
||||
@@ -396,31 +414,41 @@ const StackArchitect = () => {
|
||||
orm: techId,
|
||||
};
|
||||
|
||||
if (techId === "prisma") {
|
||||
updatedState.turso = "false";
|
||||
if (prev.database === "postgres") {
|
||||
} else {
|
||||
updatedState.prismaPostgres = "false";
|
||||
if (updatedState.dbSetup !== "none") {
|
||||
if (
|
||||
(updatedState.dbSetup === "turso" && techId === "prisma") ||
|
||||
(updatedState.dbSetup === "prisma-postgres" &&
|
||||
techId !== "prisma")
|
||||
) {
|
||||
updatedState.dbSetup = "none";
|
||||
}
|
||||
} else if (techId === "drizzle" || techId === "none") {
|
||||
updatedState.prismaPostgres = "false";
|
||||
}
|
||||
|
||||
return updatedState;
|
||||
}
|
||||
|
||||
if (
|
||||
category === "turso" &&
|
||||
(prev.database !== "sqlite" || prev.orm === "prisma")
|
||||
) {
|
||||
return prev;
|
||||
}
|
||||
if (category === "dbSetup") {
|
||||
if (prev.database === "none" && techId !== "none") {
|
||||
return prev;
|
||||
}
|
||||
|
||||
if (
|
||||
category === "prismaPostgres" &&
|
||||
(prev.database !== "postgres" || prev.orm !== "prisma")
|
||||
) {
|
||||
return prev;
|
||||
const updatedState = {
|
||||
...prev,
|
||||
dbSetup: techId,
|
||||
};
|
||||
|
||||
if (techId === "turso") {
|
||||
updatedState.database = "sqlite";
|
||||
updatedState.orm = "drizzle";
|
||||
} else if (techId === "prisma-postgres") {
|
||||
updatedState.database = "postgres";
|
||||
updatedState.orm = "prisma";
|
||||
} else if (techId === "mongodb-atlas") {
|
||||
updatedState.database = "mongodb";
|
||||
updatedState.orm = "prisma";
|
||||
}
|
||||
|
||||
return updatedState;
|
||||
}
|
||||
|
||||
if (
|
||||
@@ -440,15 +468,6 @@ const StackArchitect = () => {
|
||||
[],
|
||||
);
|
||||
|
||||
const hasWebFrontend = useCallback((frontendOptions: string[]) => {
|
||||
return (
|
||||
frontendOptions.includes("tanstack-router") ||
|
||||
frontendOptions.includes("react-router") ||
|
||||
frontendOptions.includes("tanstack-start") ||
|
||||
frontendOptions.includes("native")
|
||||
);
|
||||
}, []);
|
||||
|
||||
const copyToClipboard = useCallback(() => {
|
||||
navigator.clipboard.writeText(command);
|
||||
setCopied(true);
|
||||
@@ -698,12 +717,16 @@ const StackArchitect = () => {
|
||||
|
||||
const isDisabled =
|
||||
(activeTab === "orm" && stack.database === "none") ||
|
||||
(activeTab === "turso" &&
|
||||
(stack.database !== "sqlite" ||
|
||||
stack.orm === "prisma")) ||
|
||||
(activeTab === "prismaPostgres" &&
|
||||
(stack.database !== "postgres" ||
|
||||
stack.orm !== "prisma")) ||
|
||||
(activeTab === "dbSetup" &&
|
||||
((tech.id !== "none" && stack.database === "none") ||
|
||||
(tech.id === "turso" &&
|
||||
(stack.database !== "sqlite" ||
|
||||
stack.orm === "prisma")) ||
|
||||
(tech.id === "prisma-postgres" &&
|
||||
(stack.database !== "postgres" ||
|
||||
stack.orm !== "prisma")) ||
|
||||
(tech.id === "mongodb-atlas" &&
|
||||
stack.database !== "mongodb"))) ||
|
||||
(activeTab === "examples" &&
|
||||
(((tech.id === "todo" || tech.id === "ai") &&
|
||||
!hasWebFrontendSelected) ||
|
||||
@@ -866,7 +889,7 @@ const StackArchitect = () => {
|
||||
}
|
||||
</span>
|
||||
|
||||
{stack.orm && stack.database !== "none" && (
|
||||
{stack.orm !== "none" && stack.database !== "none" && (
|
||||
<span className="inline-flex items-center rounded border border-cyan-300 bg-cyan-100 px-1.5 py-0.5 text-cyan-800 text-xs dark:border-cyan-700/30 dark:bg-cyan-900/30 dark:text-cyan-300">
|
||||
{TECH_OPTIONS.orm.find((t) => t.id === stack.orm)?.icon}{" "}
|
||||
{TECH_OPTIONS.orm.find((t) => t.id === stack.orm)?.name}
|
||||
@@ -882,37 +905,18 @@ const StackArchitect = () => {
|
||||
</span>
|
||||
)}
|
||||
|
||||
{stack.turso === "true" &&
|
||||
stack.database === "sqlite" &&
|
||||
stack.orm !== "prisma" && (
|
||||
<span className="inline-flex items-center rounded border border-pink-300 bg-pink-100 px-1.5 py-0.5 text-pink-800 text-xs dark:border-pink-700/30 dark:bg-pink-900/30 dark:text-pink-300">
|
||||
{
|
||||
TECH_OPTIONS.turso.find((t) => t.id === stack.turso)
|
||||
?.icon
|
||||
}{" "}
|
||||
{
|
||||
TECH_OPTIONS.turso.find((t) => t.id === stack.turso)
|
||||
?.name
|
||||
}
|
||||
</span>
|
||||
)}
|
||||
|
||||
{stack.prismaPostgres === "true" &&
|
||||
stack.database === "postgres" &&
|
||||
stack.orm === "prisma" && (
|
||||
<span className="inline-flex items-center rounded border border-indigo-300 bg-indigo-100 px-1.5 py-0.5 text-indigo-800 text-xs dark:border-indigo-700/30 dark:bg-indigo-900/30 dark:text-indigo-300">
|
||||
{
|
||||
TECH_OPTIONS.prismaPostgres.find(
|
||||
(t) => t.id === stack.prismaPostgres,
|
||||
)?.icon
|
||||
}{" "}
|
||||
{
|
||||
TECH_OPTIONS.prismaPostgres.find(
|
||||
(t) => t.id === stack.prismaPostgres,
|
||||
)?.name
|
||||
}
|
||||
</span>
|
||||
)}
|
||||
{stack.dbSetup !== "none" && (
|
||||
<span className="inline-flex items-center rounded border border-pink-300 bg-pink-100 px-1.5 py-0.5 text-pink-800 text-xs dark:border-pink-700/30 dark:bg-pink-900/30 dark:text-pink-300">
|
||||
{
|
||||
TECH_OPTIONS.dbSetup.find((t) => t.id === stack.dbSetup)
|
||||
?.icon
|
||||
}{" "}
|
||||
{
|
||||
TECH_OPTIONS.dbSetup.find((t) => t.id === stack.dbSetup)
|
||||
?.name
|
||||
}
|
||||
</span>
|
||||
)}
|
||||
|
||||
{stack.addons.map((addonId) => {
|
||||
const addon = TECH_OPTIONS.addons.find(
|
||||
|
||||
@@ -74,6 +74,13 @@ export const TECH_OPTIONS = {
|
||||
icon: "🦊",
|
||||
color: "from-purple-500 to-purple-700",
|
||||
},
|
||||
{
|
||||
id: "express",
|
||||
name: "Express",
|
||||
description: "Popular Node.js framework",
|
||||
icon: "🚂",
|
||||
color: "from-gray-500 to-gray-700",
|
||||
},
|
||||
],
|
||||
database: [
|
||||
{
|
||||
@@ -91,6 +98,13 @@ export const TECH_OPTIONS = {
|
||||
icon: "🐘",
|
||||
color: "from-indigo-400 to-indigo-600",
|
||||
},
|
||||
{
|
||||
id: "mongodb",
|
||||
name: "MongoDB",
|
||||
description: "NoSQL document database",
|
||||
icon: "🍃",
|
||||
color: "from-green-400 to-green-600",
|
||||
},
|
||||
{
|
||||
id: "none",
|
||||
name: "No Database",
|
||||
@@ -115,6 +129,44 @@ export const TECH_OPTIONS = {
|
||||
icon: "◮",
|
||||
color: "from-purple-400 to-purple-600",
|
||||
},
|
||||
{
|
||||
id: "none",
|
||||
name: "No ORM",
|
||||
description: "Skip ORM integration",
|
||||
icon: "🚫",
|
||||
color: "from-gray-400 to-gray-600",
|
||||
},
|
||||
],
|
||||
dbSetup: [
|
||||
{
|
||||
id: "turso",
|
||||
name: "Turso",
|
||||
description: "SQLite cloud database powered by libSQL",
|
||||
icon: "☁️",
|
||||
color: "from-pink-400 to-pink-600",
|
||||
},
|
||||
{
|
||||
id: "prisma-postgres",
|
||||
name: "Prisma PostgreSQL",
|
||||
description: "Set up PostgreSQL with Prisma",
|
||||
icon: "🐘",
|
||||
color: "from-indigo-400 to-indigo-600",
|
||||
},
|
||||
{
|
||||
id: "mongodb-atlas",
|
||||
name: "MongoDB Atlas",
|
||||
description: "Cloud MongoDB setup with Atlas",
|
||||
icon: "🌩️",
|
||||
color: "from-green-400 to-green-600",
|
||||
},
|
||||
{
|
||||
id: "none",
|
||||
name: "Basic Setup",
|
||||
description: "No cloud DB integration",
|
||||
icon: "💻",
|
||||
color: "from-gray-400 to-gray-600",
|
||||
default: true,
|
||||
},
|
||||
],
|
||||
auth: [
|
||||
{
|
||||
@@ -133,42 +185,6 @@ export const TECH_OPTIONS = {
|
||||
color: "from-red-400 to-red-600",
|
||||
},
|
||||
],
|
||||
turso: [
|
||||
{
|
||||
id: "true",
|
||||
name: "Turso",
|
||||
description: "SQLite cloud database",
|
||||
icon: "☁️",
|
||||
color: "from-pink-400 to-pink-600",
|
||||
default: false,
|
||||
},
|
||||
{
|
||||
id: "false",
|
||||
name: "No Turso",
|
||||
description: "Skip Turso integration",
|
||||
icon: "🚫",
|
||||
color: "from-gray-400 to-gray-600",
|
||||
default: true,
|
||||
},
|
||||
],
|
||||
prismaPostgres: [
|
||||
{
|
||||
id: "true",
|
||||
name: "Prisma PostgreSQL",
|
||||
description: "Set up PostgreSQL with Prisma",
|
||||
icon: "🐘",
|
||||
color: "from-indigo-400 to-indigo-600",
|
||||
default: false,
|
||||
},
|
||||
{
|
||||
id: "false",
|
||||
name: "Skip Prisma PostgreSQL",
|
||||
description: "Basic Prisma setup",
|
||||
icon: "🚫",
|
||||
color: "from-gray-400 to-gray-600",
|
||||
default: true,
|
||||
},
|
||||
],
|
||||
packageManager: [
|
||||
{
|
||||
id: "npm",
|
||||
@@ -293,9 +309,8 @@ export const PRESET_TEMPLATES = [
|
||||
backendFramework: "hono",
|
||||
database: "sqlite",
|
||||
orm: "drizzle",
|
||||
dbSetup: "none",
|
||||
auth: "true",
|
||||
turso: "false",
|
||||
prismaPostgres: "false",
|
||||
packageManager: "bun",
|
||||
addons: [],
|
||||
examples: [],
|
||||
@@ -314,9 +329,8 @@ export const PRESET_TEMPLATES = [
|
||||
backendFramework: "hono",
|
||||
database: "sqlite",
|
||||
orm: "drizzle",
|
||||
dbSetup: "none",
|
||||
auth: "true",
|
||||
turso: "false",
|
||||
prismaPostgres: "false",
|
||||
packageManager: "bun",
|
||||
addons: [],
|
||||
examples: [],
|
||||
@@ -335,9 +349,8 @@ export const PRESET_TEMPLATES = [
|
||||
backendFramework: "hono",
|
||||
database: "postgres",
|
||||
orm: "drizzle",
|
||||
dbSetup: "none",
|
||||
auth: "false",
|
||||
turso: "false",
|
||||
prismaPostgres: "false",
|
||||
packageManager: "bun",
|
||||
addons: [],
|
||||
examples: [],
|
||||
@@ -356,9 +369,8 @@ export const PRESET_TEMPLATES = [
|
||||
backendFramework: "hono",
|
||||
database: "sqlite",
|
||||
orm: "drizzle",
|
||||
dbSetup: "turso",
|
||||
auth: "true",
|
||||
turso: "true",
|
||||
prismaPostgres: "false",
|
||||
packageManager: "bun",
|
||||
addons: ["pwa", "biome", "husky", "tauri"],
|
||||
examples: ["todo", "ai"],
|
||||
@@ -374,10 +386,9 @@ export type StackState = {
|
||||
runtime: string;
|
||||
backendFramework: string;
|
||||
database: string;
|
||||
orm: string | null;
|
||||
orm: string;
|
||||
dbSetup: string;
|
||||
auth: string;
|
||||
turso: string;
|
||||
prismaPostgres: string;
|
||||
packageManager: string;
|
||||
addons: string[];
|
||||
examples: string[];
|
||||
@@ -392,9 +403,8 @@ export const DEFAULT_STACK: StackState = {
|
||||
backendFramework: "hono",
|
||||
database: "sqlite",
|
||||
orm: "drizzle",
|
||||
dbSetup: "none",
|
||||
auth: "true",
|
||||
turso: "false",
|
||||
prismaPostgres: "false",
|
||||
packageManager: "bun",
|
||||
addons: [],
|
||||
examples: [],
|
||||
|
||||
Reference in New Issue
Block a user