Konfiguracja Prismy 7 z PostgreSQL w projekcie TypeScript Node.js
Popraw częste błędy konfiguracji Prisma 7 w TypeScript, od problemów z adresami URL typu string lub undefined po problemy z rootDir, oraz skonfiguruj PostgreSQL za pomocą adaptera sterownika pg.
Źródła: I Wasted 4 Hours Setting Up Prisma — Here’s How You Should Set Up Prisma v7
Korzystanie z szybkiego startu Prismy w zwykłym projekcie TypeScript Node.js często kończy się lawiną błędów kompilatora, zanim zostanie wykonywana choćby jedna zapytanie. Problemy nie leżą w modelach; wynikają one z sposobu, w jaki kompilator TypeScript, nowy plik konfiguracyjny Prismy oraz wygenerowany klient współpracują z tradycyjną strukturą src/dist. Ten przewodnik wyjaśnia trzy błędy, z którymi najczęściej się spotykasz, dlaczego one występują, oraz krok po kroku opisuje konfigurację z PostgreSQL, która pozwala na czystą kompilację. Prisma 7 zmieniła kilka domyślnych ustawień, więc sprawdź aktualną dokumentację Prismy w celu poznania informacji o zmianach, które mogły nastąpić od czasu napisania tego tekstu.
Trzy błędy, które psują nową konfigurację
Adres połączenia wpisany jako ciąg znaków lub nieokreślony
W pliku prisma.config.ts adres bazy danych jest zazwyczaj odczytywany za pomocą process.env.DATABASE_URL. TypeScript typizuje każdą zmienną środowiskową jako string | undefined, ponieważ nic nie gwarantuje, że zostanie ustawiona w czasie wykonywania. Konfiguracja oczekuje zwykłej wartości typu string, dlatego kompilator odrzuca to przypisanie.
prisma.config.ts poza katalogiem głównym
Zwykły projekt TypeScript ustawia rootDir na src, a outDir na dist. Prisma tworzy plik prisma.config.ts w korzeniu projektu, a kompilator domyślnie uwzględnia każdy znaleziony plik .ts. Następnie zgłasza błąd, że plik znajdujący się poza rootDir jest częścią programu. Przeniesienie konfiguracji do src uspokoiłoby błąd, ale to niewłaściwe rozwiązanie: src służy do przechowywania kodu aplikacji, takiego jak trasy, kontrolery i mechanizmy dostępu do danych, a nie konfiguracji narzędzi.
Klient wygenerowany poza katalogiem głównym
To samo dzieje się z wygenerowanym klientem. Jeśli Prisma zapisuje go do katalogu generated/prisma w korzeniu projektu, kompilator ponownie znajduje pliki TypeScript poza katalogiem rootDir. Umieszczenie wygenerowanego kodu w katalogu src również jest złym rozwiązaniem, ponieważ jest to wynik budowania z polecenia prisma generate, a nie kod źródłowy, który samodzielnie zarządzasz.
Jeśli te problemy pozostaną nierozwiązane, uniemożliwią uruchomienie projektu. Kolejnym irytującym skutkiem jest to, że skompilowany JavaScript z pliku prisma.config.ts może znaleźć się poza katalogiem dist, co zagraża uporządkowaniu repozytorium. Naprawianie błędów pojedynczo często prowadzi do powstawania nowych, dlatego warto naprawić całą konfigurację projektu.
Krok 1: utworzenie projektu i zainstalowanie zależności
Zacznij od pustego projektu TypeScript. Zainstaluj kompilator, tsx do bezpośredniego uruchamiania TypeScript oraz definicje typów Node, a następnie utwórz plik tsconfig.json:
npm init
npm install typescript tsx @types/node --save-dev
npx tsc --init
Następnie zainstaluj Prisma. CLI oraz definicje typów pg to zależności rozwojowe; klient, adapter sterownika PostgreSQL, sterownik pg oraz dotenv to zależności w czasie wykonywania:
npm install prisma @types/pg --save-dev
npm install @prisma/client @prisma/adapter-pg pg dotenv
Pakiet @prisma/adapter-pg ma tu kluczowe znaczenie. W Prisma 7 klient komunikuje się z bazą danych za pośrednictwem adaptera sterownika JavaScript, więc przekazuje mu skonfigurowane połączenie pg zamiast polegać wyłącznie na adreście URL w schemacie.
Krok 2: konfiguracja modułów ES i układu kompilatora
Oznacz pakiet jako moduł ES w pliku package.json:
{
"type": "module"
}
Następnie ustaw katalogi źródłowe i wyjściowe w pliku tsconfig.json, a także utwórz folder src:
"rootDir": "./src",
"outDir": "./dist",
Krok 3: inicjalizacja Prisma
Zainstaluj i uruchom CLI raz (sam w sobie wyświetli dostępne polecenia i potwierdzi poprawność instalacji):
npx prisma
Potem inicjalizuj Prisma dla PostgreSQL:
npx prisma init --datasource-provider postgresql --output ../generated/prisma
To tworzy plik prisma.config.ts, folder prisma zawierający plik schema.prisma, oraz plik .env z adresem URL bazy danych. Flaga --output określa miejsce, w którym zostanie utworzony klient; krok 4 ponownie omawia tę decyzję. Właśnie po tym kroku pojawiają się opisane powyżej błędy.
Krok 4: poprawa konfiguracji
Trzy precyzyjne zmiany rozwiązują wszystkie trzy błędy.
Czytanie adresu URL za pomocą narzędzia env w Prismie
Zastąp zawartość pliku prisma.config.ts poniższym tekstem. Jest to plik w języku TypeScript, mimo że fragment kodu jest inaczej oznaczony.
import "dotenv/config";
import type { PrismaConfig } from "prisma";
import { env } from "prisma/config";
export default {
schema: "prisma/schema.prisma",
migrations: {
path: "prisma/migrations",
seed: "tsx prisma/seed.ts",
},
datasource: {
url: env("DATABASE_URL"),
},
} satisfies PrismaConfig;
Na co zwrócić uwagę:
import "dotenv/config"ładuje plik.envprzed tym, jak cokolwiek go odczyta. Prisma 7 już nie ładuje go automatycznie w takim ustawieniu.env("DATABASE_URL")z modułuprisma/configzwraca wartość typustringi wywołuje wyraźny błąd, jeśli zmienna jest nieobecna, co eliminuje błąd typustring | undefined.satisfies PrismaConfigsprawdza typ obiektu bez jego rozszerzania.- Konfiguracja określa również miejsce przechowywania schematu i migracji oraz komendę służącą do wypełnienia bazy danych.
Ogranicz zawartość, którą obejmuje kompilator
Dodaj wpis include na końcu pliku tsconfig.json:
"include": ["src"],
To mówi kompilatorowi, aby budował tylko pliki znajdujące się w katalogu src. Prisma CLI nadal czyta sam plik prisma.config.ts, ale tsc przestaje traktować go jako część programu, dzięki czemu błąd rootDir znika i żaden niepotrzebny kod JavaScript nie jest wypisywany poza katalogiem dist.
Wygeneruj klienta do folderu node_modules
Następnie edytuj plik schema.prisma, aby generator nie miał żadnej specjalnej ścieżki wyjściowej:
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
Bез użycia pola output generator prisma-client-js zapisuje klienta do katalogu node_modules, więc nic z wygenerowanego nie znajduje się w korzeniu projektu, a błąd dotyczący rootDir znika. Fragment kodu kończy się po definicji provider dla źródła danych; zamknij blok nawiasem kwadratowym. W Prisma 7 adres URL do połączenia znajduje się w pliku prisma.config.ts, a nie w schemacie.
Należy pamiętać, że to jest kompromis. Nowszy generator prisma-client od Prismy jest zaprojektowany z myślą o wyraźnie określonym katalogu wyjściowym, natomiast prisma-client-js to starszy generator. Jeśli zdecydujesz się na nowszą wersję, umieść jej pliki wyjściowe poza katalogiem src i wyklucz je z procesu kompilacji za pomocą opcji include, jak opisano powyżej.
Krok 5: dodanie adresu URL bazy danych i migracja
Umieść swój ciąg połączenia w pliku .env. Podany poniżej wartość jest tylko zastępczą; użyj własnej bazy danych i nigdy nie przechowuj prawdziwych wartości:
DATABASE_URL="postgresql://johndoe:randompassword@localhost:5432/mydb?schema=public"
Zdefiniuj swoje modele w pliku schema.prisma, a następnie utwórz i zastosuj pierwszą migrację:
npx prisma migrate dev --name init
Krok 6: generowanie klienta
Stwórz typowany klient na podstawie schematu:
npx prisma generate
Zrób to ponownie za każdym razem, gdy zmieni się schemat, aby typy pozostały zsynchronizowane z twoimi modelami.
Krok 7: utworzenie wspólnej instancji Prisma
Stwórz plik src/lib/prisma.ts, który będzie przechowywał jeden klient dla całego aplikacji. Tworzy on adapter do PostgreSQL na podstawie ciągu połączenia i przekazuje go do PrismaClient. Ten kod jest również napisany w TypeScript:
import "dotenv/config";
import { PrismaPg } from "@prisma/adapter-pg";
import { PrismaClient } from "../../node_modules/@prisma/client/index.js";
const connectionString = `${process.env.DATABASE_URL}`;
const adapter = new PrismaPg({ connectionString });
const prisma = new PrismaClient({ adapter });
export default prisma;
Klient jest importowany za pomocą wyraźnej ścieżki względnej do folderu node_modules:
import { PrismaClient } from "../../node_modules/@prisma/client/index.js";
Ta ścieżka działa, ponieważ klient został utworzony w katalogu node_modules na etapie 4. W większości konfiguracji prosty wskaźnik @prisma/client odnosi się do tego samego pakietu, więc spróbuj go najpierw; ucieknij się do wyraźnej ścieżki tylko wtedy, gdy wymagają tego ustawienia rozwiązywania modułów.
Jedna z pułapek w tym fragmencie: umieszczenie process.env.DATABASE_URL w ciągu szablonowym zamienia brakującą wartość na dosłowny tekst "undefined", co później powoduje mylący błąd połączenia. Krótka weryfikacja, która rzuca błąd przy braku zmiennej, sprawia, że problemy stają się oczywiste.
Teraz imporтуj tę instancję tam, gdzie potrzebujesz dostępu do bazy danych, np. w kontrolerach lub usługach, i wykonywaj przez nią zapytania CRUD. Utrzymywanie jednego wspólnego klienta pozwala uniknąć otwierania nowej puli połączeń dla każdego pliku.
Główne wnioski
- Większość błędów konfiguracji Prisma 7 w TypeScript wynika z reguł
rootDirkompilatora, a nie samego Prisma. - Użyj funkcji
env()z modułuprisma/configw połączeniu zdotenv/config, aby uzyskać poprawnie skategoryzowany adres bazy danych załadowany w sposób wyraźny. - Ogranicz działanie
tscza pomocą parametru"include": ["src"], aby pliki narzędziowe i kod wygenerowany nie trafiały do procesu budowania. - Zachowaj wygenerowane klienty poza katalogiem
src, albo w folderzenode_modules, albo w osobnym katalogu wykluczonym z procesu budowania. - Stwórz jeden wspólny obiekt
PrismaClientz adapteremPrismaPgi sprawdź ciąg połączenia podczas uruchamiania.
Jeśli używasz Next.js zamiast zwykłej usługi Node.js, naszy przewodnik po konfiguracji Prismy 7 w projekcie Next.js 16 z TypeScript omawia szczegóły specyficzne dla tego frameworku.