Shō en Hasshii en anderen zijn met Supabase aan de slag met allerlei leuke ontwikkelprojecten. Anders dan bij de traditionele watervalmethode horen we flarden over functionele eisen die vanuit de UI worden gedefinieerd, en ik wil zeker niet achterblijven!
Daarom maak ik in dit artikel een eenvoudige notitie-app en leg ik stap voor stap uit hoe je Supabase en Prisma koppelt om gegevens in de database op te slaan. Ik ga Gemini CLI ook gewoon gebruiken, dat wordt spannend!
Omgeving: Next.js
Omdat ik de databasefunctionaliteit via de API wil gebruiken, en niet de Auth-, Realtime- en RLS-functies van Supabase, kies ik voor Prisma. Je kunt databasetabellen behandelen als JavaScript- of TypeScript-objecten, waardoor de code aansluit bij wat frontend-ontwikkelaars gewend zijn.
Prisma
Prisma ORM is een ORM-bibliotheek (Object-Relational Mapping) die je kunt gebruiken met TypeScript en JavaScript.
Kort gezegd is het een tool waarmee je databasebewerkingen uitvoert met methoden die je in je programmeertaal definieert, zonder SQL te schrijven.
Bovendien genereert Prisma types automatisch op basis van het databaseschema. Als je dan probeert te werken met een kolom die niet in de database bestaat of met gegevens van een verkeerd type, merk je dat meteen door een compileerfout!
Supabase
Supabase is een full-stack backendservice die veel aandacht krijgt als open-source alternatief voor Firebase.
- Hoge schaalbaarheid en betrouwbaarheid, gebouwd op een PostgreSQL-database
- Automatische meldingen bij gegevenswijzigingen via realtime database-functionaliteit
- Ondersteunt diverse authenticatiemethoden (e-mail/wachtwoord, social login, telefoonverificatie en meer)
- Efficiënt beheer van grote bestanden met de bestandsopslagfunctie
- Snelle ontwikkeling dankzij automatisch gegenereerde RESTful API's en GraphQL API's
- Uitgebreide ontwikkelaarstools en SDK's, eenvoudig in te stellen en te implementeren
Omdat de integratie met Supabase belangrijk is, laat ik de vormgeving maken met Gemini CLI. Het is ontzettend handig, echt verbazingwekkend! Gelukkig gebruikt ons bedrijf Google Workspace!
Ik wil een notitiefunctie maken met Supabase en Prisma. Maak voor nu alsjeblieft een page.tsx aan.
Oké, dan wil ik dat de tekst die in de textarea is ingevoerd, na het klikken op de Save Memo-knop, als lijstitem wordt toegevoegd onder Your Memos. Kun je dat zo inrichten?
De weergave ziet er zo uit en is in orde! De ingevoerde inhoud wordt nu aan de onderstaande lijst toegevoegd. Omdat dit alleen via JavaScript-events wordt afgehandeld, verdwijnen de lijstitems echter bij het herladen van de pagina.
Om de ingevoerde inhoud op te slaan, gebruiken we een database!
Maak eerst een nieuw project aan in Supabase.
Maak het project aan via de knop "New Project". Noteer het Database password, want dit is nodig om via Prisma verbinding te maken.
Koppel vervolgens Prisma.
npm install prisma --save-dev
npx prisma init
Na het invoeren van deze commando's wordt Prisma geïnstalleerd en verschijnt de map prisma.
Vervang in het .env-bestand de DATABASE_URL door de verbindings-URL van Supabase. Vul op de plaats van [YOUR-PASSWORD] het Database password in dat je eerder in Supabase hebt ingesteld.
DATABASE_URL="postgresql://postgres.odoaingwnxkhkeujwhtp:[YOUR-PASSWORD]@aws-1-ap-northeast-1.pooler.supabase.com:5432/postgres"
Beschrijf vervolgens het schema (de structuur van de database) in /prisma/schema.prisma.
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
model Memo {
id Int @id @default(autoincrement())
content String
createdAt DateTime @default(now())
}
model ○○ kun je vrij benoemen.
Nadat je het schema hebt geschreven, voer je de migratie uit.
npx prisma migrate dev --name init
Er wordt een migration.sql-bestand gegenereerd en in Supabase worden de datatabellen aangemaakt.
API maken voor de verbinding met Supabase
Om de ingevoerde waarden in Supabase op te slaan, maken we een API voor de verbinding.
Installeer Prisma Client in het project.
npm install @prisma/client
Verbinding maken met Supabase
/libs/prisma.ts
import { PrismaClient } from "@prisma/client";
const Prisma = new PrismaClient(); //インスタンス化
export const main = async () => {
try {
await Prisma.$connect();
} catch (error) {
return Error("DB接続に失敗しました");
}
};
API
/api/memos/route.ts
import { NextResponse } from "next/server";
import { prisma } from '@/lib/prisma';
export const GET = async (req: Request, res: NextResponse) => {
try {
await main();
const memos = await Prisma.memo.findMany();
return NextResponse.json(memos);
} catch (error) {
return NextResponse.json("エラーが発生しました");
} finally {
await Prisma.$disconnect();
}
};
export const POST = async (req: Request, res: NextResponse) => {
const { content } = await req.json();
try {
await main();
const memos = await Prisma.memo.**create**({
data: {
content: content,
},
});
return NextResponse.json(memos);
} catch (error) {
return NextResponse.json("エラーが発生しました");
} finally {
await Prisma.$disconnect();
}
};
De GET-functie is een API die alle records uit de database ophaalt. Met de methode findMany() haalt hij alle records op die aan de voorwaarde voldoen. In Prisma.memo.findMany() is "memo" de naam van het schema.
De POST-functie is een API waarmee gegevens aan de database worden toegevoegd. Dit doe je met create().
Er zijn ook methoden voor verwijderen, bijwerken en meer. Zelfs zonder SQL-kennis kun je deze gebruiken op een manier die vertrouwd aanvoelt als JavaScript.
Het basiswerk is nu klaar.
Plaats daarna de API die we net hebben geschreven in page.tsx om deze te integreren.
'use client';
import React, { useState, useEffect } from 'react';
interface Memo {
id: number;
content: string;
createdAt: string;
}
export default function MemoApp() {
const [memos, setMemos] = useState<Memo[]>([]);
const [newMemo, setNewMemo] = useState('');
const fetchMemos = async () => {
const response = await fetch('/api/memos');
const data = await response.json();
setMemos(data);
};
useEffect(() => {
fetchMemos();
}, []);
const handleSaveMemo = async (e: React.FormEvent) => {
e.preventDefault();
if (newMemo.trim() !== '') {
await fetch('/api/memos', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ content: newMemo }),
});
setNewMemo('');
fetchMemos();
}
};
return (
<div className="bg-white min-h-screen">
<div className="max-w-2xl mx-auto px-4 py-16">
<header className="text-center mb-12">
<h1 className="text-5xl font-extrabold text-gray-900">Memo</h1>
</header>
<main>
<div className="mb-12">
<form onSubmit={handleSaveMemo}>
<textarea
className="w-full p-4 text-gray-800 bg-gray-100 rounded-lg border-2 border-gray-200 focus:outline-none focus:ring-2 focus:ring-gray-400 focus:border-transparent transition"
placeholder="Create a new memo..."
rows={3}
value={newMemo}
onChange={(e) => setNewMemo(e.target.value)}
></textarea>
<div className="flex justify-end mt-4">
<button
type="submit"
className="px-6 py-2 bg-gray-800 text-white font-semibold rounded-lg hover:bg-gray-900 transition"
>
Save Memo
</button>
</div>
</form>
</div>
<section>
<h2 className="text-3xl font-bold text-gray-800 mb-6">Your Memos</h2>
<div className="space-y-4">
{memos.length > 0 ? (
memos.map((memo) => (
<div key={memo.id} className="bg-gray-50 p-6 rounded-lg shadow-sm">
<p className="text-gray-700">{memo.content}</p>
</div>
))
) : (
<div className="text-center text-gray-500">
<p>No memos yet. Add one above!</p>
</div>
)}
</div>
</section>
</main>
</div>
</div>
);
}
Het is opgeslagen in Supabase!
Dit keer hebben we grotendeels op Gemini vertrouwd om het te maken, maar als we een database gebruiken om waarden op te slaan, wordt het bereik van de functies en apps die je kunt bouwen ook groter!
Ik dacht eerst dat backend best ingewikkeld zou zijn, maar met een GUI-tool kun je de database makkelijk beheren, en de drempel om een database te koppelen is flink lager geworden!
Yes!
Ik ben voornamelijk bezig met markup en frontend-ontwikkeling met JavaScript, React en Next.js. Ik ben blij wanneer een site waar ik aan heb meegewerkt succesvol live gaat! Mijn hobby's zijn gitaar spelen. Ik hou van katten en geroosterde zoete aardappel 🐱🍠
ひらっち
Frontend-engineer / in dienst sinds 2022