Belajar NextJs Terbaru 16.0.1 Error Saat install Prisma dan prisma-client next-auth bcrypt
Belajar belum selesai dan khatam nextjs 14, 15 sudah naik aja tuh versi next js ke versi NextJs Terbaru 16.0.1, saat saya coba pakai nextjs 16.0.1 ada Error Saat install Prisma dan prisma-client next-aut bcrypt, namun saat installasi file-file berikut, muncul error. 
 
Selanjutnya kita buat folder 
$ npm install @prisma/client next-auth bcrypt npm error code ERESOLVE npm error ERESOLVE unable to resolve dependency tree npm error npm error While resolving: my-app@0.1.0 npm error Found: nodemailer@6.10.1 npm error node_modules/nodemailer npm error peerOptional nodemailer@"^6.8.0" from @auth/core@0.34.2 npm error node_modules/@auth/core npm error peerOptional @auth/core@"0.34.2" from next-auth@4.24.12 npm error node_modules/next-auth npm error next-auth@"*" from the root project npm error npm error Could not resolve dependency: npm error peerOptional nodemailer@"^7.0.7" from next-auth@4.24.12 npm error node_modules/next-auth npm error next-auth@"*" from the root project npm error npm error Fix the upstream dependency conflict, or retry npm error this command with --force or --legacy-peer-deps npm error to accept an incorrect (and potentially broken) dependency resolution. npm error npm error npm error For a full report see: npm error C:\Users\HAPESINDO\AppData\Local\npm-cache\_logs\2025-10-29T03_37_18_844Z-eresolve-report.txt npm error A complete log of this run can be found in: C:\Users\HAPESINDO\AppData\Local\npm-cache\_logs\2025-10-29T03_37_18_844Z-debug-0.logSolusinya, Install nodemailer@latest
  $ npm install nodemailer@latest
added 1 package, and audited 428 packages in 3s 172 packages are looking for funding run `npm fund` for details found 0 vulnerabilitiesJika sudah lanjutkan install Prisma dan prisma-client next-aut bcrypt dengan perintah install menggunakan npm
npm install @prisma/client next-auth bcrypt
Setelah itu install prisma dengan perintah
npm install prisma --save-dev
Dan jalankan init prisma untuk membuat file .env dan generate prisma 
npx prisma init
Kalau kita ingin cek versi Next.js dan NextAuth  biar cocok sepenuhnya (versi yang stabil dan tanpa konflik).
Kita bisa buat perintah seperti ini 
  npm list next next-auth nodemailer
Selanjutnya ada error saat generate prisma dev 
npx prisma migrate dev --name init  error seperti ini $ npx prisma migrate dev Failed to load config file "D:\laragon\www\my-app\prisma.config.ts" as a TypeScript/JavaScript module. Error: Error: Cannot find module 'prisma/config' Require stack: - D:\laragon\www\my-app\prisma.config.tsSolusinya tambahkan ini
import "dotenv/config";di file
prisma.config.tslalu generete ulang. Jangan lupa install juga prisma
npm install prisma
Berikut beberapa settingan untuk membuat crud dengan Nextjs 16.0.1, file schema.prismaberikut isinya :
 generator client {
  provider = "prisma-client"
  output   = "../app/generated/prisma"
}
datasource db {
  provider = "mysql"
  url      = env("DATABASE_URL")
}
model Product {
  id         Int       @id @default(autoincrement())
  nama       String
  harga      Float
  stok       Int
  image      String?
  createdAt  DateTime  @default(now())
  updatedAt  DateTime  @updatedAt
}
File prisma.config.tsberikut isinya setelah di tambahin code
import "dotenv/config";
import { defineConfig, env } from "prisma/config";
import "dotenv/config";
export default defineConfig({
  schema: "prisma/schema.prisma",
  migrations: {
    path: "prisma/migrations",
  },
  engine: "classic",
  datasource: {
    url: env("DATABASE_URL"),
  },
});
  
