mirror of
https://github.com/FranP-code/create-better-t-stack.git
synced 2025-10-12 23:52:15 +00:00
fix mongodb templates and add migrate and generate scripts
This commit is contained in:
5
.changeset/slow-melons-shine.md
Normal file
5
.changeset/slow-melons-shine.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"create-better-t-stack": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
add migrate and generate scripts
|
||||||
@@ -58,8 +58,8 @@ async function updateRootPackageJson(
|
|||||||
const needsDbScripts =
|
const needsDbScripts =
|
||||||
options.backend !== "convex" &&
|
options.backend !== "convex" &&
|
||||||
options.database !== "none" &&
|
options.database !== "none" &&
|
||||||
options.orm !== "none";
|
options.orm !== "none" &&
|
||||||
|
options.orm !== "mongoose";
|
||||||
if (options.addons.includes("turborepo")) {
|
if (options.addons.includes("turborepo")) {
|
||||||
scripts.dev = "turbo dev";
|
scripts.dev = "turbo dev";
|
||||||
scripts.build = "turbo build";
|
scripts.build = "turbo build";
|
||||||
@@ -73,6 +73,13 @@ async function updateRootPackageJson(
|
|||||||
if (needsDbScripts) {
|
if (needsDbScripts) {
|
||||||
scripts["db:push"] = `turbo -F ${backendPackageName} db:push`;
|
scripts["db:push"] = `turbo -F ${backendPackageName} db:push`;
|
||||||
scripts["db:studio"] = `turbo -F ${backendPackageName} db:studio`;
|
scripts["db:studio"] = `turbo -F ${backendPackageName} db:studio`;
|
||||||
|
if (options.orm === "prisma") {
|
||||||
|
scripts["db:generate"] = `turbo -F ${backendPackageName} db:generate`;
|
||||||
|
scripts["db:migrate"] = `turbo -F ${backendPackageName} db:migrate`;
|
||||||
|
} else if (options.orm === "drizzle") {
|
||||||
|
scripts["db:generate"] = `turbo -F ${backendPackageName} db:generate`;
|
||||||
|
scripts["db:migrate"] = `turbo -F ${backendPackageName} db:migrate`;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (options.packageManager === "pnpm") {
|
} else if (options.packageManager === "pnpm") {
|
||||||
scripts.dev = devScript;
|
scripts.dev = devScript;
|
||||||
@@ -87,6 +94,17 @@ async function updateRootPackageJson(
|
|||||||
if (needsDbScripts) {
|
if (needsDbScripts) {
|
||||||
scripts["db:push"] = `pnpm --filter ${backendPackageName} db:push`;
|
scripts["db:push"] = `pnpm --filter ${backendPackageName} db:push`;
|
||||||
scripts["db:studio"] = `pnpm --filter ${backendPackageName} db:studio`;
|
scripts["db:studio"] = `pnpm --filter ${backendPackageName} db:studio`;
|
||||||
|
if (options.orm === "prisma") {
|
||||||
|
scripts["db:generate"] =
|
||||||
|
`pnpm --filter ${backendPackageName} db:generate`;
|
||||||
|
scripts["db:migrate"] =
|
||||||
|
`pnpm --filter ${backendPackageName} db:migrate`;
|
||||||
|
} else if (options.orm === "drizzle") {
|
||||||
|
scripts["db:generate"] =
|
||||||
|
`pnpm --filter ${backendPackageName} db:generate`;
|
||||||
|
scripts["db:migrate"] =
|
||||||
|
`pnpm --filter ${backendPackageName} db:migrate`;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (options.packageManager === "npm") {
|
} else if (options.packageManager === "npm") {
|
||||||
scripts.dev = devScript;
|
scripts.dev = devScript;
|
||||||
@@ -102,6 +120,17 @@ async function updateRootPackageJson(
|
|||||||
scripts["db:push"] = `npm run db:push --workspace ${backendPackageName}`;
|
scripts["db:push"] = `npm run db:push --workspace ${backendPackageName}`;
|
||||||
scripts["db:studio"] =
|
scripts["db:studio"] =
|
||||||
`npm run db:studio --workspace ${backendPackageName}`;
|
`npm run db:studio --workspace ${backendPackageName}`;
|
||||||
|
if (options.orm === "prisma") {
|
||||||
|
scripts["db:generate"] =
|
||||||
|
`npm run db:generate --workspace ${backendPackageName}`;
|
||||||
|
scripts["db:migrate"] =
|
||||||
|
`npm run db:migrate --workspace ${backendPackageName}`;
|
||||||
|
} else if (options.orm === "drizzle") {
|
||||||
|
scripts["db:generate"] =
|
||||||
|
`npm run db:generate --workspace ${backendPackageName}`;
|
||||||
|
scripts["db:migrate"] =
|
||||||
|
`npm run db:migrate --workspace ${backendPackageName}`;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (options.packageManager === "bun") {
|
} else if (options.packageManager === "bun") {
|
||||||
scripts.dev = devScript;
|
scripts.dev = devScript;
|
||||||
@@ -116,6 +145,17 @@ async function updateRootPackageJson(
|
|||||||
if (needsDbScripts) {
|
if (needsDbScripts) {
|
||||||
scripts["db:push"] = `bun run --filter ${backendPackageName} db:push`;
|
scripts["db:push"] = `bun run --filter ${backendPackageName} db:push`;
|
||||||
scripts["db:studio"] = `bun run --filter ${backendPackageName} db:studio`;
|
scripts["db:studio"] = `bun run --filter ${backendPackageName} db:studio`;
|
||||||
|
if (options.orm === "prisma") {
|
||||||
|
scripts["db:generate"] =
|
||||||
|
`bun run --filter ${backendPackageName} db:generate`;
|
||||||
|
scripts["db:migrate"] =
|
||||||
|
`bun run --filter ${backendPackageName} db:migrate`;
|
||||||
|
} else if (options.orm === "drizzle") {
|
||||||
|
scripts["db:generate"] =
|
||||||
|
`bun run --filter ${backendPackageName} db:generate`;
|
||||||
|
scripts["db:migrate"] =
|
||||||
|
`bun run --filter ${backendPackageName} db:migrate`;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -192,9 +232,13 @@ async function updateServerPackageJson(
|
|||||||
if (options.orm === "prisma") {
|
if (options.orm === "prisma") {
|
||||||
scripts["db:push"] = "prisma db push --schema ./prisma/schema";
|
scripts["db:push"] = "prisma db push --schema ./prisma/schema";
|
||||||
scripts["db:studio"] = "prisma studio";
|
scripts["db:studio"] = "prisma studio";
|
||||||
|
scripts["db:generate"] = "prisma generate --schema ./prisma/schema";
|
||||||
|
scripts["db:migrate"] = "prisma migrate dev";
|
||||||
} else if (options.orm === "drizzle") {
|
} else if (options.orm === "drizzle") {
|
||||||
scripts["db:push"] = "drizzle-kit push";
|
scripts["db:push"] = "drizzle-kit push";
|
||||||
scripts["db:studio"] = "drizzle-kit studio";
|
scripts["db:studio"] = "drizzle-kit studio";
|
||||||
|
scripts["db:generate"] = "drizzle-kit generate";
|
||||||
|
scripts["db:migrate"] = "drizzle-kit migrate";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -371,7 +371,7 @@ export async function setupAuthTemplate(
|
|||||||
authDbSrc = path.join(
|
authDbSrc = path.join(
|
||||||
PKG_ROOT,
|
PKG_ROOT,
|
||||||
`templates/auth/server/db/mongoose/${db}`,
|
`templates/auth/server/db/mongoose/${db}`,
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
if (authDbSrc && (await fs.pathExists(authDbSrc))) {
|
if (authDbSrc && (await fs.pathExists(authDbSrc))) {
|
||||||
await processAndCopyFiles("**/*", authDbSrc, serverAppDir, context);
|
await processAndCopyFiles("**/*", authDbSrc, serverAppDir, context);
|
||||||
|
|||||||
@@ -446,82 +446,86 @@ function processAndValidateFlags(
|
|||||||
config.dbSetup = "none";
|
config.dbSetup = "none";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (effectiveDatabase === "mongodb" && effectiveOrm === "drizzle") {
|
if (config.orm === "mongoose" && !providedFlags.has("database")) {
|
||||||
consola.fatal(
|
config.database = "mongodb";
|
||||||
"Drizzle ORM is not compatible with MongoDB. Please use --orm prisma or --orm mongoose.",
|
}
|
||||||
);
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
if (effectiveDatabase === "mongodb" && effectiveOrm === "drizzle") {
|
||||||
effectiveOrm === "mongoose" &&
|
|
||||||
effectiveDatabase &&
|
|
||||||
effectiveDatabase !== "mongodb"
|
|
||||||
) {
|
|
||||||
consola.fatal(
|
|
||||||
`Mongoose ORM requires MongoDB. Cannot use --orm mongoose with --database ${effectiveDatabase}.`,
|
|
||||||
);
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (config.dbSetup && config.dbSetup !== "none") {
|
|
||||||
const dbSetup = config.dbSetup;
|
|
||||||
|
|
||||||
if (!effectiveDatabase || effectiveDatabase === "none") {
|
|
||||||
consola.fatal(
|
consola.fatal(
|
||||||
`Database setup '--db-setup ${dbSetup}' requires a database. Cannot use when database is 'none'.`,
|
"Drizzle ORM is not compatible with MongoDB. Please use --orm prisma or --orm mongoose.",
|
||||||
);
|
);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dbSetup === "turso") {
|
if (
|
||||||
if (effectiveDatabase && effectiveDatabase !== "sqlite") {
|
effectiveOrm === "mongoose" &&
|
||||||
|
effectiveDatabase &&
|
||||||
|
effectiveDatabase !== "mongodb"
|
||||||
|
) {
|
||||||
|
consola.fatal(
|
||||||
|
`Mongoose ORM requires MongoDB. Cannot use --orm mongoose with --database ${effectiveDatabase}.`,
|
||||||
|
);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config.dbSetup && config.dbSetup !== "none") {
|
||||||
|
const dbSetup = config.dbSetup;
|
||||||
|
|
||||||
|
if (!effectiveDatabase || effectiveDatabase === "none") {
|
||||||
consola.fatal(
|
consola.fatal(
|
||||||
`Turso setup requires SQLite. Cannot use --db-setup turso with --database ${effectiveDatabase}`,
|
`Database setup '--db-setup ${dbSetup}' requires a database. Cannot use when database is 'none'.`,
|
||||||
);
|
);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
if (effectiveOrm !== "drizzle") {
|
|
||||||
consola.fatal(
|
if (dbSetup === "turso") {
|
||||||
`Turso setup requires Drizzle ORM. Cannot use --db-setup turso with --orm ${effectiveOrm ?? "none"}.`,
|
if (effectiveDatabase && effectiveDatabase !== "sqlite") {
|
||||||
);
|
consola.fatal(
|
||||||
process.exit(1);
|
`Turso setup requires SQLite. Cannot use --db-setup turso with --database ${effectiveDatabase}`,
|
||||||
}
|
);
|
||||||
} else if (dbSetup === "prisma-postgres") {
|
process.exit(1);
|
||||||
if (effectiveDatabase !== "postgres") {
|
}
|
||||||
consola.fatal(
|
if (effectiveOrm !== "drizzle") {
|
||||||
`Prisma PostgreSQL setup requires PostgreSQL. Cannot use --db-setup prisma-postgres with --database ${effectiveDatabase}.`,
|
consola.fatal(
|
||||||
);
|
`Turso setup requires Drizzle ORM. Cannot use --db-setup turso with --orm ${effectiveOrm ?? "none"}.`,
|
||||||
process.exit(1);
|
);
|
||||||
}
|
process.exit(1);
|
||||||
if (effectiveOrm !== "prisma") {
|
}
|
||||||
consola.fatal(
|
} else if (dbSetup === "prisma-postgres") {
|
||||||
`Prisma PostgreSQL setup requires Prisma ORM. Cannot use --db-setup prisma-postgres with --orm ${effectiveOrm}.`,
|
if (effectiveDatabase !== "postgres") {
|
||||||
);
|
consola.fatal(
|
||||||
process.exit(1);
|
`Prisma PostgreSQL setup requires PostgreSQL. Cannot use --db-setup prisma-postgres with --database ${effectiveDatabase}.`,
|
||||||
}
|
);
|
||||||
} else if (dbSetup === "mongodb-atlas") {
|
process.exit(1);
|
||||||
if (effectiveDatabase !== "mongodb") {
|
}
|
||||||
consola.fatal(
|
if (effectiveOrm !== "prisma") {
|
||||||
`MongoDB Atlas setup requires MongoDB. Cannot use --db-setup mongodb-atlas with --database ${effectiveDatabase}.`,
|
consola.fatal(
|
||||||
);
|
`Prisma PostgreSQL setup requires Prisma ORM. Cannot use --db-setup prisma-postgres with --orm ${effectiveOrm}.`,
|
||||||
process.exit(1);
|
);
|
||||||
}
|
process.exit(1);
|
||||||
if (effectiveOrm !== "prisma" && effectiveOrm !== "mongoose") {
|
}
|
||||||
consola.fatal(
|
} else if (dbSetup === "mongodb-atlas") {
|
||||||
`MongoDB Atlas setup requires Prisma or Mongoose ORM. Cannot use --db-setup mongodb-atlas with --orm ${effectiveOrm}.`,
|
if (effectiveDatabase !== "mongodb") {
|
||||||
);
|
consola.fatal(
|
||||||
process.exit(1);
|
`MongoDB Atlas setup requires MongoDB. Cannot use --db-setup mongodb-atlas with --database ${effectiveDatabase}.`,
|
||||||
}
|
);
|
||||||
} else if (dbSetup === "neon") {
|
process.exit(1);
|
||||||
if (effectiveDatabase !== "postgres") {
|
}
|
||||||
consola.fatal(
|
if (effectiveOrm !== "prisma" && effectiveOrm !== "mongoose") {
|
||||||
`Neon PostgreSQL setup requires PostgreSQL. Cannot use --db-setup neon with --database ${effectiveDatabase}.`,
|
consola.fatal(
|
||||||
);
|
`MongoDB Atlas setup requires Prisma or Mongoose ORM. Cannot use --db-setup mongodb-atlas with --orm ${effectiveOrm}.`,
|
||||||
process.exit(1);
|
);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
} else if (dbSetup === "neon") {
|
||||||
|
if (effectiveDatabase !== "postgres") {
|
||||||
|
consola.fatal(
|
||||||
|
`Neon PostgreSQL setup requires PostgreSQL. Cannot use --db-setup neon with --database ${effectiveDatabase}.`,
|
||||||
|
);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
const includesNuxt = effectiveFrontend?.includes("nuxt");
|
const includesNuxt = effectiveFrontend?.includes("nuxt");
|
||||||
const includesSvelte = effectiveFrontend?.includes("svelte");
|
const includesSvelte = effectiveFrontend?.includes("svelte");
|
||||||
@@ -580,13 +584,13 @@ function processAndValidateFlags(
|
|||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.addons.includes("husky") && !config.addons.includes("biome")) {
|
if (config.addons.includes("husky") && !config.addons.includes("biome")) {
|
||||||
consola.warn(
|
consola.warn(
|
||||||
"Husky addon is recommended to be used with Biome for lint-staged configuration.",
|
"Husky addon is recommended to be used with Biome for lint-staged configuration.",
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
config.addons = [...new Set(config.addons)];
|
||||||
}
|
}
|
||||||
config.addons = [...new Set(config.addons)];
|
|
||||||
}
|
|
||||||
|
|
||||||
const onlyNativeFrontend =
|
const onlyNativeFrontend =
|
||||||
effectiveFrontend &&
|
effectiveFrontend &&
|
||||||
|
|||||||
@@ -29,6 +29,14 @@
|
|||||||
"db:studio": {
|
"db:studio": {
|
||||||
"cache": false,
|
"cache": false,
|
||||||
"persistent": true
|
"persistent": true
|
||||||
|
},
|
||||||
|
"db:migrate": {
|
||||||
|
"cache": false,
|
||||||
|
"persistent": true
|
||||||
|
},
|
||||||
|
"db:generate": {
|
||||||
|
"cache": false,
|
||||||
|
"persistent": true
|
||||||
}
|
}
|
||||||
{{/unless}}{{/if}}
|
{{/unless}}{{/if}}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ export const auth = betterAuth({
|
|||||||
{{#if (eq database "postgres")}}provider: "postgresql"{{/if}}
|
{{#if (eq database "postgres")}}provider: "postgresql"{{/if}}
|
||||||
{{#if (eq database "sqlite")}}provider: "sqlite"{{/if}}
|
{{#if (eq database "sqlite")}}provider: "sqlite"{{/if}}
|
||||||
{{#if (eq database "mysql")}}provider: "mysql"{{/if}}
|
{{#if (eq database "mysql")}}provider: "mysql"{{/if}}
|
||||||
|
{{#if (eq database "mongodb")}}provider: "mongodb"{{/if}}
|
||||||
}),
|
}),
|
||||||
trustedOrigins: [
|
trustedOrigins: [
|
||||||
process.env.CORS_ORIGIN || "",{{#if (includes frontend "native")}}
|
process.env.CORS_ORIGIN || "",{{#if (includes frontend "native")}}
|
||||||
@@ -67,7 +68,7 @@ import { expo } from "@better-auth/expo";
|
|||||||
import { client } from "../db";
|
import { client } from "../db";
|
||||||
|
|
||||||
export const auth = betterAuth({
|
export const auth = betterAuth({
|
||||||
database: mongodbAdapter(client.db()),
|
database: mongodbAdapter(client),
|
||||||
trustedOrigins: [
|
trustedOrigins: [
|
||||||
process.env.CORS_ORIGIN || "",{{#if (includes frontend "native")}}
|
process.env.CORS_ORIGIN || "",{{#if (includes frontend "native")}}
|
||||||
"my-better-t-app://",{{/if}}
|
"my-better-t-app://",{{/if}}
|
||||||
@@ -104,4 +105,4 @@ export const auth = betterAuth({
|
|||||||
plugins: [expo()]
|
plugins: [expo()]
|
||||||
{{/if~}}
|
{{/if~}}
|
||||||
});
|
});
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
import mongoose from 'mongoose';
|
import mongoose from "mongoose";
|
||||||
|
|
||||||
await mongoose.connect(process.env.DATABASE_URL || "");
|
await mongoose.connect(process.env.DATABASE_URL || "").catch((error) => {
|
||||||
const client = mongoose.connection.getClient();
|
console.log("Error connecting to database:", error);
|
||||||
|
});
|
||||||
|
|
||||||
export { client };
|
const client = mongoose.connection.getClient().db("myDB");
|
||||||
|
|
||||||
|
export { client };
|
||||||
|
|||||||
@@ -23,7 +23,11 @@ export const todoRouter = {
|
|||||||
}),
|
}),
|
||||||
|
|
||||||
toggle: publicProcedure
|
toggle: publicProcedure
|
||||||
|
{{#if (eq database "mongodb")}}
|
||||||
|
.input(z.object({ id: z.string(), completed: z.boolean() }))
|
||||||
|
{{else}}
|
||||||
.input(z.object({ id: z.number(), completed: z.boolean() }))
|
.input(z.object({ id: z.number(), completed: z.boolean() }))
|
||||||
|
{{/if}}
|
||||||
.handler(async ({ input }) => {
|
.handler(async ({ input }) => {
|
||||||
await prisma.todo.update({
|
await prisma.todo.update({
|
||||||
where: { id: input.id },
|
where: { id: input.id },
|
||||||
@@ -33,7 +37,11 @@ export const todoRouter = {
|
|||||||
}),
|
}),
|
||||||
|
|
||||||
delete: publicProcedure
|
delete: publicProcedure
|
||||||
|
{{#if (eq database "mongodb")}}
|
||||||
|
.input(z.object({ id: z.string() }))
|
||||||
|
{{else}}
|
||||||
.input(z.object({ id: z.number() }))
|
.input(z.object({ id: z.number() }))
|
||||||
|
{{/if}}
|
||||||
.handler(async ({ input }) => {
|
.handler(async ({ input }) => {
|
||||||
await prisma.todo.delete({
|
await prisma.todo.delete({
|
||||||
where: { id: input.id },
|
where: { id: input.id },
|
||||||
@@ -69,7 +77,11 @@ export const todoRouter = router({
|
|||||||
}),
|
}),
|
||||||
|
|
||||||
toggle: publicProcedure
|
toggle: publicProcedure
|
||||||
|
{{#if (eq database "mongodb")}}
|
||||||
|
.input(z.object({ id: z.string(), completed: z.boolean() }))
|
||||||
|
{{else}}
|
||||||
.input(z.object({ id: z.number(), completed: z.boolean() }))
|
.input(z.object({ id: z.number(), completed: z.boolean() }))
|
||||||
|
{{/if}}
|
||||||
.mutation(async ({ input }) => {
|
.mutation(async ({ input }) => {
|
||||||
try {
|
try {
|
||||||
return await prisma.todo.update({
|
return await prisma.todo.update({
|
||||||
@@ -85,7 +97,11 @@ export const todoRouter = router({
|
|||||||
}),
|
}),
|
||||||
|
|
||||||
delete: publicProcedure
|
delete: publicProcedure
|
||||||
|
{{#if (eq database "mongodb")}}
|
||||||
|
.input(z.object({ id: z.string() }))
|
||||||
|
{{else}}
|
||||||
.input(z.object({ id: z.number() }))
|
.input(z.object({ id: z.number() }))
|
||||||
|
{{/if}}
|
||||||
.mutation(async ({ input }) => {
|
.mutation(async ({ input }) => {
|
||||||
try {
|
try {
|
||||||
return await prisma.todo.delete({
|
return await prisma.todo.delete({
|
||||||
|
|||||||
@@ -22,10 +22,12 @@
|
|||||||
"lucide-react": "^0.503.0",
|
"lucide-react": "^0.503.0",
|
||||||
"motion": "^12.8.0",
|
"motion": "^12.8.0",
|
||||||
"next": "15.3.1",
|
"next": "15.3.1",
|
||||||
|
"next-themes": "^0.4.6",
|
||||||
"nuqs": "^2.4.3",
|
"nuqs": "^2.4.3",
|
||||||
"react": "^19.1.0",
|
"react": "^19.1.0",
|
||||||
"react-dom": "^19.1.0",
|
"react-dom": "^19.1.0",
|
||||||
"react-tweet": "^3.2.2",
|
"react-tweet": "^3.2.2",
|
||||||
|
"sonner": "^2.0.3",
|
||||||
"tailwind-merge": "^3.2.0"
|
"tailwind-merge": "^3.2.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -4,6 +4,7 @@ import { Poppins } from "next/font/google";
|
|||||||
import { NuqsAdapter } from "nuqs/adapters/next/app";
|
import { NuqsAdapter } from "nuqs/adapters/next/app";
|
||||||
import type { ReactNode } from "react";
|
import type { ReactNode } from "react";
|
||||||
import "./global.css";
|
import "./global.css";
|
||||||
|
import { Toaster } from "@/components/ui/sonner";
|
||||||
|
|
||||||
const poppins = Poppins({
|
const poppins = Poppins({
|
||||||
subsets: ["latin"],
|
subsets: ["latin"],
|
||||||
@@ -96,6 +97,7 @@ export default function Layout({ children }: { children: ReactNode }) {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<NuqsAdapter>{children}</NuqsAdapter>
|
<NuqsAdapter>{children}</NuqsAdapter>
|
||||||
|
<Toaster />
|
||||||
</RootProvider>
|
</RootProvider>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
25
apps/web/src/components/ui/sonner.tsx
Normal file
25
apps/web/src/components/ui/sonner.tsx
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { useTheme } from "next-themes";
|
||||||
|
import { Toaster as Sonner, type ToasterProps } from "sonner";
|
||||||
|
|
||||||
|
const Toaster = ({ ...props }: ToasterProps) => {
|
||||||
|
const { theme = "system" } = useTheme();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Sonner
|
||||||
|
theme={theme as ToasterProps["theme"]}
|
||||||
|
className="toaster group"
|
||||||
|
style={
|
||||||
|
{
|
||||||
|
"--normal-bg": "var(--popover)",
|
||||||
|
"--normal-text": "var(--popover-foreground)",
|
||||||
|
"--normal-border": "var(--border)",
|
||||||
|
} as React.CSSProperties
|
||||||
|
}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export { Toaster };
|
||||||
6
bun.lock
6
bun.lock
@@ -14,7 +14,7 @@
|
|||||||
},
|
},
|
||||||
"apps/cli": {
|
"apps/cli": {
|
||||||
"name": "create-better-t-stack",
|
"name": "create-better-t-stack",
|
||||||
"version": "2.5.1",
|
"version": "2.6.1",
|
||||||
"bin": {
|
"bin": {
|
||||||
"create-better-t-stack": "dist/index.js",
|
"create-better-t-stack": "dist/index.js",
|
||||||
},
|
},
|
||||||
@@ -54,10 +54,12 @@
|
|||||||
"lucide-react": "^0.503.0",
|
"lucide-react": "^0.503.0",
|
||||||
"motion": "^12.8.0",
|
"motion": "^12.8.0",
|
||||||
"next": "15.3.1",
|
"next": "15.3.1",
|
||||||
|
"next-themes": "^0.4.6",
|
||||||
"nuqs": "^2.4.3",
|
"nuqs": "^2.4.3",
|
||||||
"react": "^19.1.0",
|
"react": "^19.1.0",
|
||||||
"react-dom": "^19.1.0",
|
"react-dom": "^19.1.0",
|
||||||
"react-tweet": "^3.2.2",
|
"react-tweet": "^3.2.2",
|
||||||
|
"sonner": "^2.0.3",
|
||||||
"tailwind-merge": "^3.2.0",
|
"tailwind-merge": "^3.2.0",
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
@@ -1524,6 +1526,8 @@
|
|||||||
|
|
||||||
"slice-ansi": ["slice-ansi@5.0.0", "", { "dependencies": { "ansi-styles": "^6.0.0", "is-fullwidth-code-point": "^4.0.0" } }, "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ=="],
|
"slice-ansi": ["slice-ansi@5.0.0", "", { "dependencies": { "ansi-styles": "^6.0.0", "is-fullwidth-code-point": "^4.0.0" } }, "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ=="],
|
||||||
|
|
||||||
|
"sonner": ["sonner@2.0.3", "", { "peerDependencies": { "react": "^18.0.0 || ^19.0.0 || ^19.0.0-rc", "react-dom": "^18.0.0 || ^19.0.0 || ^19.0.0-rc" } }, "sha512-njQ4Hht92m0sMqqHVDL32V2Oun9W1+PHO9NDv9FHfJjT3JT22IG4Jpo3FPQy+mouRKCXFWO+r67v6MrHX2zeIA=="],
|
||||||
|
|
||||||
"source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="],
|
"source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="],
|
||||||
|
|
||||||
"source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="],
|
"source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="],
|
||||||
|
|||||||
Reference in New Issue
Block a user