Langkah selanjutnya membuat server action, dimana file ProductAction.tsxkita buat didalam directory
/app/actionsdengan isi
"use server"
import prisma from "@/lib/prisma"
import { revalidatePath } from "next/cache"
import fs from "fs";
import path from "path";
import { redirect } from "next/navigation";
async function saveImage(file: File): Promise<string> {
    const uploadDir = path.join(process.cwd(), "public", "uploads");
    if (!fs.existsSync(uploadDir)) fs.mkdirSync(uploadDir, { recursive: true });
    const buffer = Buffer.from(await file.arrayBuffer());
    const filename = Date.now() + "-" + file.name.replace(/\s+/g, "_");
    const filepath = path.join(uploadDir, filename);
    await fs.promises.writeFile(filepath, buffer);
    return "/uploads/" + filename;
}
export async function addProduct(formData: FormData) {
    const nama = formData.get("nama") as string;
    const harga = Number(formData.get("harga"));
    const stok = Number(formData.get("stok"));
    const file = formData.get("image") as File | null;
    let imagePath: string | undefined;
    if (file && file.size > 0) {
        imagePath = await saveImage(file);
    }
    if (!nama || isNaN(harga) || isNaN(stok)) {
        throw new Error("data tidak valid")
    }
    await prisma.product.create({
        data: { nama, harga, stok, image: imagePath }
    })
    revalidatePath("/products")
    redirect("/products");
}
// Edit Produk
export async function updateProduct(id: number, formData: FormData) {
    const nama = formData.get("nama") as string;
    const harga = Number(formData.get("harga"));
    const stok = Number(formData.get("stok"));
    const file = formData.get("image") as File | null;
    // const description = formData.get("description") as string | null;
    let imagePath: string | undefined;
    if (file && file.size > 0) {
        imagePath = await saveImage(file);
    }
    await prisma.product.update({
        where: { id },
        data: { nama, harga, stok, ...(imagePath ? { image: imagePath } : {}) },
    });
    revalidatePath("/products");
    redirect("/products");
}
//Hapus Produk
export async function deleteProduct(id: number) {
    await prisma.product.delete({ where: { id } });
    revalidatePath("/products");
    redirect("/products");
}
/app/productsyang didalamnya ada file
page.tsxdengan isi berikut
 
                import prisma from "@/lib/prisma";import DeleteButton from "@/componens/DeleteButton";import Link from "next/link";
export default async function ProductPage() {
    const products = await prisma.product.findMany({        orderBy: { id: "desc" }    })
    return (        <div>            <div className="flex justify-between mb-6">                <h1 className="text-2xl font-bold">Daftar Produk</h1>                <Link href="/products/new" className="bg-blue-600 text-white px-4 py-2 rounded-lg">+ Tambah Produk</Link>            </div>
            <table className="w-full border-collapse border">                <thead>                    <tr className="bg-gray-100">                        <th className="border p-2">#</th>                        <th className="border p-2">Gambar</th>                        <th className="border p-2">Nama</th>                        <th className="border p-2">Harga</th>                        <th className="border p-2">Stok</th>                        <th className="border p-2">Action</th>                    </tr>                </thead>                <tbody>                    {products.map((p: { id: number, nama: string, harga: number, stok: number, image?: string | null }, index) => (                        <tr key={p.id}>                            <td className="border p-2">{index + 1}</td>                            <td className="border p-2">                                {p.image ? (                                    <img                                        src={p.image}                                        alt={p.nama}                                        className="w-16 h-16 object-cover rounded"                                    />                                ) : (                                    <span className="text-gray-400 italic">No image</span>                                )}                            </td>                            <td className="border p-2">{p.nama}</td>                            <td className="border p-2">Rp.{p.harga.toLocaleString("id-ID")}</td>                            <td className="border p-2">{p.stok}</td>                            <td className="border p-2">                                <div className="flex justify-center gap-2">                                    <Link                                        href={`/products/edit/${p.id}`}                                        className="bg-blue-500 text-white px-2 py-1 rounded"                                    >                                        Edit                                    </Link>                                    <DeleteButton id={p.id} />                                </div>
                            </td>                        </tr>                    ))}                </tbody>            </table>        </div>    )}
Komentar
Posting Komentar